summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Makefile.am50
-rw-r--r--src/common/Makefile.nmake20
-rw-r--r--src/common/OpenBSD_malloc_Linux.c2
-rw-r--r--src/common/address.c74
-rw-r--r--src/common/address.h20
-rw-r--r--src/common/aes.c1021
-rw-r--r--src/common/aes.h4
-rw-r--r--src/common/compat.c195
-rw-r--r--src/common/compat.h35
-rw-r--r--src/common/compat_libevent.c200
-rw-r--r--src/common/compat_libevent.h28
-rw-r--r--src/common/container.c20
-rw-r--r--src/common/container.h28
-rw-r--r--src/common/crypto.c419
-rw-r--r--src/common/crypto.h9
-rw-r--r--src/common/log.c31
-rw-r--r--src/common/mempool.c3
-rw-r--r--src/common/torgzip.c4
-rw-r--r--src/common/torint.h9
-rw-r--r--src/common/torlog.h5
-rw-r--r--src/common/tortls.c1200
-rw-r--r--src/common/tortls.h49
-rw-r--r--src/common/util.c1344
-rw-r--r--src/common/util.h150
-rw-r--r--src/config/geoip9764
-rw-r--r--src/or/Makefile.am120
-rw-r--r--src/or/Makefile.nmake28
-rw-r--r--src/or/buffers.c865
-rw-r--r--src/or/buffers.h38
-rw-r--r--src/or/circuitbuild.c1038
-rw-r--r--src/or/circuitbuild.h55
-rw-r--r--src/or/circuitlist.c35
-rw-r--r--src/or/circuituse.c361
-rw-r--r--src/or/circuituse.h12
-rw-r--r--src/or/command.c682
-rw-r--r--src/or/config.c2128
-rw-r--r--src/or/config.h37
-rw-r--r--src/or/connection.c1673
-rw-r--r--src/or/connection.h73
-rw-r--r--src/or/connection_edge.c879
-rw-r--r--src/or/connection_edge.h40
-rw-r--r--src/or/connection_or.c1087
-rw-r--r--src/or/connection_or.h33
-rw-r--r--src/or/control.c490
-rw-r--r--src/or/control.h6
-rw-r--r--src/or/cpuworker.c23
-rw-r--r--src/or/directory.c454
-rw-r--r--src/or/directory.h9
-rw-r--r--src/or/dirserv.c445
-rw-r--r--src/or/dirserv.h35
-rw-r--r--src/or/dirvote.c61
-rw-r--r--src/or/dirvote.h8
-rw-r--r--src/or/dns.c25
-rw-r--r--src/or/dnsserv.c73
-rw-r--r--src/or/dnsserv.h4
-rw-r--r--src/or/eventdns.c31
-rw-r--r--src/or/geoip.c344
-rw-r--r--src/or/geoip.h10
-rw-r--r--src/or/hibernate.c62
-rw-r--r--src/or/hibernate.h26
-rw-r--r--src/or/main.c551
-rw-r--r--src/or/main.h12
-rw-r--r--src/or/microdesc.c297
-rw-r--r--src/or/microdesc.h18
-rw-r--r--src/or/networkstatus.c467
-rw-r--r--src/or/networkstatus.h40
-rw-r--r--src/or/nodelist.c758
-rw-r--r--src/or/nodelist.h60
-rw-r--r--src/or/ntmain.c3
-rw-r--r--src/or/or.h872
-rw-r--r--src/or/policies.c245
-rw-r--r--src/or/policies.h22
-rw-r--r--src/or/relay.c225
-rw-r--r--src/or/relay.h9
-rw-r--r--src/or/rendclient.c189
-rw-r--r--src/or/rendclient.h2
-rw-r--r--src/or/rendcommon.c9
-rw-r--r--src/or/rendcommon.h4
-rw-r--r--src/or/rendservice.c82
-rw-r--r--src/or/rendservice.h2
-rw-r--r--src/or/rephist.c750
-rw-r--r--src/or/rephist.h17
-rw-r--r--src/or/router.c319
-rw-r--r--src/or/router.h48
-rw-r--r--src/or/routerlist.c1374
-rw-r--r--src/or/routerlist.h104
-rw-r--r--src/or/routerparse.c70
-rw-r--r--src/or/routerparse.h1
-rw-r--r--src/or/status.c115
-rw-r--r--src/or/status.h10
-rw-r--r--src/or/transports.c1248
-rw-r--r--src/or/transports.h106
-rw-r--r--src/test/Makefile.am28
-rw-r--r--src/test/bench.c327
-rw-r--r--src/test/test-child.c40
-rw-r--r--src/test/test.c890
-rw-r--r--src/test/test.h3
-rw-r--r--src/test/test_addr.c193
-rw-r--r--src/test/test_crypto.c128
-rw-r--r--src/test/test_dir.c100
-rw-r--r--src/test/test_microdesc.c233
-rw-r--r--src/test/test_pt.c147
-rw-r--r--src/test/test_util.c592
-rw-r--r--src/test/tinytest.c17
-rw-r--r--src/test/tinytest_demo.c14
-rw-r--r--src/test/tinytest_macros.h39
-rw-r--r--src/tools/Makefile.am18
-rw-r--r--src/tools/tor-fw-helper/Makefile.am38
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-natpmp.c233
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-natpmp.h47
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-upnp.c189
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-upnp.h43
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.c396
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.h57
-rw-r--r--src/tools/tor-gencert.c4
-rw-r--r--src/tools/tor-resolve.c2
-rw-r--r--src/win32/orconfig.h11
117 files changed, 28325 insertions, 9467 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 6952591d67..2920e73d2e 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -1,7 +1,7 @@
noinst_LIBRARIES = libor.a libor-crypto.a libor-event.a
-EXTRA_DIST = common_sha1.i sha256.c
+EXTRA_DIST = common_sha1.i sha256.c Makefile.nmake
#CFLAGS = -Wall -Wpointer-arith -O2
@@ -11,18 +11,54 @@ else
libor_extra_source=
endif
-libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
- memarea.c di_ops.c procmon.c util_codedigest.c $(libor_extra_source)
-libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
+libor_a_SOURCES = \
+ address.c \
+ compat.c \
+ container.c \
+ di_ops.c \
+ log.c \
+ memarea.c \
+ mempool.c \
+ procmon.c \
+ util.c \
+ util_codedigest.c \
+ $(libor_extra_source)
+
+libor_crypto_a_SOURCES = \
+ aes.c \
+ crypto.c \
+ torgzip.c \
+ tortls.c
+
libor_event_a_SOURCES = compat_libevent.c
-noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h procmon.h
+noinst_HEADERS = \
+ address.h \
+ aes.h \
+ ciphers.inc \
+ compat.h \
+ compat_libevent.h \
+ container.h \
+ crypto.h \
+ di_ops.h \
+ ht.h \
+ memarea.h \
+ mempool.h \
+ procmon.h \
+ strlcat.c \
+ strlcpy.c \
+ torgzip.h \
+ torint.h \
+ torlog.h \
+ tortls.h \
+ tortls_states.h \
+ util.h
common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
if test "@SHA1SUM@" != none; then \
- @SHA1SUM@ $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \
+ (cd "$(srcdir)" && @SHA1SUM@ $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \
elif test "@OPENSSL@" != none; then \
- @OPENSSL@ sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \
+ (cd "$(srcdir)" && @OPENSSL@ sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \
else \
rm common_sha1.i; \
touch common_sha1.i; \
diff --git a/src/common/Makefile.nmake b/src/common/Makefile.nmake
new file mode 100644
index 0000000000..c8b5988666
--- /dev/null
+++ b/src/common/Makefile.nmake
@@ -0,0 +1,20 @@
+all: libor.lib libor-crypto.lib libor-event.lib
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include
+
+LIBOR_OBJECTS = address.obj compat.obj container.obj di_ops.obj \
+ log.obj memarea.obj mempool.obj procmon.obj util.obj \
+ util_codedigest.obj
+
+LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj torgzip.obj tortls.obj
+
+LIBOR_EVENT_OBJECTS = compat_libevent.obj
+
+libor.lib: $(LIBOR_OBJECTS)
+ lib $(LIBOR_OBJECTS) /out:libor.lib
+
+libor-crypto.lib: $(LIBOR_CRYPTO_OBJECTS)
+ lib $(LIBOR_CRYPTO_OBJECTS) /out:libor-crypto.lib
+
+libor-event.lib: $(LIBOR_EVENT_OBJECTS)
+ lib $(LIBOR_EVENT_OBJECTS) /out:libor-event.lib
diff --git a/src/common/OpenBSD_malloc_Linux.c b/src/common/OpenBSD_malloc_Linux.c
index 19dac77657..445135c6bb 100644
--- a/src/common/OpenBSD_malloc_Linux.c
+++ b/src/common/OpenBSD_malloc_Linux.c
@@ -1236,7 +1236,7 @@ imalloc(size_t size)
ptralloc = 1;
size = malloc_pagesize;
}
- if ((size + malloc_pagesize) < size) { /* Check for overflow */
+ if (size > SIZE_MAX - malloc_pagesize) { /* Check for overflow */
result = NULL;
errno = ENOMEM;
} else if (size <= malloc_maxsize)
diff --git a/src/common/address.c b/src/common/address.c
index 7fc7301051..f40e428cce 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -52,6 +52,13 @@
#include <string.h>
#include <assert.h>
+/* tor_addr_is_null() and maybe other functions rely on AF_UNSPEC being 0 to
+ * work correctly. Bail out here if we've found a platform where AF_UNSPEC
+ * isn't 0. */
+#if AF_UNSPEC != 0
+#error We rely on AF_UNSPEC being 0. Let us know about your platform, please!
+#endif
+
/** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a
* sockaddr object in *<b>sa_out</b> of object size <b>len</b>. If not enough
* room is available in sa_out, or on error, return 0. On success, return
@@ -343,22 +350,28 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
* brackets.
*/
const char *
-tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate)
+tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
{
const char *ptr;
tor_assert(addr && dest);
switch (tor_addr_family(addr)) {
case AF_INET:
- if (len<3)
+ /* Shortest addr x.x.x.x + \0 */
+ if (len < 8)
return NULL;
- ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len);
+ ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len);
break;
case AF_INET6:
+ /* Shortest addr [ :: ] + \0 */
+ if (len < (3 + (decorate ? 2 : 0)))
+ return NULL;
+
if (decorate)
ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest+1, len-2);
else
ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest, len);
+
if (ptr && decorate) {
*dest = '[';
memcpy(dest+strlen(dest), "]", 2);
@@ -384,7 +397,7 @@ tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate)
* IPv4 or IPv6 address too.
*/
int
-tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address,
+tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int family, int accept_regular)
{
if (!strcasecmpend(address, ".in-addr.arpa")) {
@@ -455,7 +468,7 @@ tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address,
if (accept_regular) {
tor_addr_t tmp;
- int r = tor_addr_from_str(&tmp, address);
+ int r = tor_addr_parse(&tmp, address);
if (r < 0)
return 0;
if (r != family && family != AF_UNSPEC)
@@ -470,13 +483,17 @@ tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address,
return 0;
}
-/** Convert <b>addr</b> to an in-addr.arpa name or a .ip6.arpa name, and store
- * the result in the <b>outlen</b>-byte buffer at <b>out</b>. Return 0 on
- * success, -1 on failure. */
+/** Convert <b>addr</b> to an in-addr.arpa name or a .ip6.arpa name,
+ * and store the result in the <b>outlen</b>-byte buffer at
+ * <b>out</b>. Return the number of chars written to <b>out</b>, not
+ * including the trailing \0, on success. Returns -1 on failure. */
int
-tor_addr_to_reverse_lookup_name(char *out, size_t outlen,
- const tor_addr_t *addr)
+tor_addr_to_PTR_name(char *out, size_t outlen,
+ const tor_addr_t *addr)
{
+ tor_assert(out);
+ tor_assert(addr);
+
if (addr->family == AF_INET) {
uint32_t a = tor_addr_to_ipv4h(addr);
@@ -499,7 +516,7 @@ tor_addr_to_reverse_lookup_name(char *out, size_t outlen,
*cp++ = '.';
}
memcpy(cp, "ip6.arpa", 9); /* 8 characters plus NUL */
- return 0;
+ return 32 * 2 + 8;
}
return -1;
}
@@ -964,6 +981,19 @@ fmt_addr(const tor_addr_t *addr)
return "???";
}
+/** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4
+ * addresses. Also not thread-safe, also clobbers its return buffer on
+ * repeated calls. */
+const char *
+fmt_addr32(uint32_t addr)
+{
+ static char buf[INET_NTOA_BUF_LEN];
+ struct in_addr in;
+ in.s_addr = htonl(addr);
+ tor_inet_ntoa(&in, buf, sizeof(buf));
+ return buf;
+}
+
/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
* may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by
* square brackets.
@@ -971,7 +1001,7 @@ fmt_addr(const tor_addr_t *addr)
* Return an address family on success, or -1 if an invalid address string is
* provided. */
int
-tor_addr_from_str(tor_addr_t *addr, const char *src)
+tor_addr_parse(tor_addr_t *addr, const char *src)
{
char *tmp = NULL; /* Holds substring if we got a dotted quad. */
int result;
@@ -999,7 +1029,7 @@ tor_addr_from_str(tor_addr_t *addr, const char *src)
* address as needed, and put the result in <b>addr_out</b> and (optionally)
* <b>port_out</b>. Return 0 on success, negative on failure. */
int
-tor_addr_port_parse(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
+tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
{
const char *port;
tor_addr_t addr;
@@ -1135,6 +1165,20 @@ is_internal_IP(uint32_t ip, int for_listening)
return tor_addr_is_internal(&myaddr, for_listening);
}
+/** Given an address of the form "host:port", try to divide it into its host
+ * ane port portions, setting *<b>address_out</b> to a newly allocated string
+ * holding the address portion and *<b>port_out</b> to the port (or 0 if no
+ * port is given). Return 0 on success, -1 on failure. */
+int
+tor_addr_port_split(int severity, const char *addrport,
+ char **address_out, uint16_t *port_out)
+{
+ tor_assert(addrport);
+ tor_assert(address_out);
+ tor_assert(port_out);
+ return addr_port_lookup(severity, addrport, address_out, NULL, port_out);
+}
+
/** Parse a string of the form "host[:port]" from <b>addrport</b>. If
* <b>address</b> is provided, set *<b>address</b> to a copy of the
* host portion of the string. If <b>addr</b> is provided, try to
@@ -1146,7 +1190,7 @@ is_internal_IP(uint32_t ip, int for_listening)
* Return 0 on success, -1 on failure.
*/
int
-parse_addr_port(int severity, const char *addrport, char **address,
+addr_port_lookup(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out)
{
const char *colon;
@@ -1156,7 +1200,7 @@ parse_addr_port(int severity, const char *addrport, char **address,
tor_assert(addrport);
- colon = strchr(addrport, ':');
+ colon = strrchr(addrport, ':');
if (colon) {
_address = tor_strndup(addrport, colon-addrport);
_port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL);
diff --git a/src/common/address.h b/src/common/address.h
index 9a7656f69b..bc225a65ea 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -127,6 +127,7 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out);
char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
const char *fmt_addr(const tor_addr_t *addr);
+const char * fmt_addr32(uint32_t addr);
int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
/** Flag to specify how to do a comparison between addresses. In an "exact"
@@ -148,24 +149,24 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
unsigned int tor_addr_hash(const tor_addr_t *addr);
int tor_addr_is_v4(const tor_addr_t *addr);
-int tor_addr_is_internal(const tor_addr_t *ip, int for_listening) ATTR_PURE;
+int tor_addr_is_internal(const tor_addr_t *ip, int for_listening);
/** Longest length that can be required for a reverse lookup name. */
/* 32 nybbles, 32 dots, 8 characters of "ip6.arpa", 1 NUL: 73 characters. */
#define REVERSE_LOOKUP_NAME_BUF_LEN 73
-int tor_addr_to_reverse_lookup_name(char *out, size_t outlen,
+int tor_addr_to_PTR_name(char *out, size_t outlen,
const tor_addr_t *addr);
-int tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address,
+int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int family, int accept_regular);
-int tor_addr_port_parse(const char *s, tor_addr_t *addr_out,
+int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
uint16_t *port_out);
int tor_addr_parse_mask_ports(const char *s,
tor_addr_t *addr_out, maskbits_t *mask_out,
uint16_t *port_min_out, uint16_t *port_max_out);
-const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int len,
+const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
int decorate);
-int tor_addr_from_str(tor_addr_t *addr, const char *src);
+int tor_addr_parse(tor_addr_t *addr, const char *src);
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr);
/** Set <b>dest</b> to the IPv4 address encoded in <b>v4addr</b> in host
@@ -180,9 +181,12 @@ void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
int tor_addr_is_null(const tor_addr_t *addr);
int tor_addr_is_loopback(const tor_addr_t *addr);
+int tor_addr_port_split(int severity, const char *addrport,
+ char **address_out, uint16_t *port_out);
+
/* IPv4 helpers */
-int is_internal_IP(uint32_t ip, int for_listening) ATTR_PURE;
-int parse_addr_port(int severity, const char *addrport, char **address,
+int is_internal_IP(uint32_t ip, int for_listening);
+int addr_port_lookup(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out);
int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
diff --git a/src/common/aes.c b/src/common/aes.c
index c2fdeb594a..cec6899817 100644
--- a/src/common/aes.c
+++ b/src/common/aes.c
@@ -6,11 +6,7 @@
/**
* \file aes.c
- * \brief Implements the AES cipher (with 128-bit keys and blocks),
- * and a counter-mode stream cipher on top of AES. This code is
- * taken from the main Rijndael distribution. (We include this
- * because many people are running older versions of OpenSSL without
- * AES support.)
+ * \brief Implements a counter-mode stream cipher on top of AES.
**/
#include "orconfig.h"
@@ -18,120 +14,39 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <openssl/engine.h>
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+/* See comments about which counter mode implementation to use below. */
+#include <openssl/modes.h>
+#define USE_OPENSSL_CTR
+#endif
#include "compat.h"
#include "aes.h"
#include "util.h"
#include "torlog.h"
-/* We have 3 strategies for getting AES: Via OpenSSL's AES_encrypt function,
- * via OpenSSL's EVP_EncryptUpdate function, or via the built-in AES
- * implementation below. */
-
-/** Defined iff we're using OpenSSL's AES functions for AES. */
-#undef USE_OPENSSL_AES
-/** Defined iff we're using OpenSSL's EVP code for AES. */
-#undef USE_OPENSSL_EVP
-/** Defined iff we're using Tor's internal AES implementation, defined
- * below. */
-#undef USE_BUILTIN_AES
-
-/* Figure out our CPU type. We use this to pick an AES implementation.
- * Macros are as listed at http://predef.sourceforge.net/prearch.html
- */
-#if (defined(i386) || defined(__i386__) || defined(__i386) || defined(_X86_) \
- || defined(_M_IX86) || defined(__THW_INTEL__) || defined(__I86__))
-# define CPU_IS_X86
-#elif (defined(__amd64__) || defined(__amd64) || \
- defined(__x86_64__) || defined(__x86_64) || \
- defined(_M_X64))
-# define CPU_IS_X86_64
-#elif (defined(__ia64__) || defined(__ia64) || defined(_IA64) || \
- defined(_M_IA64))
-# define CPU_IS_IA64
-#elif (defined(__sparc__) || defined(__sparc))
-# define CPU_IS_SPARC
-#elif (defined(__arm__) || defined (__TARGET_ARCH_ARM))
-# define CPU_IS_ARM
+#ifdef ANDROID
+/* Android's OpenSSL seems to have removed all of its Engine support. */
+#define DISABLE_ENGINES
#endif
-/* Here we pick which to use, if none is force-defined. See
- * http://archives.seul.org/or/dev/Feb-2007/msg00045.html
- * for a summary of the most recent benchmarking results that led to this
- * nutty decision tree.
-*/
-#if (!defined(USE_BUILTIN_AES) && \
- !defined(USE_OPENSSL_AES) && \
- !defined(USE_OPENSSL_EVP))
-
-/* OpenSSL 0.9.7 was the first to support AES. It was slower than our
- * built-in implementation.
- * OpenSSL 0.9.8 added assembly implementations for i386 and ia64.
- * Either the i386 stuff isn't used for x86-64, or it isn't faster.
- * OpenSSL 0.9.9 (not yet out) has added assembly implementations for
- * x86_64 (aka amd64), sparc9, and arm
+/* We have 2 strategies for getting AES: Via OpenSSL's AES_encrypt function,
+ * via OpenSSL's EVP_EncryptUpdate function.
*
- * Note: the "f" at the end of OpenSSL version numbers below means
- * "release". */
-# if defined(CPU_IS_X86) || defined(CPU_IS_IA64)
-# if OPENSSL_VERSION_NUMBER >= 0x0090800fL
-# define USE_OPENSSL_AES
-# endif
-# endif
-
-# if defined(CPU_IS_X86_64) || defined(CPU_IS_ARM) || defined(CPU_IS_SPARC)
-# if OPENSSL_VERSION_NUMBER >= 0x0090900fL
-# define USE_OPENSSL_AES
-# endif
-# endif
-
-/* Otherwise, use the built-in implementation below. */
-# ifndef USE_OPENSSL_AES
-# define USE_BUILTIN_AES
-# endif
-#endif /* endif need to pick a method */
-
-/* Include OpenSSL headers as needed. */
-#ifdef USE_OPENSSL_AES
-# include <openssl/aes.h>
-#endif
-#ifdef USE_OPENSSL_EVP
-# include <openssl/evp.h>
-#endif
-
-/* Figure out which AES optimizations to use. */
-#ifdef USE_BUILTIN_AES
-/** If this is defined, we take advantage of the fact that AES treats its
- * input as a set of 4 32-bit words, so that there is no need to encode and
- * decode the 128-bit counter before every block encryption */
-# define USE_RIJNDAEL_COUNTER_OPTIMIZATION
-# if 0 && (defined(__powerpc__) || defined(__powerpc64__))
-/* XXXX do more experimentation before concluding this is actually
- * a good idea. */
-# define FULL_UNROLL
-# endif
-#endif
-
-/*======================================================================*/
-/* From rijndael-alg-fst.h */
-
-typedef uint64_t u64;
-typedef uint32_t u32;
-typedef uint8_t u8;
-
-#ifdef USE_BUILTIN_AES
-#define MAXNR 14
+ * If there's any hardware acceleration in play, we want to be using EVP_* so
+ * we can get it. Otherwise, we'll want AES_*, which seems to be about 5%
+ * faster than indirecting through the EVP layer.
+ */
-static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/],
- const u8 cipherKey[], int keyBits);
-#ifdef USE_RIJNDAEL_COUNTER_OPTIMIZATION
-static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr,
- u32 ctr3, u32 ctr2,
- u32 ctr1, u32 ctr0, u8 ct[16]);
-#else
-static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr,
- const u8 pt[16], u8 ct[16]);
-#endif
-#endif
+/* We have 2 strategies for counter mode: use our own, or use OpenSSL's.
+ *
+ * Here we have a counter mode that's faster than the one shipping with
+ * OpenSSL pre-1.0 (by about 10%!). But OpenSSL 1.0.0 added a counter mode
+ * implementation faster than the one here (by about 7%). So we pick which
+ * one to used based on the Openssl version above.
+ */
/*======================================================================*/
/* Interface to AES code, and counter implementation */
@@ -139,42 +54,78 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr,
/** Implements an AES counter-mode cipher. */
struct aes_cnt_cipher {
/** This next element (however it's defined) is the AES key. */
-#if defined(USE_OPENSSL_EVP)
- EVP_CIPHER_CTX key;
-#elif defined(USE_OPENSSL_AES)
- AES_KEY key;
-#else
- u32 rk[4*(MAXNR+1)];
- int nr;
-#endif
+ union {
+ EVP_CIPHER_CTX evp;
+ AES_KEY aes;
+ } key;
-#if !defined(WORDS_BIGENDIAN) || defined(USE_RIJNDAEL_COUNTER_OPTIMIZATION)
+#if !defined(WORDS_BIGENDIAN) && !defined(USE_OPENSSL_CTR)
#define USING_COUNTER_VARS
/** These four values, together, implement a 128-bit counter, with
* counter0 as the low-order word and counter3 as the high-order word. */
- u32 counter3;
- u32 counter2;
- u32 counter1;
- u32 counter0;
+ uint32_t counter3;
+ uint32_t counter2;
+ uint32_t counter1;
+ uint32_t counter0;
#endif
-#ifndef USE_RIJNDAEL_COUNTER_OPTIMIZATION
-#define USING_COUNTER_BUFS
union {
/** The counter, in big-endian order, as bytes. */
- u8 buf[16];
+ uint8_t buf[16];
/** The counter, in big-endian order, as big-endian words. Note that
* on big-endian platforms, this is redundant with counter3...0,
* so we just use these values instead. */
- u32 buf32[4];
+ uint32_t buf32[4];
} ctr_buf;
-#endif
+
/** The encrypted value of ctr_buf. */
- u8 buf[16];
+ uint8_t buf[16];
/** Our current stream position within buf. */
- u8 pos;
+#ifdef USE_OPENSSL_CTR
+ unsigned int pos;
+#else
+ uint8_t pos;
+#endif
+
+ /** True iff we're using the evp implementation of this cipher. */
+ uint8_t using_evp;
};
+/** True if we should prefer the EVP implementation for AES, either because
+ * we're testing it or because we have hardware acceleration configured */
+static int should_use_EVP = 0;
+
+/** Check whether we should use the EVP interface for AES. If <b>force_val</b>
+ * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP
+ * if there is an engine enabled for aes-ecb. */
+int
+evaluate_evp_for_aes(int force_val)
+{
+ ENGINE *e;
+
+ if (force_val >= 0) {
+ should_use_EVP = force_val;
+ return 0;
+ }
+#ifdef DISABLE_ENGINES
+ should_use_EVP = 0;
+#else
+ e = ENGINE_get_cipher_engine(NID_aes_128_ecb);
+
+ if (e) {
+ log_notice(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.",
+ ENGINE_get_name(e));
+ should_use_EVP = 1;
+ } else {
+ log_notice(LD_CRYPTO, "No AES engine found; using AES_* functions.");
+ should_use_EVP = 0;
+ }
+#endif
+
+ return 0;
+}
+
+#ifndef USE_OPENSSL_CTR
#if !defined(USING_COUNTER_VARS)
#define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)])
#else
@@ -194,25 +145,16 @@ _aes_fill_buf(aes_cnt_cipher_t *cipher)
* 3) changing the counter position was not trivial, last time I looked.
* None of these issues are insurmountable in principle.
*/
-#if defined(USE_BUILTIN_AES) && defined(USE_RIJNDAEL_COUNTER_OPTIMIZATION)
- rijndaelEncrypt(cipher->rk, cipher->nr,
- cipher->counter3, cipher->counter2,
- cipher->counter1, cipher->counter0, cipher->buf);
-#else
-#if defined(USE_OPENSSL_EVP)
- {
+ if (cipher->using_evp) {
int outl=16, inl=16;
- EVP_EncryptUpdate(&cipher->key, cipher->buf, &outl,
+ EVP_EncryptUpdate(&cipher->key.evp, cipher->buf, &outl,
cipher->ctr_buf.buf, inl);
+ } else {
+ AES_encrypt(cipher->ctr_buf.buf, cipher->buf, &cipher->key.aes);
}
-#elif defined(USE_OPENSSL_AES)
- AES_encrypt(cipher->ctr_buf.buf, cipher->buf, &cipher->key);
-#else
- rijndaelEncrypt(cipher->rk, cipher->nr, cipher->ctr_buf.buf, cipher->buf);
-#endif
-#endif
}
+#endif
/**
* Return a newly allocated counter-mode AES128 cipher implementation.
@@ -232,33 +174,37 @@ aes_new_cipher(void)
void
aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits)
{
-#if defined(USE_OPENSSL_EVP)
- const EVP_CIPHER *c;
- switch (key_bits) {
- case 128: c = EVP_aes_128_ecb(); break;
- case 192: c = EVP_aes_192_ecb(); break;
- case 256: c = EVP_aes_256_ecb(); break;
- default: tor_assert(0);
+ if (should_use_EVP) {
+ const EVP_CIPHER *c;
+ switch (key_bits) {
+ case 128: c = EVP_aes_128_ecb(); break;
+ case 192: c = EVP_aes_192_ecb(); break;
+ case 256: c = EVP_aes_256_ecb(); break;
+ default: tor_assert(0);
+ }
+ EVP_EncryptInit(&cipher->key.evp, c, (const unsigned char*)key, NULL);
+ cipher->using_evp = 1;
+ } else {
+ AES_set_encrypt_key((const unsigned char *)key, key_bits, &cipher->key.aes);
+ cipher->using_evp = 0;
}
- EVP_EncryptInit(&cipher->key, c, (const unsigned char*)key, NULL);
-#elif defined(USE_OPENSSL_AES)
- AES_set_encrypt_key((const unsigned char *)key, key_bits, &(cipher->key));
-#else
- cipher->nr = rijndaelKeySetupEnc(cipher->rk, (const unsigned char*)key,
- key_bits);
-#endif
+
#ifdef USING_COUNTER_VARS
cipher->counter0 = 0;
cipher->counter1 = 0;
cipher->counter2 = 0;
cipher->counter3 = 0;
#endif
-#ifdef USING_COUNTER_BUFS
+
memset(cipher->ctr_buf.buf, 0, sizeof(cipher->ctr_buf.buf));
-#endif
cipher->pos = 0;
+
+#ifdef USE_OPENSSL_CTR
+ memset(cipher->buf, 0, sizeof(cipher->buf));
+#else
_aes_fill_buf(cipher);
+#endif
}
/** Release storage held by <b>cipher</b>
@@ -268,14 +214,14 @@ aes_free_cipher(aes_cnt_cipher_t *cipher)
{
if (!cipher)
return;
-#ifdef USE_OPENSSL_EVP
- EVP_CIPHER_CTX_cleanup(&cipher->key);
-#endif
+ if (cipher->using_evp) {
+ EVP_CIPHER_CTX_cleanup(&cipher->key.evp);
+ }
memset(cipher, 0, sizeof(aes_cnt_cipher_t));
tor_free(cipher);
}
-#if defined(USING_COUNTER_VARS) && defined(USING_COUNTER_BUFS)
+#if defined(USING_COUNTER_VARS)
#define UPDATE_CTR_BUF(c, n) STMT_BEGIN \
(c)->ctr_buf.buf32[3-(n)] = htonl((c)->counter ## n); \
STMT_END
@@ -283,6 +229,18 @@ aes_free_cipher(aes_cnt_cipher_t *cipher)
#define UPDATE_CTR_BUF(c, n)
#endif
+#ifdef USE_OPENSSL_CTR
+/* Helper function to use EVP with openssl's counter-mode wrapper. */
+static void evp_block128_fn(const uint8_t in[16],
+ uint8_t out[16],
+ const void *key)
+{
+ EVP_CIPHER_CTX *ctx = (void*)key;
+ int inl=16, outl=16;
+ EVP_EncryptUpdate(ctx, out, &outl, in, inl);
+}
+#endif
+
/** Encrypt <b>len</b> bytes from <b>input</b>, storing the result in
* <b>output</b>. Uses the key in <b>cipher</b>, and advances the counter
* by <b>len</b> bytes as it encrypts.
@@ -291,11 +249,29 @@ void
aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
char *output)
{
-
- /* XXXX This function is up to 5% of our runtime in some profiles;
- * we should look into unrolling some of the loops; taking advantage
- * of alignment, using a bigger buffer, and so on. Not till after 0.1.2.x,
- * though. */
+#ifdef USE_OPENSSL_CTR
+ if (cipher->using_evp) {
+ /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If
+ * it weren't disabled, it might be better just to use that.
+ */
+ CRYPTO_ctr128_encrypt((const unsigned char *)input,
+ (unsigned char *)output,
+ len,
+ &cipher->key.evp,
+ cipher->ctr_buf.buf,
+ cipher->buf,
+ &cipher->pos,
+ evp_block128_fn);
+ } else {
+ AES_ctr128_encrypt((const unsigned char *)input,
+ (unsigned char *)output,
+ len,
+ &cipher->key.aes,
+ cipher->ctr_buf.buf,
+ cipher->buf,
+ &cipher->pos);
+ }
+#else
int c = cipher->pos;
if (PREDICT_UNLIKELY(!len)) return;
@@ -318,6 +294,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
UPDATE_CTR_BUF(cipher, 0);
_aes_fill_buf(cipher);
}
+#endif
}
/** Encrypt <b>len</b> bytes from <b>input</b>, storing the results in place.
@@ -327,11 +304,9 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
void
aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
{
-
- /* XXXX This function is up to 5% of our runtime in some profiles;
- * we should look into unrolling some of the loops; taking advantage
- * of alignment, using a bigger buffer, and so on. Not till after 0.1.2.x,
- * though. */
+#ifdef USE_OPENSSL_CTR
+ aes_crypt(cipher, data, len, data);
+#else
int c = cipher->pos;
if (PREDICT_UNLIKELY(!len)) return;
@@ -354,6 +329,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
UPDATE_CTR_BUF(cipher, 0);
_aes_fill_buf(cipher);
}
+#endif
}
/** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value
@@ -368,705 +344,10 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv)
cipher->counter0 = ntohl(get_uint32(iv+12));
#endif
cipher->pos = 0;
-#ifndef USE_RIJNDAEL_COUNTER_OPTIMIZATION
memcpy(cipher->ctr_buf.buf, iv, 16);
-#endif
+#ifndef USE_OPENSSL_CTR
_aes_fill_buf(cipher);
-}
-
-#ifdef USE_BUILTIN_AES
-/*======================================================================*/
-/* From rijndael-alg-fst.c */
-
-/**
- * rijndael-alg-fst.c
- *
- * @version 3.0 (December 2000)
- *
- * Optimized ANSI C code for the Rijndael cipher (now AES)
- *
- * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
- * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
- * @author Paulo Barreto <paulo.barreto@terra.com.br>
- *
- * This code is hereby placed in the public domain.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
-Te0[x] = S [x].[02, 01, 01, 03];
-Te1[x] = S [x].[03, 02, 01, 01];
-Te2[x] = S [x].[01, 03, 02, 01];
-Te3[x] = S [x].[01, 01, 03, 02];
-Te4[x] = S [x].[01, 01, 01, 01];
-
-Td0[x] = Si[x].[0e, 09, 0d, 0b];
-Td1[x] = Si[x].[0b, 0e, 09, 0d];
-Td2[x] = Si[x].[0d, 0b, 0e, 09];
-Td3[x] = Si[x].[09, 0d, 0b, 0e];
-Td4[x] = Si[x].[01, 01, 01, 01];
-*/
-
-static const u32 Te0[256] = {
- 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
- 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
- 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
- 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
- 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
- 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
- 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
- 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
- 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
- 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
- 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
- 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
- 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
- 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
- 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
- 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
- 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
- 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
- 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
- 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
- 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
- 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
- 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
- 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
- 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
- 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
- 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
- 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
- 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
- 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
- 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
- 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
- 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
- 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
- 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
- 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
- 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
- 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
- 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
- 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
- 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
- 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
- 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
- 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
- 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
- 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
- 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
- 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
- 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
- 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
- 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
- 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
- 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
- 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
- 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
- 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
- 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
- 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
- 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
- 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
- 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
- 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
- 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
- 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
-};
-static const u32 Te1[256] = {
- 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
- 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
- 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
- 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
- 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
- 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
- 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
- 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
- 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
- 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
- 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
- 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
- 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
- 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
- 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
- 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
- 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
- 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
- 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
- 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
- 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
- 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
- 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
- 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
- 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
- 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
- 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
- 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
- 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
- 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
- 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
- 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
- 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
- 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
- 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
- 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
- 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
- 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
- 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
- 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
- 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
- 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
- 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
- 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
- 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
- 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
- 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
- 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
- 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
- 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
- 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
- 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
- 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
- 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
- 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
- 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
- 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
- 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
- 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
- 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
- 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
- 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
- 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
- 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
-};
-static const u32 Te2[256] = {
- 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
- 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
- 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
- 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
- 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
- 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
- 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
- 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
- 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
- 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
- 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
- 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
- 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
- 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
- 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
- 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
- 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
- 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
- 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
- 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
- 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
- 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
- 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
- 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
- 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
- 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
- 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
- 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
- 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
- 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
- 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
- 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
- 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
- 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
- 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
- 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
- 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
- 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
- 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
- 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
- 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
- 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
- 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
- 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
- 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
- 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
- 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
- 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
- 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
- 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
- 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
- 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
- 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
- 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
- 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
- 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
- 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
- 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
- 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
- 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
- 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
- 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
- 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
- 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
-};
-static const u32 Te3[256] = {
-
- 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
- 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
- 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
- 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
- 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
- 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
- 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
- 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
- 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
- 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
- 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
- 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
- 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
- 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
- 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
- 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
- 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
- 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
- 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
- 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
- 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
- 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
- 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
- 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
- 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
- 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
- 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
- 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
- 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
- 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
- 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
- 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
- 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
- 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
- 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
- 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
- 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
- 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
- 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
- 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
- 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
- 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
- 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
- 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
- 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
- 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
- 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
- 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
- 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
- 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
- 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
- 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
- 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
- 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
- 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
- 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
- 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
- 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
- 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
- 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
- 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
- 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
- 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
- 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
-};
-static const u32 Te4[256] = {
- 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
- 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
- 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
- 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
- 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
- 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
- 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
- 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
- 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
- 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
- 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
- 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
- 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
- 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
- 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
- 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
- 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
- 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
- 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
- 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
- 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
- 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
- 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
- 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
- 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
- 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
- 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
- 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
- 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
- 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
- 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
- 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
- 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
- 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
- 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
- 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
- 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
- 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
- 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
- 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
- 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
- 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
- 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
- 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
- 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
- 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
- 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
- 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
- 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
- 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
- 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
- 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
- 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
- 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
- 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
- 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
- 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
- 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
- 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
- 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
- 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
- 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
- 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
- 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
-};
-
-static const u32 rcon[] = {
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000,
- 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
-};
-
-#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
-
-#ifdef _MSC_VER
-#define GETU32(p) SWAP(*((u32 *)(p)))
-#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
-#else
-#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
-#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
#endif
-
-/**
- * Expand the cipher key into the encryption key schedule.
- *
- * @return the number of rounds for the given cipher key size.
- */
-static int
-rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)
-{
- int i = 0;
- u32 temp;
-
- rk[0] = GETU32(cipherKey );
- rk[1] = GETU32(cipherKey + 4);
- rk[2] = GETU32(cipherKey + 8);
- rk[3] = GETU32(cipherKey + 12);
- if (keyBits == 128) {
- for (;;) {
- temp = rk[3];
- rk[4] = rk[0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[5] = rk[1] ^ rk[4];
- rk[6] = rk[2] ^ rk[5];
- rk[7] = rk[3] ^ rk[6];
- if (++i == 10) {
- return 10;
- }
- rk += 4;
- }
- }
- rk[4] = GETU32(cipherKey + 16);
- rk[5] = GETU32(cipherKey + 20);
- if (keyBits == 192) {
- for (;;) {
- temp = rk[ 5];
- rk[ 6] = rk[ 0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[ 7] = rk[ 1] ^ rk[ 6];
- rk[ 8] = rk[ 2] ^ rk[ 7];
- rk[ 9] = rk[ 3] ^ rk[ 8];
- if (++i == 8) {
- return 12;
- }
- rk[10] = rk[ 4] ^ rk[ 9];
- rk[11] = rk[ 5] ^ rk[10];
- rk += 6;
- }
- }
- rk[6] = GETU32(cipherKey + 24);
- rk[7] = GETU32(cipherKey + 28);
- if (keyBits == 256) {
- for (;;) {
- temp = rk[ 7];
- rk[ 8] = rk[ 0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[ 9] = rk[ 1] ^ rk[ 8];
- rk[10] = rk[ 2] ^ rk[ 9];
- rk[11] = rk[ 3] ^ rk[10];
- if (++i == 7) {
- return 14;
- }
- temp = rk[11];
- rk[12] = rk[ 4] ^
- (Te4[(temp >> 24) ] & 0xff000000) ^
- (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(temp ) & 0xff] & 0x000000ff);
- rk[13] = rk[ 5] ^ rk[12];
- rk[14] = rk[ 6] ^ rk[13];
- rk[15] = rk[ 7] ^ rk[14];
-
- rk += 8;
- }
- }
- return 0;
-}
-
-#ifdef USE_RIJNDAEL_COUNTER_OPTIMIZATION
-static void
-rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, u32 ctr3, u32 ctr2, u32 ctr1, u32 ctr0, u8 ct[16])
-#else
-static void
-rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16])
-#endif
-{
- u32 s0, s1, s2, s3, t0, t1, t2, t3;
-#ifndef FULL_UNROLL
- int r;
-#endif /* ?FULL_UNROLL */
-
- /*
- * map byte array block to cipher state
- * and add initial round key:
- */
-#ifdef USE_RIJNDAEL_COUNTER_OPTIMIZATION
- s0 = ctr3 ^ rk[0];
- s1 = ctr2 ^ rk[1];
- s2 = ctr1 ^ rk[2];
- s3 = ctr0 ^ rk[3];
-#else
- s0 = GETU32(pt ) ^ rk[0];
- s1 = GETU32(pt + 4) ^ rk[1];
- s2 = GETU32(pt + 8) ^ rk[2];
- s3 = GETU32(pt + 12) ^ rk[3];
-#endif
-
-#ifdef FULL_UNROLL
- /* round 1: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
- /* round 2: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
- /* round 3: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
- /* round 4: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
- /* round 5: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
- /* round 6: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
- /* round 7: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
- /* round 8: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
- /* round 9: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
- if (Nr > 10) {
- /* round 10: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
- /* round 11: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
- if (Nr > 12) {
- /* round 12: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
- /* round 13: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
- }
- }
- rk += Nr << 2;
-#else /* !FULL_UNROLL */
- /*
- * Nr - 1 full rounds:
- */
- r = Nr >> 1;
- for (;;) {
- t0 =
- Te0[(s0 >> 24) ] ^
- Te1[(s1 >> 16) & 0xff] ^
- Te2[(s2 >> 8) & 0xff] ^
- Te3[(s3 ) & 0xff] ^
- rk[4];
- t1 =
- Te0[(s1 >> 24) ] ^
- Te1[(s2 >> 16) & 0xff] ^
- Te2[(s3 >> 8) & 0xff] ^
- Te3[(s0 ) & 0xff] ^
- rk[5];
- t2 =
- Te0[(s2 >> 24) ] ^
- Te1[(s3 >> 16) & 0xff] ^
- Te2[(s0 >> 8) & 0xff] ^
- Te3[(s1 ) & 0xff] ^
- rk[6];
- t3 =
- Te0[(s3 >> 24) ] ^
- Te1[(s0 >> 16) & 0xff] ^
- Te2[(s1 >> 8) & 0xff] ^
- Te3[(s2 ) & 0xff] ^
- rk[7];
-
- rk += 8;
- if (--r == 0) {
- break;
- }
-
- s0 =
- Te0[(t0 >> 24) ] ^
- Te1[(t1 >> 16) & 0xff] ^
- Te2[(t2 >> 8) & 0xff] ^
- Te3[(t3 ) & 0xff] ^
- rk[0];
- s1 =
- Te0[(t1 >> 24) ] ^
- Te1[(t2 >> 16) & 0xff] ^
- Te2[(t3 >> 8) & 0xff] ^
- Te3[(t0 ) & 0xff] ^
- rk[1];
- s2 =
- Te0[(t2 >> 24) ] ^
- Te1[(t3 >> 16) & 0xff] ^
- Te2[(t0 >> 8) & 0xff] ^
- Te3[(t1 ) & 0xff] ^
- rk[2];
- s3 =
- Te0[(t3 >> 24) ] ^
- Te1[(t0 >> 16) & 0xff] ^
- Te2[(t1 >> 8) & 0xff] ^
- Te3[(t2 ) & 0xff] ^
- rk[3];
- }
-#endif /* ?FULL_UNROLL */
- /*
- * apply last round and
- * map cipher state to byte array block:
- */
- s0 =
- (Te4[(t0 >> 24) ] & 0xff000000) ^
- (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[0];
- PUTU32(ct , s0);
- s1 =
- (Te4[(t1 >> 24) ] & 0xff000000) ^
- (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[1];
- PUTU32(ct + 4, s1);
- s2 =
- (Te4[(t2 >> 24) ] & 0xff000000) ^
- (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[2];
- PUTU32(ct + 8, s2);
- s3 =
- (Te4[(t3 >> 24) ] & 0xff000000) ^
- (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[3];
- PUTU32(ct + 12, s3);
-}
-#endif
-
-#ifdef AES_BENCHMARK
-int
-main(int c, char **v)
-{
- int i;
- char blob[509]; /* the size of a cell payload. */
- char blob_out[509];
- aes_cnt_cipher_t *cipher = aes_new_cipher();
- aes_set_key(cipher, "aesbenchmarkkey!", 128);
- memset(blob, 'z', sizeof(blob));
-
- for (i=0;i<1000000; ++i) {
- aes_crypt(cipher, blob, sizeof(blob), blob_out);
- }
- return 0;
}
-#endif
diff --git a/src/common/aes.h b/src/common/aes.h
index eb633dbcce..221e846155 100644
--- a/src/common/aes.h
+++ b/src/common/aes.h
@@ -13,8 +13,6 @@
* \brief Headers for aes.c
*/
-#include "torint.h"
-
struct aes_cnt_cipher;
typedef struct aes_cnt_cipher aes_cnt_cipher_t;
@@ -26,5 +24,7 @@ void aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len);
void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv);
+int evaluate_evp_for_aes(int force_value);
+
#endif
diff --git a/src/common/compat.c b/src/common/compat.c
index 80b4907b81..ea95f9f085 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -58,6 +58,14 @@
#endif
#endif
+/* Includes for the process attaching prevention */
+#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
+#include <sys/prctl.h>
+#elif defined(__APPLE__)
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#endif
+
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -103,6 +111,35 @@
#include "strlcat.c"
#endif
+/** As open(path, flags, mode), but return an fd with the close-on-exec mode
+ * set. */
+int
+tor_open_cloexec(const char *path, int flags, unsigned mode)
+{
+#ifdef O_CLOEXEC
+ return open(path, flags|O_CLOEXEC, mode);
+#else
+ int fd = open(path, flags, mode);
+#ifdef FD_CLOEXEC
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+ return fd;
+#endif
+}
+
+/** DOCDOC */
+FILE *
+tor_fopen_cloexec(const char *path, const char *mode)
+{
+ FILE *result = fopen(path, mode);
+#ifdef FD_CLOEXEC
+ if (result != NULL)
+ fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
+#endif
+ return result;
+}
+
#ifdef HAVE_SYS_MMAN_H
/** Try to create a memory mapping for <b>filename</b> and return it. On
* failure, return NULL. Sets errno properly, using ERANGE to mean
@@ -118,7 +155,7 @@ tor_mmap_file(const char *filename)
tor_assert(filename);
- fd = open(filename, O_RDONLY, 0);
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
if (fd<0) {
int save_errno = errno;
int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
@@ -695,7 +732,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
*locked_out = 0;
log_info(LD_FS, "Locking \"%s\"", filename);
- fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
if (fd < 0) {
log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
strerror(errno));
@@ -922,8 +959,16 @@ mark_socket_open(tor_socket_t s)
tor_socket_t
tor_open_socket(int domain, int type, int protocol)
{
- tor_socket_t s = socket(domain, type, protocol);
+ tor_socket_t s;
+#ifdef SOCK_CLOEXEC
+#define LINUX_CLOEXEC_OPEN_SOCKET
+ type |= SOCK_CLOEXEC;
+#endif
+ s = socket(domain, type, protocol);
if (SOCKET_OK(s)) {
+#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -936,8 +981,17 @@ tor_open_socket(int domain, int type, int protocol)
tor_socket_t
tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
{
- tor_socket_t s = accept(sockfd, addr, len);
+ tor_socket_t s;
+#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
+#define LINUX_CLOEXEC_ACCEPT
+ s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
+#else
+ s = accept(sockfd, addr, len);
+#endif
if (SOCKET_OK(s)) {
+#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -993,8 +1047,17 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
//don't use win32 socketpairs (they are always bad)
#if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
int r;
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
+#endif
r = socketpair(family, type, protocol, fd);
if (r == 0) {
+#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
+ if (fd[0] >= 0)
+ fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ if (fd[1] >= 0)
+ fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
if (fd[0] >= 0) {
++n_sockets_open;
@@ -1464,6 +1527,57 @@ switch_id(const char *user)
#endif
}
+/* We only use the linux prctl for now. There is no Win32 support; this may
+ * also work on various BSD systems and Mac OS X - send testing feedback!
+ *
+ * On recent Gnu/Linux kernels it is possible to create a system-wide policy
+ * that will prevent non-root processes from attaching to other processes
+ * unless they are the parent process; thus gdb can attach to programs that
+ * they execute but they cannot attach to other processes running as the same
+ * user. The system wide policy may be set with the sysctl
+ * kernel.yama.ptrace_scope or by inspecting
+ * /proc/sys/kernel/yama/ptrace_scope and it is 1 by default on Ubuntu 11.04.
+ *
+ * This ptrace scope will be ignored on Gnu/Linux for users with
+ * CAP_SYS_PTRACE and so it is very likely that root will still be able to
+ * attach to the Tor process.
+ */
+/** Attempt to disable debugger attachment: return 0 on success, -1 on
+ * failure. */
+int
+tor_disable_debugger_attach(void)
+{
+ int r, attempted;
+ r = -1;
+ attempted = 0;
+ log_debug(LD_CONFIG,
+ "Attemping to disable debugger attachment to Tor for "
+ "unprivileged users.");
+#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && defined(HAVE_PRCTL)
+#ifdef PR_SET_DUMPABLE
+ attempted = 1;
+ r = prctl(PR_SET_DUMPABLE, 0);
+#endif
+#endif
+#if defined(__APPLE__) && defined(PT_DENY_ATTACH)
+ if (r < 0) {
+ attempted = 1;
+ r = ptrace(PT_DENY_ATTACH, 0, 0, 0);
+ }
+#endif
+
+ // XXX: TODO - Mac OS X has dtrace and this may be disabled.
+ // XXX: TODO - Windows probably has something similar
+ if (r == 0) {
+ log_debug(LD_CONFIG,"Debugger attachment disabled for "
+ "unprivileged users.");
+ } else if (attempted) {
+ log_warn(LD_CONFIG, "Unable to disable ptrace attach: %s",
+ strerror(errno));
+ }
+ return r;
+}
+
#ifdef HAVE_PWD_H
/** Allocate and return a string containing the home directory for the
* user <b>username</b>. Only works on posix-like systems. */
@@ -1577,7 +1691,7 @@ tor_inet_ntop(int af, const void *src, char *dst, size_t len)
addr->s6_addr[12], addr->s6_addr[13],
addr->s6_addr[14], addr->s6_addr[15]);
}
- if (strlen(buf) > len)
+ if ((strlen(buf) + 1) > len) /* +1 for \0 */
return NULL;
strlcpy(dst, buf, len);
return dst;
@@ -1618,7 +1732,7 @@ tor_inet_ntop(int af, const void *src, char *dst, size_t len)
}
}
*cp = '\0';
- if (strlen(buf) > len)
+ if ((strlen(buf) + 1) > len) /* +1 for \0 */
return NULL;
strlcpy(dst, buf, len);
return dst;
@@ -1678,24 +1792,30 @@ tor_inet_pton(int af, const char *src, void *dst)
return 0;
if (TOR_ISXDIGIT(*src)) {
char *next;
+ ssize_t len;
long r = strtol(src, &next, 16);
- if (next > 4+src)
- return 0;
- if (next == src)
- return 0;
- if (r<0 || r>65536)
+ tor_assert(next != NULL);
+ tor_assert(next != src);
+
+ len = *next == '\0' ? eow - src : next - src;
+ if (len > 4)
return 0;
+ if (len > 1 && !TOR_ISXDIGIT(src[1]))
+ return 0; /* 0x is not valid */
+ tor_assert(r >= 0);
+ tor_assert(r < 65536);
words[i++] = (uint16_t)r;
setWords++;
src = next;
if (*src != ':' && src != eow)
return 0;
++src;
- } else if (*src == ':' && i > 0 && gapPos==-1) {
+ } else if (*src == ':' && i > 0 && gapPos == -1) {
gapPos = i;
++src;
- } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) {
+ } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
+ gapPos == -1) {
gapPos = i;
src += 2;
} else {
@@ -1806,6 +1926,7 @@ get_uname(void)
static struct {
unsigned major; unsigned minor; const char *version;
} win_version_table[] = {
+ { 6, 2, "Windows 8" },
{ 6, 1, "Windows 7" },
{ 6, 0, "Windows Vista" },
{ 5, 2, "Windows Server 2003" },
@@ -1862,7 +1983,7 @@ get_uname(void)
plat, extra);
} else {
if (info.dwMajorVersion > 6 ||
- (info.dwMajorVersion==6 && info.dwMinorVersion>1))
+ (info.dwMajorVersion==6 && info.dwMinorVersion>2))
tor_snprintf(uname_result, sizeof(uname_result),
"Very recent version of Windows [major=%d,minor=%d] %s",
(int)info.dwMajorVersion,(int)info.dwMinorVersion,
@@ -1994,6 +2115,52 @@ spawn_exit(void)
#endif
}
+/** Implementation logic for compute_num_cpus(). */
+static int
+compute_num_cpus_impl(void)
+{
+#ifdef MS_WINDOWS
+ SYSTEM_INFO info;
+ memset(&info, 0, sizeof(info));
+ GetSystemInfo(&info);
+ if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
+ return (int)info.dwNumberOfProcessors;
+ else
+ return -1;
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+ long cpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (cpus >= 1 && cpus < INT_MAX)
+ return (int)cpus;
+ else
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+#define MAX_DETECTABLE_CPUS 16
+
+/** Return how many CPUs we are running with. We assume that nobody is
+ * using hot-swappable CPUs, so we don't recompute this after the first
+ * time. Return -1 if we don't know how to tell the number of CPUs on this
+ * system.
+ */
+int
+compute_num_cpus(void)
+{
+ static int num_cpus = -2;
+ if (num_cpus == -2) {
+ num_cpus = compute_num_cpus_impl();
+ tor_assert(num_cpus != -2);
+ if (num_cpus > MAX_DETECTABLE_CPUS)
+ log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
+ "will not autodetect any more than %d, though. If you "
+ "want to configure more, set NumCPUs in your torrc",
+ num_cpus, MAX_DETECTABLE_CPUS);
+ }
+ return num_cpus;
+}
+
/** Set *timeval to the current time of day. On error, log and terminate.
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
*/
diff --git a/src/common/compat.h b/src/common/compat.h
index eb79b04449..db541623d3 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -9,8 +9,12 @@
#include "orconfig.h"
#include "torint.h"
#ifdef MS_WINDOWS
+#ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+#endif
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
#define WIN32_LEAN_AND_MEAN
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#include <winsock.h>
@@ -41,9 +45,6 @@
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
@@ -51,6 +52,8 @@
#include <netinet6/in6.h>
#endif
+#include <stdio.h>
+
#if defined (WINCE)
#include <fcntl.h>
#include <io.h>
@@ -132,7 +135,6 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
/* GCC has several useful attributes. */
#if defined(__GNUC__) && __GNUC__ >= 3
#define ATTR_NORETURN __attribute__((noreturn))
-#define ATTR_PURE __attribute__((pure))
#define ATTR_CONST __attribute__((const))
#define ATTR_MALLOC __attribute__((malloc))
#define ATTR_NORETURN __attribute__((noreturn))
@@ -165,7 +167,6 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
#define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
#else
#define ATTR_NORETURN
-#define ATTR_PURE
#define ATTR_CONST
#define ATTR_MALLOC
#define ATTR_NORETURN
@@ -177,6 +178,10 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
/** Expands to a syntactically valid empty statement. */
#define STMT_NIL (void)0
+/** Expands to a syntactically valid empty statement, explicitly (void)ing its
+ * argument. */
+#define STMT_VOID(a) while (0) { (void)(a); }
+
#ifdef __GNUC__
/** STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that
* the macro can be used as if it were a single C statement. */
@@ -264,9 +269,9 @@ int tor_asprintf(char **strp, const char *fmt, ...)
int tor_vasprintf(char **strp, const char *fmt, va_list args);
const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
- size_t nlen) ATTR_PURE ATTR_NONNULL((1,3));
+ size_t nlen) ATTR_NONNULL((1,3));
static const void *tor_memstr(const void *haystack, size_t hlen,
- const char *needle) ATTR_PURE ATTR_NONNULL((1,3));
+ const char *needle) ATTR_NONNULL((1,3));
static INLINE const void *
tor_memstr(const void *haystack, size_t hlen, const char *needle)
{
@@ -367,6 +372,9 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
#endif
/* ===== File compatibility */
+int tor_open_cloexec(const char *path, int flags, unsigned mode);
+FILE *tor_fopen_cloexec(const char *path, const char *mode);
+
int replace_file(const char *from, const char *to);
int touch_file(const char *fname);
@@ -392,7 +400,7 @@ typedef int socklen_t;
#ifdef MS_WINDOWS
#define tor_socket_t intptr_t
-#define SOCKET_OK(s) ((s) != INVALID_SOCKET)
+#define SOCKET_OK(s) ((unsigned)(s) != INVALID_SOCKET)
#else
#define tor_socket_t int
#define SOCKET_OK(s) ((s) >= 0)
@@ -536,9 +544,9 @@ long tor_weak_random(void);
/* ===== OS compatibility */
const char *get_uname(void);
-uint16_t get_uint16(const void *cp) ATTR_PURE ATTR_NONNULL((1));
-uint32_t get_uint32(const void *cp) ATTR_PURE ATTR_NONNULL((1));
-uint64_t get_uint64(const void *cp) ATTR_PURE ATTR_NONNULL((1));
+uint16_t get_uint16(const void *cp) ATTR_NONNULL((1));
+uint32_t get_uint32(const void *cp) ATTR_NONNULL((1));
+uint64_t get_uint64(const void *cp) ATTR_NONNULL((1));
void set_uint16(void *cp, uint16_t v) ATTR_NONNULL((1));
void set_uint32(void *cp, uint32_t v) ATTR_NONNULL((1));
void set_uint64(void *cp, uint64_t v) ATTR_NONNULL((1));
@@ -556,6 +564,7 @@ set_uint8(void *cp, uint8_t v)
typedef unsigned long rlim_t;
#endif
int set_max_file_descriptors(rlim_t limit, int *max);
+int tor_disable_debugger_attach(void);
int switch_id(const char *user);
#ifdef HAVE_PWD_H
char *get_user_homedir(const char *username);
@@ -577,6 +586,8 @@ void spawn_exit(void) ATTR_NORETURN;
#undef TOR_IS_MULTITHREADED
#endif
+int compute_num_cpus(void);
+
/* Because we use threads instead of processes on most platforms (Windows,
* Linux, etc), we need locking for them. On platforms with poor thread
* support or broken gethostbyname_r, these functions are no-ops. */
@@ -610,7 +621,7 @@ void tor_threads_init(void);
#else
#define tor_mutex_new() ((tor_mutex_t*)tor_malloc(sizeof(int)))
#define tor_mutex_init(m) STMT_NIL
-#define tor_mutex_acquire(m) STMT_NIL
+#define tor_mutex_acquire(m) STMT_VOID(m)
#define tor_mutex_release(m) STMT_NIL
#define tor_mutex_free(m) STMT_BEGIN tor_free(m); STMT_END
#define tor_mutex_uninit(m) STMT_NIL
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 6d89be804b..67f465927c 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -19,6 +19,10 @@
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
+#include <event2/thread.h>
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
#else
#include <event.h>
#endif
@@ -163,11 +167,24 @@ struct event_base *the_event_base = NULL;
#endif
#endif
+#ifdef USE_BUFFEREVENTS
+static int using_iocp_bufferevents = 0;
+static void tor_libevent_set_tick_timeout(int msec_per_tick);
+
+int
+tor_libevent_using_iocp_bufferevents(void)
+{
+ return using_iocp_bufferevents;
+}
+#endif
+
/** Initialize the Libevent library and set up the event base. */
void
-tor_libevent_initialize(void)
+tor_libevent_initialize(tor_libevent_cfg *torcfg)
{
tor_assert(the_event_base == NULL);
+ /* some paths below don't use torcfg, so avoid unused variable warnings */
+ (void)torcfg;
#ifdef __APPLE__
if (MACOSX_KQUEUE_IS_BROKEN ||
@@ -177,11 +194,76 @@ tor_libevent_initialize(void)
#endif
#ifdef HAVE_EVENT2_EVENT_H
- the_event_base = event_base_new();
+ {
+ int attempts = 0;
+ int using_threads;
+ struct event_config *cfg;
+
+ retry:
+ ++attempts;
+ using_threads = 0;
+ cfg = event_config_new();
+ tor_assert(cfg);
+
+#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS)
+ if (! torcfg->disable_iocp) {
+ evthread_use_windows_threads();
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
+ using_iocp_bufferevents = 1;
+ using_threads = 1;
+ } else {
+ using_iocp_bufferevents = 0;
+ }
+#endif
+
+ if (!using_threads) {
+ /* Telling Libevent not to try to turn locking on can avoid a needless
+ * socketpair() attempt. */
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
+ }
+
+#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
+ if (torcfg->num_cpus > 0)
+ event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
+#endif
+
+#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
+ /* We can enable changelist support with epoll, since we don't give
+ * Libevent any dup'd fds. This lets us avoid some syscalls. */
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
+#endif
+
+ the_event_base = event_base_new_with_config(cfg);
+
+ event_config_free(cfg);
+
+ if (using_threads && the_event_base == NULL && attempts < 2) {
+ /* This could be a socketpair() failure, which can happen sometimes on
+ * windows boxes with obnoxious firewall rules. Downgrade and try
+ * again. */
+#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS)
+ if (torcfg->disable_iocp == 0) {
+ log_warn(LD_GENERAL, "Unable to initialize Libevent. Trying again "
+ "with IOCP disabled.");
+ } else
+#endif
+ {
+ log_warn(LD_GENERAL, "Unable to initialize Libevent. Trying again.");
+ }
+
+ torcfg->disable_iocp = 1;
+ goto retry;
+ }
+ }
#else
the_event_base = event_init();
#endif
+ if (!the_event_base) {
+ log_err(LD_GENERAL, "Unable to initialize Libevent: cannot continue.");
+ exit(1);
+ }
+
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
/* Making this a NOTICE for now so we can link bugs to a libevent versions
* or methods better. */
@@ -195,6 +277,10 @@ tor_libevent_initialize(void)
"You have a *VERY* old version of libevent. It is likely to be buggy; "
"please build Tor with a more recent version.");
#endif
+
+#ifdef USE_BUFFEREVENTS
+ tor_libevent_set_tick_timeout(torcfg->msec_per_tick);
+#endif
}
/** Return the current Libevent event base that we're set up to use. */
@@ -240,7 +326,7 @@ tor_decode_libevent_version(const char *v)
/* Try the new preferred "1.4.11-stable" format.
* Also accept "1.4.14b-stable". */
- fields = sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
+ fields = tor_sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
if (fields == 3 ||
((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
(fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
@@ -248,7 +334,7 @@ tor_decode_libevent_version(const char *v)
}
/* Try the old "1.3e" format. */
- fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
+ fields = tor_sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
if (fields == 3 && TOR_ISALPHA(c)) {
return V_OLD(major, minor, c);
} else if (fields == 2) {
@@ -472,6 +558,60 @@ tor_check_libevent_header_compatibility(void)
#endif
}
+struct tor_libevent_action_t {
+ struct event *ev;
+ void (*cb)(void *arg);
+ void *arg;
+};
+
+/** Callback for tor_run_in_libevent_loop */
+static void
+run_runnable_cb(evutil_socket_t s, short what, void *arg)
+{
+ tor_libevent_action_t *r = arg;
+ void (*cb)(void *) = r->cb;
+ void *cb_arg = r->arg;
+ (void)what;
+ (void)s;
+ tor_event_free(r->ev);
+ tor_free(r);
+
+ cb(cb_arg);
+}
+
+/** Cause cb(arg) to run later on this iteration of the libevent loop, or in
+ * the next iteration of the libevent loop. This is useful for when you're
+ * deep inside a no-reentrant code and there's some function you want to call
+ * without worrying about whether it might cause reeentrant invocation.
+ */
+tor_libevent_action_t *
+tor_run_in_libevent_loop(void (*cb)(void *arg), void *arg)
+{
+ tor_libevent_action_t *r = tor_malloc(sizeof(tor_libevent_action_t));
+ r->cb = cb;
+ r->arg = arg;
+ r->ev = tor_event_new(tor_libevent_get_base(), -1, EV_TIMEOUT,
+ run_runnable_cb, r);
+ if (!r->ev) {
+ tor_free(r);
+ return NULL;
+ }
+ /* Make the event active immediately. */
+ event_active(r->ev, EV_TIMEOUT, 1);
+
+ return r;
+}
+
+/**
+ * Cancel <b>action</b> without running it.
+ */
+void
+tor_cancel_libevent_action(tor_libevent_action_t *action)
+{
+ tor_event_free(action->ev);
+ tor_free(action);
+}
+
/*
If possible, we're going to try to use Libevent's periodic timer support,
since it does a pretty good job of making sure that periodic events get
@@ -552,3 +692,55 @@ periodic_timer_free(periodic_timer_t *timer)
tor_free(timer);
}
+#ifdef USE_BUFFEREVENTS
+static const struct timeval *one_tick = NULL;
+/**
+ * Return a special timeout to be passed whenever libevent's O(1) timeout
+ * implementation should be used. Only use this when the timer is supposed
+ * to fire after msec_per_tick ticks have elapsed.
+*/
+const struct timeval *
+tor_libevent_get_one_tick_timeout(void)
+{
+ tor_assert(one_tick);
+ return one_tick;
+}
+
+/** Initialize the common timeout that we'll use to refill the buckets every
+ * time a tick elapses. */
+static void
+tor_libevent_set_tick_timeout(int msec_per_tick)
+{
+ struct event_base *base = tor_libevent_get_base();
+ struct timeval tv;
+
+ tor_assert(! one_tick);
+ tv.tv_sec = msec_per_tick / 1000;
+ tv.tv_usec = (msec_per_tick % 1000) * 1000;
+ one_tick = event_base_init_common_timeout(base, &tv);
+}
+
+static struct bufferevent *
+tor_get_root_bufferevent(struct bufferevent *bev)
+{
+ struct bufferevent *u;
+ while ((u = bufferevent_get_underlying(bev)) != NULL)
+ bev = u;
+ return bev;
+}
+
+int
+tor_set_bufferevent_rate_limit(struct bufferevent *bev,
+ struct ev_token_bucket_cfg *cfg)
+{
+ return bufferevent_set_rate_limit(tor_get_root_bufferevent(bev), cfg);
+}
+
+int
+tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
+ struct bufferevent_rate_limit_group *g)
+{
+ return bufferevent_add_to_rate_limit_group(tor_get_root_bufferevent(bev), g);
+}
+#endif
+
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index 89b256396b..4076cc0e08 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -8,6 +8,11 @@
struct event;
struct event_base;
+#ifdef USE_BUFFEREVENTS
+struct bufferevent;
+struct ev_token_bucket_cfg;
+struct bufferevent_rate_limit_group;
+#endif
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/util.h>
@@ -39,8 +44,12 @@ void tor_event_free(struct event *ev);
#define tor_evdns_add_server_port evdns_add_server_port
#endif
-typedef struct periodic_timer_t periodic_timer_t;
+typedef struct tor_libevent_action_t tor_libevent_action_t;
+tor_libevent_action_t *tor_run_in_libevent_loop(void (*cb)(void *arg),
+ void *arg);
+void tor_cancel_libevent_action(tor_libevent_action_t *action);
+typedef struct periodic_timer_t periodic_timer_t;
periodic_timer_t *periodic_timer_new(struct event_base *base,
const struct timeval *tv,
void (*cb)(periodic_timer_t *timer, void *data),
@@ -54,7 +63,13 @@ struct timeval;
int tor_event_base_loopexit(struct event_base *base, struct timeval *tv);
#endif
-void tor_libevent_initialize(void);
+typedef struct tor_libevent_cfg {
+ int disable_iocp;
+ int num_cpus;
+ int msec_per_tick;
+} tor_libevent_cfg;
+
+void tor_libevent_initialize(tor_libevent_cfg *cfg);
struct event_base *tor_libevent_get_base(void);
const char *tor_libevent_get_method(void);
void tor_check_libevent_version(const char *m, int server,
@@ -62,5 +77,14 @@ void tor_check_libevent_version(const char *m, int server,
void tor_check_libevent_header_compatibility(void);
const char *tor_libevent_get_version_str(void);
+#ifdef USE_BUFFEREVENTS
+const struct timeval *tor_libevent_get_one_tick_timeout(void);
+int tor_libevent_using_iocp_bufferevents(void);
+int tor_set_bufferevent_rate_limit(struct bufferevent *bev,
+ struct ev_token_bucket_cfg *cfg);
+int tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
+ struct bufferevent_rate_limit_group *g);
+#endif
+
#endif
diff --git a/src/common/container.c b/src/common/container.c
index 1515c387ad..31cc6c5a6c 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -62,13 +62,22 @@ smartlist_clear(smartlist_t *sl)
static INLINE void
smartlist_ensure_capacity(smartlist_t *sl, int size)
{
+#if SIZEOF_SIZE_T > SIZEOF_INT
+#define MAX_CAPACITY (INT_MAX)
+#else
+#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*))))
+#endif
if (size > sl->capacity) {
- int higher = sl->capacity * 2;
- while (size > higher)
- higher *= 2;
- tor_assert(higher > 0); /* detect overflow */
+ int higher = sl->capacity;
+ if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) {
+ tor_assert(size <= MAX_CAPACITY);
+ higher = MAX_CAPACITY;
+ } else {
+ while (size > higher)
+ higher *= 2;
+ }
sl->capacity = higher;
- sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
+ sl->list = tor_realloc(sl->list, sizeof(void*)*((size_t)sl->capacity));
}
}
@@ -287,7 +296,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
/** Remove the <b>idx</b>th element of sl; if idx is not the last
* element, swap the last element of sl into the <b>idx</b>th space.
- * Return the old value of the <b>idx</b>th element.
*/
void
smartlist_del(smartlist_t *sl, int idx)
diff --git a/src/common/container.h b/src/common/container.h
index 4a6eba789d..fe071cc1b3 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -35,19 +35,14 @@ void smartlist_remove(smartlist_t *sl, const void *element);
void *smartlist_pop_last(smartlist_t *sl);
void smartlist_reverse(smartlist_t *sl);
void smartlist_string_remove(smartlist_t *sl, const char *element);
-int smartlist_isin(const smartlist_t *sl, const void *element) ATTR_PURE;
-int smartlist_string_isin(const smartlist_t *sl, const char *element)
- ATTR_PURE;
-int smartlist_string_pos(const smartlist_t *, const char *elt) ATTR_PURE;
-int smartlist_string_isin_case(const smartlist_t *sl, const char *element)
- ATTR_PURE;
-int smartlist_string_num_isin(const smartlist_t *sl, int num) ATTR_PURE;
-int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
- ATTR_PURE;
-int smartlist_digest_isin(const smartlist_t *sl, const char *element)
- ATTR_PURE;
-int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
- ATTR_PURE;
+int smartlist_isin(const smartlist_t *sl, const void *element);
+int smartlist_string_isin(const smartlist_t *sl, const char *element);
+int smartlist_string_pos(const smartlist_t *, const char *elt);
+int smartlist_string_isin_case(const smartlist_t *sl, const char *element);
+int smartlist_string_num_isin(const smartlist_t *sl, int num);
+int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2);
+int smartlist_digest_isin(const smartlist_t *sl, const char *element);
+int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
@@ -55,14 +50,14 @@ void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
#ifdef DEBUG_SMARTLIST
/** Return the number of items in sl.
*/
-static INLINE int smartlist_len(const smartlist_t *sl) ATTR_PURE;
+static INLINE int smartlist_len(const smartlist_t *sl);
static INLINE int smartlist_len(const smartlist_t *sl) {
tor_assert(sl);
return (sl)->num_used;
}
/** Return the <b>idx</b>th element of sl.
*/
-static INLINE void *smartlist_get(const smartlist_t *sl, int idx) ATTR_PURE;
+static INLINE void *smartlist_get(const smartlist_t *sl, int idx);
static INLINE void *smartlist_get(const smartlist_t *sl, int idx) {
tor_assert(sl);
tor_assert(idx>=0);
@@ -114,8 +109,7 @@ void smartlist_uniq_strings(smartlist_t *sl);
void smartlist_uniq_digests(smartlist_t *sl);
void smartlist_uniq_digests256(smartlist_t *sl);
void *smartlist_bsearch(smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member))
- ATTR_PURE;
+ int (*compare)(const void *key, const void **member));
int smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
int (*compare)(const void *key, const void **member),
int *found_out);
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 851f11bf3b..ebaa0122fd 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -13,8 +13,12 @@
#include "orconfig.h"
#ifdef MS_WINDOWS
+#ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+#endif
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
@@ -60,8 +64,6 @@
#error "We require OpenSSL >= 0.9.7"
#endif
-#include <openssl/engine.h>
-
#ifdef ANDROID
/* Android's OpenSSL seems to have removed all of its Engine support. */
#define DISABLE_ENGINES
@@ -274,6 +276,9 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
} else {
log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
}
+
+ evaluate_evp_for_aes(-1);
+
return crypto_seed_rng(1);
}
return 0;
@@ -948,7 +953,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data,
log_warn(LD_BUG, "couldn't compute digest");
return -1;
}
- buflen = crypto_pk_keysize(env)+1;
+ buflen = crypto_pk_keysize(env);
buf = tor_malloc(buflen);
r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
if (r != DIGEST_LEN) {
@@ -1133,8 +1138,8 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env,
warnOnFailure);
}
- buf = tor_malloc(pkeylen+1);
- outlen = crypto_pk_private_decrypt(env,buf,pkeylen+1,from,pkeylen,padding,
+ buf = tor_malloc(pkeylen);
+ outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
warnOnFailure);
if (outlen<0) {
log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
@@ -1202,9 +1207,6 @@ crypto_pk_asn1_decode(const char *str, size_t len)
{
RSA *rsa;
unsigned char *buf;
- /* This ifdef suppresses a type warning. Take out the first case once
- * everybody is using OpenSSL 0.9.7 or later.
- */
const unsigned char *cp;
cp = buf = tor_malloc(len);
memcpy(buf,str,len);
@@ -1245,6 +1247,32 @@ crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out)
return 0;
}
+/** Compute all digests of the DER encoding of <b>pk</b>, and store them
+ * in <b>digests_out</b>. Return 0 on success, -1 on failure. */
+int
+crypto_pk_get_all_digests(crypto_pk_env_t *pk, digests_t *digests_out)
+{
+ unsigned char *buf, *bufp;
+ int len;
+
+ len = i2d_RSAPublicKey(pk->key, NULL);
+ if (len < 0)
+ return -1;
+ buf = bufp = tor_malloc(len+1);
+ len = i2d_RSAPublicKey(pk->key, &bufp);
+ if (len < 0) {
+ crypto_log_errors(LOG_WARN,"encoding public key");
+ tor_free(buf);
+ return -1;
+ }
+ if (crypto_digest_all(digests_out, (char*)buf, len) < 0) {
+ tor_free(buf);
+ return -1;
+ }
+ tor_free(buf);
+ return 0;
+}
+
/** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
* every four spaces. */
/* static */ void
@@ -1663,6 +1691,10 @@ crypto_digest_get_digest(crypto_digest_env_t *digest,
SHA256_Final(r, &tmpenv.d.sha2);
break;
default:
+ log_warn(LD_BUG, "Called with unknown algorithm %d", digest->algorithm);
+ /* If fragile_assert is not enabled, then we should at least not
+ * leak anything. */
+ memset(r, 0xff, sizeof(r));
tor_fragile_assert();
break;
}
@@ -1710,8 +1742,79 @@ crypto_hmac_sha1(char *hmac_out,
(unsigned char*)hmac_out, NULL);
}
+/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
+ * the <b>key</b> of length <b>key_len</b>. Store the DIGEST_LEN-byte result
+ * in <b>hmac_out</b>.
+ */
+void
+crypto_hmac_sha256(char *hmac_out,
+ const char *key, size_t key_len,
+ const char *msg, size_t msg_len)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x00908000l)
+ /* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */
+ tor_assert(key_len < INT_MAX);
+ tor_assert(msg_len < INT_MAX);
+ HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
+ (unsigned char*)hmac_out, NULL);
+#else
+ /* OpenSSL doesn't have an EVP implementation for SHA256. We'll need
+ to do HMAC on our own.
+
+ HMAC isn't so hard: To compute HMAC(key, msg):
+ 1. If len(key) > blocksize, key = H(key).
+ 2. If len(key) < blocksize, right-pad key up to blocksize with 0 bytes.
+ 3. let ipad = key xor 0x363636363636....36
+ let opad = key xor 0x5c5c5c5c5c5c....5c
+ The result is H(opad | H( ipad | msg ) )
+ */
+#define BLOCKSIZE 64
+#define DIGESTSIZE 32
+ uint8_t k[BLOCKSIZE];
+ uint8_t pad[BLOCKSIZE];
+ uint8_t d[DIGESTSIZE];
+ int i;
+ SHA256_CTX st;
+
+ tor_assert(key_len < INT_MAX);
+ tor_assert(msg_len < INT_MAX);
+
+ if (key_len <= BLOCKSIZE) {
+ memset(k, 0, sizeof(k));
+ memcpy(k, key, key_len); /* not time invariant in key_len */
+ } else {
+ SHA256((const uint8_t *)key, key_len, k);
+ memset(k+DIGESTSIZE, 0, sizeof(k)-DIGESTSIZE);
+ }
+ for (i = 0; i < BLOCKSIZE; ++i)
+ pad[i] = k[i] ^ 0x36;
+ SHA256_Init(&st);
+ SHA256_Update(&st, pad, BLOCKSIZE);
+ SHA256_Update(&st, (uint8_t*)msg, msg_len);
+ SHA256_Final(d, &st);
+
+ for (i = 0; i < BLOCKSIZE; ++i)
+ pad[i] = k[i] ^ 0x5c;
+ SHA256_Init(&st);
+ SHA256_Update(&st, pad, BLOCKSIZE);
+ SHA256_Update(&st, d, DIGESTSIZE);
+ SHA256_Final((uint8_t*)hmac_out, &st);
+
+ /* Now clear everything. */
+ memset(k, 0, sizeof(k));
+ memset(pad, 0, sizeof(pad));
+ memset(d, 0, sizeof(d));
+ memset(&st, 0, sizeof(st));
+#undef BLOCKSIZE
+#undef DIGESTSIZE
+#endif
+}
+
/* DH */
+/** Our DH 'g' parameter */
+#define DH_GENERATOR 2
+
/** Shared P parameter for our circuit-crypto DH key exchanges. */
static BIGNUM *dh_param_p = NULL;
/** Shared P parameter for our TLS DH key exchanges. */
@@ -1719,49 +1822,303 @@ static BIGNUM *dh_param_p_tls = NULL;
/** Shared G parameter for our DH key exchanges. */
static BIGNUM *dh_param_g = NULL;
+/** Generate and return a reasonable and safe DH parameter p. */
+static BIGNUM *
+crypto_generate_dynamic_dh_modulus(void)
+{
+ BIGNUM *dynamic_dh_modulus;
+ DH *dh_parameters;
+ int r, dh_codes;
+ char *s;
+
+ dynamic_dh_modulus = BN_new();
+ tor_assert(dynamic_dh_modulus);
+
+ dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL);
+ tor_assert(dh_parameters);
+
+ r = DH_check(dh_parameters, &dh_codes);
+ tor_assert(r && !dh_codes);
+
+ BN_copy(dynamic_dh_modulus, dh_parameters->p);
+ tor_assert(dynamic_dh_modulus);
+
+ DH_free(dh_parameters);
+
+ { /* log the dynamic DH modulus: */
+ s = BN_bn2hex(dynamic_dh_modulus);
+ tor_assert(s);
+ log_info(LD_OR, "Dynamic DH modulus generated: [%s]", s);
+ OPENSSL_free(s);
+ }
+
+ return dynamic_dh_modulus;
+}
+
+/** Store our dynamic DH modulus (and its group parameters) to
+ <b>fname</b> for future use. */
+static int
+crypto_store_dynamic_dh_modulus(const char *fname)
+{
+ int len, new_len;
+ DH *dh = NULL;
+ unsigned char *dh_string_repr = NULL, *cp = NULL;
+ char *base64_encoded_dh = NULL;
+ int retval = -1;
+
+ tor_assert(fname);
+
+ if (!dh_param_p_tls) {
+ log_info(LD_CRYPTO, "Tried to store a DH modulus that does not exist.");
+ goto done;
+ }
+
+ if (!(dh = DH_new()))
+ goto done;
+ if (!(dh->p = BN_dup(dh_param_p_tls)))
+ goto done;
+ if (!(dh->g = BN_new()))
+ goto done;
+ if (!BN_set_word(dh->g, DH_GENERATOR))
+ goto done;
+
+ len = i2d_DHparams(dh, NULL);
+ if (len < 0) {
+ log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (1).");
+ goto done;
+ }
+
+ cp = dh_string_repr = tor_malloc_zero(len+1);
+ len = i2d_DHparams(dh, &cp);
+ if ((len < 0) || ((cp - dh_string_repr) != len)) {
+ log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (2).");
+ goto done;
+ }
+
+ base64_encoded_dh = tor_malloc_zero(len * 2); /* should be enough */
+ new_len = base64_encode(base64_encoded_dh, len * 2,
+ (char *)dh_string_repr, len);
+ if (new_len < 0) {
+ log_warn(LD_CRYPTO, "Error occured while base64-encoding DH modulus.");
+ goto done;
+ }
+
+ if (write_bytes_to_new_file(fname, base64_encoded_dh, new_len, 0) < 0) {
+ log_info(LD_CRYPTO, "'%s' was already occupied.", fname);
+ goto done;
+ }
+
+ retval = 0;
+
+ done:
+ if (dh)
+ DH_free(dh);
+ tor_free(dh_string_repr);
+ tor_free(base64_encoded_dh);
+
+ return retval;
+}
+
+/** Return the dynamic DH modulus stored in <b>fname</b>. If there is no
+ dynamic DH modulus stored in <b>fname</b>, return NULL. */
+static BIGNUM *
+crypto_get_stored_dynamic_dh_modulus(const char *fname)
+{
+ int retval;
+ char *contents = NULL;
+ int dh_codes;
+ char *fname_new = NULL;
+ DH *stored_dh = NULL;
+ BIGNUM *dynamic_dh_modulus = NULL;
+ int length = 0;
+ unsigned char *base64_decoded_dh = NULL;
+ const unsigned char *cp = NULL;
+
+ tor_assert(fname);
+
+ contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
+ if (!contents) {
+ log_info(LD_CRYPTO, "Could not open file '%s'", fname);
+ goto done; /*usually means that ENOENT. don't try to move file to broken.*/
+ }
+
+ /* 'fname' contains the DH parameters stored in base64-ed DER
+ format. We are only interested in the DH modulus. */
+
+ cp = base64_decoded_dh = tor_malloc_zero(strlen(contents));
+ length = base64_decode((char *)base64_decoded_dh, strlen(contents),
+ contents, strlen(contents));
+ if (length < 0) {
+ log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (base64).");
+ goto err;
+ }
+
+ stored_dh = d2i_DHparams(NULL, &cp, length);
+ if ((!stored_dh) || (cp - base64_decoded_dh != length)) {
+ log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (d2i).");
+ goto err;
+ }
+
+ { /* check the cryptographic qualities of the stored dynamic DH modulus: */
+ retval = DH_check(stored_dh, &dh_codes);
+ if (!retval || dh_codes) {
+ log_warn(LD_CRYPTO, "Stored dynamic DH modulus is not a safe prime.");
+ goto err;
+ }
+
+ retval = DH_size(stored_dh);
+ if (retval < DH_BYTES) {
+ log_warn(LD_CRYPTO, "Stored dynamic DH modulus is smaller "
+ "than '%d' bits.", DH_BYTES*8);
+ goto err;
+ }
+
+ if (!BN_is_word(stored_dh->g, 2)) {
+ log_warn(LD_CRYPTO, "Stored dynamic DH parameters do not use '2' "
+ "as the group generator.");
+ goto err;
+ }
+ }
+
+ { /* log the dynamic DH modulus: */
+ char *s = BN_bn2hex(stored_dh->p);
+ tor_assert(s);
+ log_info(LD_OR, "Found stored dynamic DH modulus: [%s]", s);
+ OPENSSL_free(s);
+ }
+
+ goto done;
+
+ err:
+
+ { /* move broken prime to $filename.broken */
+ fname_new = tor_malloc(strlen(fname) + 8);
+
+ /* no can do if these functions return error */
+ strlcpy(fname_new, fname, strlen(fname) + 8);
+ strlcat(fname_new, ".broken", strlen(fname) + 8);
+
+ log_warn(LD_CRYPTO, "Moving broken dynamic DH prime to '%s'.", fname_new);
+
+ if (replace_file(fname, fname_new))
+ log_notice(LD_CRYPTO, "Error while moving '%s' to '%s'.",
+ fname, fname_new);
+
+ tor_free(fname_new);
+ }
+
+ if (stored_dh) {
+ DH_free(stored_dh);
+ stored_dh = NULL;
+ }
+
+ done:
+ tor_free(contents);
+ tor_free(base64_decoded_dh);
+
+ if (stored_dh) {
+ dynamic_dh_modulus = BN_dup(stored_dh->p);
+ DH_free(stored_dh);
+ }
+
+ return dynamic_dh_modulus;
+}
+
+/** Set the global TLS Diffie-Hellman modulus.
+ * If <b>dynamic_dh_modulus_fname</b> is set, try to read a dynamic DH modulus
+ * off it and use it as the DH modulus. If that's not possible,
+ * generate a new dynamic DH modulus.
+ * If <b>dynamic_dh_modulus_fname</b> is NULL, use the Apache mod_ssl DH
+ * modulus. */
+void
+crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname)
+{
+ BIGNUM *tls_prime = NULL;
+ int store_dh_prime_afterwards = 0;
+ int r;
+
+ /* If the space is occupied, free the previous TLS DH prime */
+ if (dh_param_p_tls) {
+ BN_free(dh_param_p_tls);
+ dh_param_p_tls = NULL;
+ }
+
+ if (dynamic_dh_modulus_fname) { /* use dynamic DH modulus: */
+ log_info(LD_OR, "Using stored dynamic DH modulus.");
+ tls_prime = crypto_get_stored_dynamic_dh_modulus(dynamic_dh_modulus_fname);
+
+ if (!tls_prime) {
+ log_notice(LD_OR, "Generating fresh dynamic DH modulus. "
+ "This might take a while...");
+ tls_prime = crypto_generate_dynamic_dh_modulus();
+
+ store_dh_prime_afterwards++;
+ }
+ } else { /* use the static DH prime modulus used by Apache in mod_ssl: */
+ tls_prime = BN_new();
+ tor_assert(tls_prime);
+
+ /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
+ * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
+ * prime.
+ */
+ r =BN_hex2bn(&tls_prime,
+ "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
+ "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
+ "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
+ "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
+ "B0E7393E0F24218EB3");
+ tor_assert(r);
+ }
+
+ tor_assert(tls_prime);
+
+ dh_param_p_tls = tls_prime;
+
+ if (store_dh_prime_afterwards)
+ /* save the new dynamic DH modulus to disk. */
+ if (crypto_store_dynamic_dh_modulus(dynamic_dh_modulus_fname)) {
+ log_notice(LD_CRYPTO, "Failed while storing dynamic DH modulus. "
+ "Make sure your data directory is sane.");
+ }
+}
+
/** Initialize dh_param_p and dh_param_g if they are not already
* set. */
static void
init_dh_param(void)
{
- BIGNUM *p, *p2, *g;
+ BIGNUM *circuit_dh_prime, *generator;
int r;
- if (dh_param_p && dh_param_g && dh_param_p_tls)
+ if (dh_param_p && dh_param_g)
return;
- p = BN_new();
- p2 = BN_new();
- g = BN_new();
- tor_assert(p);
- tor_assert(p2);
- tor_assert(g);
+ circuit_dh_prime = BN_new();
+ generator = BN_new();
+ tor_assert(circuit_dh_prime && generator);
+
+ /* Set our generator for all DH parameters */
+ r = BN_set_word(generator, DH_GENERATOR);
+ tor_assert(r);
/* This is from rfc2409, section 6.2. It's a safe prime, and
supposedly it equals:
2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
*/
- r = BN_hex2bn(&p,
+ r = BN_hex2bn(&circuit_dh_prime,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF");
tor_assert(r);
- /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
- * modules/ssl/ssl_engine_dh.c */
- r = BN_hex2bn(&p2,
- "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
- "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
- "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
- "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
- "B0E7393E0F24218EB3");
- tor_assert(r);
- r = BN_set_word(g, 2);
- tor_assert(r);
- dh_param_p = p;
- dh_param_p_tls = p2;
- dh_param_g = g;
+ /* Set the new values as the global DH parameters. */
+ dh_param_p = circuit_dh_prime;
+ dh_param_g = generator;
+
+ /* Should be already set by config.c. */
+ tor_assert(dh_param_p_tls);
}
/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 1a8c81f837..771c49c2d1 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -91,6 +91,8 @@ int crypto_global_cleanup(void);
crypto_pk_env_t *crypto_new_pk_env(void);
void crypto_free_pk_env(crypto_pk_env_t *env);
+void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname);
+
/* convenience function: wraps crypto_create_crypto_env, set_key, and init. */
crypto_cipher_env_t *crypto_create_init_cipher(const char *key,
int encrypt_mode);
@@ -150,6 +152,7 @@ int crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, char *to,
int crypto_pk_asn1_encode(crypto_pk_env_t *pk, char *dest, size_t dest_len);
crypto_pk_env_t *crypto_pk_asn1_decode(const char *str, size_t len);
int crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out);
+int crypto_pk_get_all_digests(crypto_pk_env_t *pk, digests_t *digests_out);
int crypto_pk_get_fingerprint(crypto_pk_env_t *pk, char *fp_out,int add_space);
int crypto_pk_check_fingerprint_syntax(const char *s);
@@ -195,6 +198,9 @@ void crypto_digest_assign(crypto_digest_env_t *into,
void crypto_hmac_sha1(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
+void crypto_hmac_sha256(char *hmac_out,
+ const char *key, size_t key_len,
+ const char *msg, size_t msg_len);
/* Key negotiation */
#define DH_TYPE_CIRCUIT 1
@@ -245,7 +251,8 @@ void secret_to_key(char *key_out, size_t key_out_len, const char *secret,
size_t secret_len, const char *s2k_specifier);
#ifdef CRYPTO_PRIVATE
-/* Prototypes for private functions only used by tortls.c and crypto.c */
+/* Prototypes for private functions only used by tortls.c, crypto.c, and the
+ * unit tests. */
struct rsa_st;
struct evp_pkey_st;
struct dh_st;
diff --git a/src/common/log.c b/src/common/log.c
index ac98f13539..97400623e5 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -154,6 +154,17 @@ log_set_application_name(const char *name)
appname = name ? tor_strdup(name) : NULL;
}
+/** Log time granularity in milliseconds. */
+static int log_time_granularity = 1;
+
+/** Define log time granularity for all logs to be <b>granularity_msec</b>
+ * milliseconds. */
+void
+set_log_time_granularity(int granularity_msec)
+{
+ log_time_granularity = granularity_msec;
+}
+
/** Helper: Write the standard prefix for log lines to a
* <b>buf_len</b> character buffer in <b>buf</b>.
*/
@@ -164,14 +175,22 @@ _log_prefix(char *buf, size_t buf_len, int severity)
struct timeval now;
struct tm tm;
size_t n;
- int r;
+ int r, ms;
tor_gettimeofday(&now);
t = (time_t)now.tv_sec;
+ ms = (int)now.tv_usec / 1000;
+ if (log_time_granularity >= 1000) {
+ t -= t % (log_time_granularity / 1000);
+ ms = 0;
+ } else {
+ ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
+ }
n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
- r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ",
- (int)now.tv_usec / 1000, sev_to_string(severity));
+ r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
+ sev_to_string(severity));
+
if (r<0)
return buf_len-1;
else
@@ -703,7 +722,7 @@ change_callback_log_severity(int loglevelMin, int loglevelMax,
UNLOCK_LOGS();
}
-/** If there are any log messages that were genered with LD_NOCB waiting to
+/** If there are any log messages that were generated with LD_NOCB waiting to
* be sent to callback-based loggers, send them now. */
void
flush_pending_log_callbacks(void)
@@ -803,7 +822,7 @@ add_file_log(const log_severity_list_t *severity, const char *filename)
int fd;
logfile_t *lf;
- fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
if (fd<0)
return -1;
if (tor_fd_seekend(fd)<0)
@@ -880,7 +899,7 @@ log_level_to_string(int level)
static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
"HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
- "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", NULL
+ "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL
};
/** Return a bitmask for the log domain for which <b>domain</b> is the name,
diff --git a/src/common/mempool.c b/src/common/mempool.c
index c444923189..1462c5f8fe 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -62,7 +62,6 @@
#if 1
/* Tor dependencies */
-#include "orconfig.h"
#include "util.h"
#include "compat.h"
#include "torlog.h"
@@ -137,7 +136,7 @@ struct mp_chunk_t {
int capacity; /**< Number of items that can be fit into this chunk. */
size_t mem_size; /**< Number of usable bytes in mem. */
char *next_mem; /**< Pointer into part of <b>mem</b> not yet carved up. */
- char mem[1]; /**< Storage for this chunk. (Not actual size.) */
+ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< Storage for this chunk. */
};
/** Number of extra bytes needed beyond mem_size to allocate a chunk. */
diff --git a/src/common/torgzip.c b/src/common/torgzip.c
index a26e5b21e5..62e4a07035 100644
--- a/src/common/torgzip.c
+++ b/src/common/torgzip.c
@@ -44,11 +44,7 @@
#define off64_t int64_t
#endif
-#ifdef _MSC_VER
-#include "..\..\contrib\zlib\zlib.h"
-#else
#include <zlib.h>
-#endif
/** Set to 1 if zlib is a version that supports gzip; set to 0 if it doesn't;
* set to -1 if we haven't checked yet. */
diff --git a/src/common/torint.h b/src/common/torint.h
index 0b5c29adc0..af975471f1 100644
--- a/src/common/torint.h
+++ b/src/common/torint.h
@@ -111,6 +111,15 @@ typedef signed int int32_t;
typedef unsigned int uint32_t;
#define HAVE_UINT32_T
#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX 0xffffu
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX 0x7fff
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-INT16_MAX-1)
+#endif
#ifndef UINT32_MAX
#define UINT32_MAX 0xffffffffu
#endif
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 541a0d1738..4c5729ef53 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -92,8 +92,10 @@
#define LD_HIST (1u<<18)
/** OR handshaking */
#define LD_HANDSHAKE (1u<<19)
+/** Heartbeat messages */
+#define LD_HEARTBEAT (1u<<20)
/** Number of logging domains in the code. */
-#define N_LOGGING_DOMAINS 20
+#define N_LOGGING_DOMAINS 21
/** This log message is not safe to send to a callback-based logger
* immediately. Used as a flag, not a log domain. */
@@ -145,6 +147,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
log_callback cb);
void flush_pending_log_callbacks(void);
void log_set_application_name(const char *name);
+void set_log_time_granularity(int granularity_msec);
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
CHECK_PRINTF(3,4);
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 10f4440cb4..18f2684707 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -22,8 +22,12 @@
#include <assert.h>
#ifdef MS_WINDOWS /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
+ #ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+ #endif
+ #ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+ #endif
#define WIN32_LEAN_AND_MEAN
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#include <winsock.h>
@@ -44,15 +48,22 @@
#error "We require OpenSSL >= 0.9.7"
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#include <event2/buffer.h>
+#include <event2/event.h>
+#endif
+
#define CRYPTO_PRIVATE /* to import prototypes from crypto.h */
+#define TORTLS_PRIVATE
#include "crypto.h"
#include "tortls.h"
#include "util.h"
#include "torlog.h"
#include "container.h"
-#include "ht.h"
#include <string.h>
+#include "compat_libevent.h"
/* Enable the "v2" TLS handshake.
*/
@@ -86,22 +97,36 @@ static int use_unsafe_renegotiation_op = 0;
* SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */
static int use_unsafe_renegotiation_flag = 0;
+/** Structure that we use for a single certificate. */
+struct tor_cert_t {
+ X509 *cert;
+ uint8_t *encoded;
+ size_t encoded_len;
+ unsigned pkey_digests_set : 1;
+ digests_t cert_digests;
+ digests_t pkey_digests;
+};
+
/** Holds a SSL_CTX object and related state used to configure TLS
* connections.
*/
typedef struct tor_tls_context_t {
int refcnt;
SSL_CTX *ctx;
- X509 *my_cert;
- X509 *my_id_cert;
- crypto_pk_env_t *key;
+ tor_cert_t *my_link_cert;
+ tor_cert_t *my_id_cert;
+ tor_cert_t *my_auth_cert;
+ crypto_pk_env_t *link_key;
+ crypto_pk_env_t *auth_key;
} tor_tls_context_t;
+#define TOR_TLS_MAGIC 0x71571571
+
/** Holds a SSL object and its associated data. Members are only
* accessed from within tortls.c.
*/
struct tor_tls_t {
- HT_ENTRY(tor_tls_t) node;
+ uint32_t magic;
tor_tls_context_t *context; /** A link to the context object for this tls. */
SSL *ssl; /**< An OpenSSL SSL object. */
int socket; /**< The underlying file descriptor for this TLS connection. */
@@ -109,6 +134,7 @@ struct tor_tls_t {
enum {
TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE,
+ TOR_TLS_ST_BUFFEREVENT
} state : 3; /**< The current SSL state, depending on which operations have
* completed successfully. */
unsigned int isServer:1; /**< True iff this is a server-side connection */
@@ -117,8 +143,10 @@ struct tor_tls_t {
* of the connection protocol (client sends
* different cipher list, server sends only
* one certificate). */
- /** True iff we should call negotiated_callback when we're done reading. */
+ /** True iff we should call negotiated_callback when we're done reading. */
unsigned int got_renegotiate:1;
+ /** Incremented every time we start the server side of a handshake. */
+ unsigned int server_handshake_count:2;
size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
* time. */
/** Last values retrieved from BIO_number_read()/write(); see
@@ -129,6 +157,11 @@ struct tor_tls_t {
/** If set, a callback to invoke whenever the client tries to renegotiate
* the handshake. */
void (*negotiated_callback)(tor_tls_t *tls, void *arg);
+
+ /** Callback to invoke whenever a client tries to renegotiate more
+ than once. */
+ void (*excess_renegotiations_callback)(void *);
+
/** Argument to pass to negotiated_callback. */
void *callback_arg;
};
@@ -143,42 +176,29 @@ static SSL_CIPHER *CLIENT_CIPHER_DUMMIES = NULL;
static STACK_OF(SSL_CIPHER) *CLIENT_CIPHER_STACK = NULL;
#endif
-/** Helper: compare tor_tls_t objects by its SSL. */
-static INLINE int
-tor_tls_entries_eq(const tor_tls_t *a, const tor_tls_t *b)
-{
- return a->ssl == b->ssl;
-}
+/** The ex_data index in which we store a pointer to an SSL object's
+ * corresponding tor_tls_t object. */
+static int tor_tls_object_ex_data_index = -1;
-/** Helper: return a hash value for a tor_tls_t by its SSL. */
-static INLINE unsigned int
-tor_tls_entry_hash(const tor_tls_t *a)
+/** Helper: Allocate tor_tls_object_ex_data_index. */
+static void
+tor_tls_allocate_tor_tls_object_ex_data_index(void)
{
-#if SIZEOF_INT == SIZEOF_VOID_P
- return ((unsigned int)(uintptr_t)a->ssl);
-#else
- return (unsigned int) ((((uint64_t)a->ssl)>>2) & UINT_MAX);
-#endif
+ if (tor_tls_object_ex_data_index == -1) {
+ tor_tls_object_ex_data_index =
+ SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ tor_assert(tor_tls_object_ex_data_index != -1);
+ }
}
-/** Map from SSL* pointers to tor_tls_t objects using those pointers.
- */
-static HT_HEAD(tlsmap, tor_tls_t) tlsmap_root = HT_INITIALIZER();
-
-HT_PROTOTYPE(tlsmap, tor_tls_t, node, tor_tls_entry_hash,
- tor_tls_entries_eq)
-HT_GENERATE(tlsmap, tor_tls_t, node, tor_tls_entry_hash,
- tor_tls_entries_eq, 0.6, malloc, realloc, free)
-
/** Helper: given a SSL* pointer, return the tor_tls_t object using that
* pointer. */
static INLINE tor_tls_t *
tor_tls_get_by_ssl(const SSL *ssl)
{
- tor_tls_t search, *result;
- memset(&search, 0, sizeof(search));
- search.ssl = (SSL*)ssl;
- result = HT_FIND(tlsmap, &tlsmap_root, &search);
+ tor_tls_t *result = SSL_get_ex_data(ssl, tor_tls_object_ex_data_index);
+ if (result)
+ tor_assert(result->magic == TOR_TLS_MAGIC);
return result;
}
@@ -189,17 +209,22 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
const char *cname,
const char *cname_sign,
unsigned int lifetime);
-static void tor_tls_unblock_renegotiation(tor_tls_t *tls);
+
static int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
crypto_pk_env_t *identity,
- unsigned int key_lifetime);
+ unsigned int key_lifetime,
+ int is_client);
static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity,
- unsigned int key_lifetime);
+ unsigned int key_lifetime,
+ int is_client);
+static int check_cert_lifetime_internal(int severity, const X509 *cert,
+ int past_tolerance, int future_tolerance);
/** Global TLS contexts. We keep them here because nobody else needs
* to touch them. */
static tor_tls_context_t *server_tls_context = NULL;
static tor_tls_context_t *client_tls_context = NULL;
+
/** True iff tor_tls_init() has been called. */
static int tls_library_is_initialized = 0;
@@ -223,36 +248,96 @@ ssl_state_to_string(int ssl_state)
return buf;
}
+/** Write a description of the current state of <b>tls</b> into the
+ * <b>sz</b>-byte buffer at <b>buf</b>. */
+void
+tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz)
+{
+ const char *ssl_state;
+ const char *tortls_state;
+
+ if (PREDICT_UNLIKELY(!tls || !tls->ssl)) {
+ strlcpy(buf, "(No SSL object)", sz);
+ return;
+ }
+
+ ssl_state = ssl_state_to_string(tls->ssl->state);
+ switch (tls->state) {
+#define CASE(st) case TOR_TLS_ST_##st: tortls_state = " in "#st ; break
+ CASE(HANDSHAKE);
+ CASE(OPEN);
+ CASE(GOTCLOSE);
+ CASE(SENTCLOSE);
+ CASE(CLOSED);
+ CASE(RENEGOTIATE);
+#undef CASE
+ case TOR_TLS_ST_BUFFEREVENT:
+ tortls_state = "";
+ break;
+ default:
+ tortls_state = " in unknown TLS state";
+ break;
+ }
+
+ tor_snprintf(buf, sz, "%s%s", ssl_state, tortls_state);
+}
+
+void
+tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
+ int severity, int domain, const char *doing)
+{
+ const char *state = NULL, *addr;
+ const char *msg, *lib, *func;
+ int st;
+
+ st = (tls && tls->ssl) ? tls->ssl->state : -1;
+ state = (st>=0)?ssl_state_to_string(st):"---";
+
+ addr = tls ? tls->address : NULL;
+
+ /* Some errors are known-benign, meaning they are the fault of the other
+ * side of the connection. The caller doesn't know this, so override the
+ * priority for those cases. */
+ switch (ERR_GET_REASON(err)) {
+ case SSL_R_HTTP_REQUEST:
+ case SSL_R_HTTPS_PROXY_REQUEST:
+ case SSL_R_RECORD_LENGTH_MISMATCH:
+ case SSL_R_RECORD_TOO_LARGE:
+ case SSL_R_UNKNOWN_PROTOCOL:
+ case SSL_R_UNSUPPORTED_PROTOCOL:
+ severity = LOG_INFO;
+ break;
+ default:
+ break;
+ }
+
+ msg = (const char*)ERR_reason_error_string(err);
+ lib = (const char*)ERR_lib_error_string(err);
+ func = (const char*)ERR_func_error_string(err);
+ if (!msg) msg = "(null)";
+ if (!lib) lib = "(null)";
+ if (!func) func = "(null)";
+ if (doing) {
+ log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
+ doing, addr?" with ":"", addr?addr:"",
+ msg, lib, func, state);
+ } else {
+ log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
+ addr?" with ":"", addr?addr:"",
+ msg, lib, func, state);
+ }
+}
+
/** Log all pending tls errors at level <b>severity</b>. Use
* <b>doing</b> to describe our current activities.
*/
static void
tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
{
- const char *state = NULL;
- int st;
unsigned long err;
- const char *msg, *lib, *func, *addr;
- addr = tls ? tls->address : NULL;
- st = (tls && tls->ssl) ? tls->ssl->state : -1;
+
while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!state)
- state = (st>=0)?ssl_state_to_string(st):"---";
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (doing) {
- log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
- doing, addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- } else {
- log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
- addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- }
+ tor_tls_log_one_error(tls, err, severity, domain, doing);
}
}
@@ -427,6 +512,8 @@ tor_tls_init(void)
SSLeay_version(SSLEAY_VERSION), version);
}
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
tls_library_is_initialized = 1;
}
}
@@ -445,10 +532,6 @@ tor_tls_free_all(void)
client_tls_context = NULL;
tor_tls_context_decref(ctx);
}
- if (!HT_EMPTY(&tlsmap_root)) {
- log_warn(LD_MM, "Still have entries in the tlsmap at shutdown.");
- }
- HT_CLEAR(tlsmap, &tlsmap_root);
#ifdef V2_HANDSHAKE_CLIENT
if (CLIENT_CIPHER_DUMMIES)
tor_free(CLIENT_CIPHER_DUMMIES);
@@ -502,7 +585,13 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
const char *cname_sign,
unsigned int cert_lifetime)
{
+ /* OpenSSL generates self-signed certificates with random 64-bit serial
+ * numbers, so let's do that too. */
+#define SERIAL_NUMBER_SIZE 8
+
time_t start_time, end_time;
+ BIGNUM *serial_number = NULL;
+ unsigned char serial_tmp[SERIAL_NUMBER_SIZE];
EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
X509 *x509 = NULL;
X509_NAME *name = NULL, *name_issuer=NULL;
@@ -523,8 +612,15 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
goto error;
if (!(X509_set_version(x509, 2)))
goto error;
- if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time)))
- goto error;
+
+ { /* our serial number is 8 random bytes. */
+ if (crypto_rand((char *)serial_tmp, sizeof(serial_tmp)) < 0)
+ goto error;
+ if (!(serial_number = BN_bin2bn(serial_tmp, sizeof(serial_tmp), NULL)))
+ goto error;
+ if (!(BN_to_ASN1_INTEGER(serial_number, X509_get_serialNumber(x509))))
+ goto error;
+ }
if (!(name = tor_x509_name_new(cname)))
goto error;
@@ -557,11 +653,15 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
EVP_PKEY_free(sign_pkey);
if (pkey)
EVP_PKEY_free(pkey);
+ if (serial_number)
+ BN_free(serial_number);
if (name)
X509_NAME_free(name);
if (name_issuer)
X509_NAME_free(name_issuer);
return x509;
+
+#undef SERIAL_NUMBER_SIZE
}
/** List of ciphers that servers should select from.*/
@@ -608,6 +708,137 @@ static const int N_CLIENT_CIPHERS =
SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA)
#endif
+/** Free all storage held in <b>cert</b> */
+void
+tor_cert_free(tor_cert_t *cert)
+{
+ if (! cert)
+ return;
+ if (cert->cert)
+ X509_free(cert->cert);
+ tor_free(cert->encoded);
+ memset(cert, 0x03, sizeof(*cert));
+ tor_free(cert);
+}
+
+/**
+ * Allocate a new tor_cert_t to hold the certificate "x509_cert".
+ *
+ * Steals a reference to x509_cert.
+ */
+static tor_cert_t *
+tor_cert_new(X509 *x509_cert)
+{
+ tor_cert_t *cert;
+ EVP_PKEY *pkey;
+ RSA *rsa;
+ int length, length2;
+ unsigned char *cp;
+
+ if (!x509_cert)
+ return NULL;
+
+ length = i2d_X509(x509_cert, NULL);
+ cert = tor_malloc_zero(sizeof(tor_cert_t));
+ if (length <= 0) {
+ tor_free(cert);
+ log_err(LD_CRYPTO, "Couldn't get length of encoded x509 certificate");
+ X509_free(x509_cert);
+ return NULL;
+ }
+ cert->encoded_len = (size_t) length;
+ cp = cert->encoded = tor_malloc(length);
+ length2 = i2d_X509(x509_cert, &cp);
+ tor_assert(length2 == length);
+
+ cert->cert = x509_cert;
+
+ crypto_digest_all(&cert->cert_digests,
+ (char*)cert->encoded, cert->encoded_len);
+
+ if ((pkey = X509_get_pubkey(x509_cert)) &&
+ (rsa = EVP_PKEY_get1_RSA(pkey))) {
+ crypto_pk_env_t *pk = _crypto_new_pk_env_rsa(rsa);
+ crypto_pk_get_all_digests(pk, &cert->pkey_digests);
+ cert->pkey_digests_set = 1;
+ crypto_free_pk_env(pk);
+ EVP_PKEY_free(pkey);
+ }
+
+ return cert;
+}
+
+/** Read a DER-encoded X509 cert, of length exactly <b>certificate_len</b>,
+ * from a <b>certificate</b>. Return a newly allocated tor_cert_t on success
+ * and NULL on failure. */
+tor_cert_t *
+tor_cert_decode(const uint8_t *certificate, size_t certificate_len)
+{
+ X509 *x509;
+ const unsigned char *cp = (const unsigned char *)certificate;
+ tor_cert_t *newcert;
+ tor_assert(certificate);
+
+ if (certificate_len > INT_MAX)
+ return NULL;
+
+#if OPENSSL_VERSION_NUMBER < 0x00908000l
+ /* This ifdef suppresses a type warning. Take out this case once everybody
+ * is using OpenSSL 0.9.8 or later. */
+ x509 = d2i_X509(NULL, (unsigned char**)&cp, (int)certificate_len);
+#else
+ x509 = d2i_X509(NULL, &cp, (int)certificate_len);
+#endif
+ if (!x509)
+ return NULL; /* Couldn't decode */
+ if (cp - certificate != (int)certificate_len) {
+ X509_free(x509);
+ return NULL; /* Didn't use all the bytes */
+ }
+ newcert = tor_cert_new(x509);
+ if (!newcert) {
+ return NULL;
+ }
+ if (newcert->encoded_len != certificate_len ||
+ fast_memneq(newcert->encoded, certificate, certificate_len)) {
+ /* Cert wasn't in DER */
+ tor_cert_free(newcert);
+ return NULL;
+ }
+ return newcert;
+}
+
+/** Set *<b>encoded_out</b> and *<b>size_out/b> to <b>cert</b>'s encoded DER
+ * representation and length, respectively. */
+void
+tor_cert_get_der(const tor_cert_t *cert,
+ const uint8_t **encoded_out, size_t *size_out)
+{
+ tor_assert(cert);
+ tor_assert(encoded_out);
+ tor_assert(size_out);
+ *encoded_out = cert->encoded;
+ *size_out = cert->encoded_len;
+}
+
+/** Return a set of digests for the public key in <b>cert</b>, or NULL if this
+ * cert's public key is not one we know how to take the digest of. */
+const digests_t *
+tor_cert_get_id_digests(const tor_cert_t *cert)
+{
+ if (cert->pkey_digests_set)
+ return &cert->pkey_digests;
+ else
+ return NULL;
+}
+
+/** Return a set of digests for the public key in <b>cert</b>. */
+const digests_t *
+tor_cert_get_cert_digests(const tor_cert_t *cert)
+{
+ return &cert->cert_digests;
+}
+
/** Remove a reference to <b>ctx</b>, and free it if it has no more
* references. */
static void
@@ -616,13 +847,172 @@ tor_tls_context_decref(tor_tls_context_t *ctx)
tor_assert(ctx);
if (--ctx->refcnt == 0) {
SSL_CTX_free(ctx->ctx);
- X509_free(ctx->my_cert);
- X509_free(ctx->my_id_cert);
- crypto_free_pk_env(ctx->key);
+ tor_cert_free(ctx->my_link_cert);
+ tor_cert_free(ctx->my_id_cert);
+ tor_cert_free(ctx->my_auth_cert);
+ crypto_free_pk_env(ctx->link_key);
+ crypto_free_pk_env(ctx->auth_key);
tor_free(ctx);
}
}
+/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
+ * and ID certificate that we're currently using for our V3 in-protocol
+ * handshake's certificate chain. If <b>server</b> is true, provide the certs
+ * that we use in server mode; otherwise, provide the certs that we use in
+ * client mode. */
+int
+tor_tls_get_my_certs(int server,
+ const tor_cert_t **link_cert_out,
+ const tor_cert_t **id_cert_out)
+{
+ tor_tls_context_t *ctx = server ? server_tls_context : client_tls_context;
+ if (! ctx)
+ return -1;
+ if (link_cert_out)
+ *link_cert_out = server ? ctx->my_link_cert : ctx->my_auth_cert;
+ if (id_cert_out)
+ *id_cert_out = ctx->my_id_cert;
+ return 0;
+}
+
+/**
+ * Return the authentication key that we use to authenticate ourselves as a
+ * client in the V3 in-protocol handshake.
+ */
+crypto_pk_env_t *
+tor_tls_get_my_client_auth_key(void)
+{
+ if (! client_tls_context)
+ return NULL;
+ return client_tls_context->auth_key;
+}
+
+/**
+ * Return a newly allocated copy of the public key that a certificate
+ * certifies. Return NULL if the cert's key is not RSA.
+ */
+crypto_pk_env_t *
+tor_tls_cert_get_key(tor_cert_t *cert)
+{
+ crypto_pk_env_t *result = NULL;
+ EVP_PKEY *pkey = X509_get_pubkey(cert->cert);
+ RSA *rsa;
+ if (!pkey)
+ return NULL;
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (!rsa) {
+ EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ result = _crypto_new_pk_env_rsa(rsa);
+ EVP_PKEY_free(pkey);
+ return result;
+}
+
+/** Return true iff <b>a</b> and <b>b</b> represent the same public key. */
+static int
+pkey_eq(EVP_PKEY *a, EVP_PKEY *b)
+{
+ /* We'd like to do this, but openssl 0.9.7 doesn't have it:
+ return EVP_PKEY_cmp(a,b) == 1;
+ */
+ unsigned char *a_enc=NULL, *b_enc=NULL, *a_ptr, *b_ptr;
+ int a_len1, b_len1, a_len2, b_len2, result;
+ a_len1 = i2d_PublicKey(a, NULL);
+ b_len1 = i2d_PublicKey(b, NULL);
+ if (a_len1 != b_len1)
+ return 0;
+ a_ptr = a_enc = tor_malloc(a_len1);
+ b_ptr = b_enc = tor_malloc(b_len1);
+ a_len2 = i2d_PublicKey(a, &a_ptr);
+ b_len2 = i2d_PublicKey(b, &b_ptr);
+ tor_assert(a_len2 == a_len1);
+ tor_assert(b_len2 == b_len1);
+ result = tor_memeq(a_enc, b_enc, a_len1);
+ tor_free(a_enc);
+ tor_free(b_enc);
+ return result;
+}
+
+/** Return true iff the other side of <b>tls</b> has authenticated to us, and
+ * the key certified in <b>cert</b> is the same as the key they used to do it.
+ */
+int
+tor_tls_cert_matches_key(const tor_tls_t *tls, const tor_cert_t *cert)
+{
+ X509 *peercert = SSL_get_peer_certificate(tls->ssl);
+ EVP_PKEY *link_key = NULL, *cert_key = NULL;
+ int result;
+
+ if (!peercert)
+ return 0;
+ link_key = X509_get_pubkey(peercert);
+ cert_key = X509_get_pubkey(cert->cert);
+
+ result = link_key && cert_key && pkey_eq(cert_key, link_key);
+
+ X509_free(peercert);
+ if (link_key)
+ EVP_PKEY_free(link_key);
+ if (cert_key)
+ EVP_PKEY_free(cert_key);
+
+ return result;
+}
+
+/** Check whether <b>cert</b> is well-formed, currently live, and correctly
+ * signed by the public key in <b>signing_cert</b>. If <b>check_rsa_1024</b>,
+ * make sure that it has an RSA key with 1024 bits; otherwise, just check that
+ * the key is long enough. Return 1 if the cert is good, and 0 if it's bad or
+ * we couldn't check it. */
+int
+tor_tls_cert_is_valid(int severity,
+ const tor_cert_t *cert,
+ const tor_cert_t *signing_cert,
+ int check_rsa_1024)
+{
+ EVP_PKEY *cert_key;
+ EVP_PKEY *signing_key = X509_get_pubkey(signing_cert->cert);
+ int r, key_ok = 0;
+ if (!signing_key)
+ return 0;
+ r = X509_verify(cert->cert, signing_key);
+ EVP_PKEY_free(signing_key);
+ if (r <= 0)
+ return 0;
+
+ /* okay, the signature checked out right. Now let's check the check the
+ * lifetime. */
+ if (check_cert_lifetime_internal(severity, cert->cert,
+ 48*60*60, 30*24*60*60) < 0)
+ return 0;
+
+ cert_key = X509_get_pubkey(cert->cert);
+ if (check_rsa_1024 && cert_key) {
+ RSA *rsa = EVP_PKEY_get1_RSA(cert_key);
+ if (rsa && BN_num_bits(rsa->n) == 1024)
+ key_ok = 1;
+ if (rsa)
+ RSA_free(rsa);
+ } else if (cert_key) {
+ int min_bits = 1024;
+#ifdef EVP_PKEY_EC
+ if (EVP_PKEY_type(cert_key->type) == EVP_PKEY_EC)
+ min_bits = 128;
+#endif
+ if (EVP_PKEY_bits(cert_key) >= min_bits)
+ key_ok = 1;
+ }
+ EVP_PKEY_free(cert_key);
+ if (!key_ok)
+ return 0;
+
+ /* XXXX compare DNs or anything? */
+
+ return 1;
+}
+
/** Increase the reference count of <b>ctx</b>. */
static void
tor_tls_context_incref(tor_tls_context_t *ctx)
@@ -653,7 +1043,7 @@ tor_tls_context_init(int is_public_server,
rv1 = tor_tls_context_init_one(&server_tls_context,
server_identity,
- key_lifetime);
+ key_lifetime, 0);
if (rv1 >= 0) {
new_ctx = server_tls_context;
@@ -669,7 +1059,8 @@ tor_tls_context_init(int is_public_server,
if (server_identity != NULL) {
rv1 = tor_tls_context_init_one(&server_tls_context,
server_identity,
- key_lifetime);
+ key_lifetime,
+ 0);
} else {
tor_tls_context_t *old_ctx = server_tls_context;
server_tls_context = NULL;
@@ -681,7 +1072,8 @@ tor_tls_context_init(int is_public_server,
rv2 = tor_tls_context_init_one(&client_tls_context,
client_identity,
- key_lifetime);
+ key_lifetime,
+ 1);
}
return MIN(rv1, rv2);
@@ -696,10 +1088,12 @@ tor_tls_context_init(int is_public_server,
static int
tor_tls_context_init_one(tor_tls_context_t **ppcontext,
crypto_pk_env_t *identity,
- unsigned int key_lifetime)
+ unsigned int key_lifetime,
+ int is_client)
{
tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
- key_lifetime);
+ key_lifetime,
+ is_client);
tor_tls_context_t *old_ctx = *ppcontext;
if (new_ctx != NULL) {
@@ -721,39 +1115,61 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
* certificate.
*/
static tor_tls_context_t *
-tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
+tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime,
+ int is_client)
{
- crypto_pk_env_t *rsa = NULL;
+ crypto_pk_env_t *rsa = NULL, *rsa_auth = NULL;
EVP_PKEY *pkey = NULL;
tor_tls_context_t *result = NULL;
- X509 *cert = NULL, *idcert = NULL;
+ X509 *cert = NULL, *idcert = NULL, *authcert = NULL;
char *nickname = NULL, *nn2 = NULL;
tor_tls_init();
nickname = crypto_random_hostname(8, 20, "www.", ".net");
+#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE
nn2 = crypto_random_hostname(8, 20, "www.", ".net");
+#else
+ nn2 = crypto_random_hostname(8, 20, "www.", ".com");
+#endif
- /* Generate short-term RSA key. */
+ /* Generate short-term RSA key for use with TLS. */
if (!(rsa = crypto_new_pk_env()))
goto error;
if (crypto_pk_generate_key(rsa)<0)
goto error;
- /* Create certificate signed by identity key. */
- cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
- key_lifetime);
- /* Create self-signed certificate for identity key. */
- idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
- IDENTITY_CERT_LIFETIME);
- if (!cert || !idcert) {
- log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
- goto error;
+ if (!is_client) {
+ /* Generate short-term RSA key for use in the in-protocol ("v3")
+ * authentication handshake. */
+ if (!(rsa_auth = crypto_new_pk_env()))
+ goto error;
+ if (crypto_pk_generate_key(rsa_auth)<0)
+ goto error;
+ /* Create a link certificate signed by identity key. */
+ cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
+ key_lifetime);
+ /* Create self-signed certificate for identity key. */
+ idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
+ IDENTITY_CERT_LIFETIME);
+ /* Create an authentication certificate signed by identity key. */
+ authcert = tor_tls_create_certificate(rsa_auth, identity, nickname, nn2,
+ key_lifetime);
+ if (!cert || !idcert || !authcert) {
+ log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
+ goto error;
+ }
}
result = tor_malloc_zero(sizeof(tor_tls_context_t));
result->refcnt = 1;
- result->my_cert = X509_dup(cert);
- result->my_id_cert = X509_dup(idcert);
- result->key = crypto_pk_dup_key(rsa);
+ if (!is_client) {
+ result->my_link_cert = tor_cert_new(X509_dup(cert));
+ result->my_id_cert = tor_cert_new(X509_dup(idcert));
+ result->my_auth_cert = tor_cert_new(X509_dup(authcert));
+ if (!result->my_link_cert || !result->my_id_cert || !result->my_auth_cert)
+ goto error;
+ result->link_key = crypto_pk_dup_key(rsa);
+ result->auth_key = crypto_pk_dup_key(rsa_auth);
+ }
#ifdef EVERYONE_HAS_AES
/* Tell OpenSSL to only use TLS1 */
@@ -785,27 +1201,31 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
- if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
- goto error;
- X509_free(cert); /* We just added a reference to cert. */
- cert=NULL;
- if (idcert) {
- X509_STORE *s = SSL_CTX_get_cert_store(result->ctx);
- tor_assert(s);
- X509_STORE_add_cert(s, idcert);
- X509_free(idcert); /* The context now owns the reference to idcert */
- idcert = NULL;
+ if (! is_client) {
+ if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
+ goto error;
+ X509_free(cert); /* We just added a reference to cert. */
+ cert=NULL;
+ if (idcert) {
+ X509_STORE *s = SSL_CTX_get_cert_store(result->ctx);
+ tor_assert(s);
+ X509_STORE_add_cert(s, idcert);
+ X509_free(idcert); /* The context now owns the reference to idcert */
+ idcert = NULL;
+ }
}
SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
- tor_assert(rsa);
- if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
- goto error;
- if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
- goto error;
- EVP_PKEY_free(pkey);
- pkey = NULL;
- if (!SSL_CTX_check_private_key(result->ctx))
- goto error;
+ if (!is_client) {
+ tor_assert(rsa);
+ if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
+ goto error;
+ if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
+ goto error;
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ if (!SSL_CTX_check_private_key(result->ctx))
+ goto error;
+ }
{
crypto_dh_env_t *dh = crypto_dh_new(DH_TYPE_TLS);
tor_assert(dh);
@@ -819,6 +1239,9 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
if (rsa)
crypto_free_pk_env(rsa);
+ if (rsa_auth)
+ crypto_free_pk_env(rsa_auth);
+ X509_free(authcert);
tor_free(nickname);
tor_free(nn2);
return result;
@@ -831,12 +1254,16 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
EVP_PKEY_free(pkey);
if (rsa)
crypto_free_pk_env(rsa);
+ if (rsa_auth)
+ crypto_free_pk_env(rsa_auth);
if (result)
tor_tls_context_decref(result);
if (cert)
X509_free(cert);
if (idcert)
X509_free(idcert);
+ if (authcert)
+ X509_free(authcert);
return NULL;
}
@@ -892,45 +1319,49 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address)
return 1;
}
-/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
- * changes state. We use this:
- * <ul><li>To alter the state of the handshake partway through, so we
- * do not send or request extra certificates in v2 handshakes.</li>
- * <li>To detect renegotiation</li></ul>
- */
+/** We got an SSL ClientHello message. This might mean that the
+ * client wants to initiate a renegotiation and appropriate actions
+ * must be taken. */
static void
-tor_tls_server_info_callback(const SSL *ssl, int type, int val)
+tor_tls_got_client_hello(tor_tls_t *tls)
{
- tor_tls_t *tls;
- (void) val;
- if (type != SSL_CB_ACCEPT_LOOP)
- return;
- if (ssl->state != SSL3_ST_SW_SRVR_HELLO_A)
- return;
+ if (tls->server_handshake_count < 3)
+ ++tls->server_handshake_count;
- tls = tor_tls_get_by_ssl(ssl);
- if (tls) {
- /* Check whether we're watching for renegotiates. If so, this is one! */
- if (tls->negotiated_callback)
- tls->got_renegotiate = 1;
- } else {
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
+ if (tls->server_handshake_count == 2) {
+ if (!tls->negotiated_callback) {
+ log_warn(LD_BUG, "Got a renegotiation request but we don't"
+ " have a renegotiation callback set!");
+ }
+
+ tls->got_renegotiate = 1;
+ } else if (tls->server_handshake_count > 2 &&
+ tls->excess_renegotiations_callback) {
+ /* We got more than one renegotiation requests. The Tor protocol
+ needs just one renegotiation; more than that probably means
+ They are trying to DoS us and we have to stop them. */
+
+ tls->excess_renegotiations_callback(tls->callback_arg);
}
/* Now check the cipher list. */
- if (tor_tls_client_is_using_v2_ciphers(ssl, ADDR(tls))) {
+ if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
/*XXXX_TLS keep this from happening more than once! */
/* Yes, we're casting away the const from ssl. This is very naughty of us.
* Let's hope openssl doesn't notice! */
/* Set SSL_MODE_NO_AUTO_CHAIN to keep from sending back any extra certs. */
- SSL_set_mode((SSL*) ssl, SSL_MODE_NO_AUTO_CHAIN);
+ SSL_set_mode((SSL*) tls->ssl, SSL_MODE_NO_AUTO_CHAIN);
/* Don't send a hello request. */
- SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL);
+ SSL_set_verify((SSL*) tls->ssl, SSL_VERIFY_NONE, NULL);
if (tls) {
tls->wasV2Handshake = 1;
+#ifdef USE_BUFFEREVENTS
+ if (use_unsafe_renegotiation_flag)
+ tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+#endif
} else {
log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
}
@@ -938,6 +1369,34 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
}
#endif
+/** This is a callback function for SSL_set_info_callback() and it
+ * will be called in every SSL state change.
+ * It logs the SSL state change, and executes any actions that must be
+ * taken. */
+static void
+tor_tls_state_changed_callback(const SSL *ssl, int type, int val)
+{
+ log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].",
+ ssl, ssl_state_to_string(ssl->state), type, val);
+
+#ifdef V2_HANDSHAKE_SERVER
+ if (type == SSL_CB_ACCEPT_LOOP &&
+ ssl->state == SSL3_ST_SW_SRVR_HELLO_A) {
+
+ /* Call tor_tls_got_client_hello() for every SSL ClientHello we
+ receive. */
+
+ tor_tls_t *tls = tor_tls_get_by_ssl(ssl);
+ if (!tls) {
+ log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
+ return;
+ }
+
+ tor_tls_got_client_hello(tls);
+ }
+#endif
+}
+
/** Replace *<b>ciphers</b> with a new list of SSL ciphersuites: specifically,
* a list designed to mimic a common web browser. Some of the ciphers in the
* list won't actually be implemented by OpenSSL: that's okay so long as the
@@ -1018,6 +1477,7 @@ tor_tls_new(int sock, int isServer)
tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
tor_tls_context_t *context = isServer ? server_tls_context :
client_tls_context;
+ result->magic = TOR_TLS_MAGIC;
tor_assert(context); /* make sure somebody made it first */
if (!(result->ssl = SSL_new(context->ctx))) {
@@ -1058,7 +1518,14 @@ tor_tls_new(int sock, int isServer)
tor_free(result);
return NULL;
}
- HT_INSERT(tlsmap, &tlsmap_root, result);
+ {
+ int set_worked =
+ SSL_set_ex_data(result->ssl, tor_tls_object_ex_data_index, result);
+ if (!set_worked) {
+ log_warn(LD_BUG,
+ "Couldn't set the tls for an SSL*; connection will fail");
+ }
+ }
SSL_set_bio(result->ssl, bio, bio);
tor_tls_context_incref(context);
result->context = context;
@@ -1071,11 +1538,8 @@ tor_tls_new(int sock, int isServer)
log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu",
result->last_read_count, result->last_write_count);
}
-#ifdef V2_HANDSHAKE_SERVER
- if (isServer) {
- SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
- }
-#endif
+
+ SSL_set_info_callback(result->ssl, tor_tls_state_changed_callback);
/* Not expected to get called. */
tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object");
@@ -1093,31 +1557,28 @@ tor_tls_set_logged_address(tor_tls_t *tls, const char *address)
tls->address = tor_strdup(address);
}
-/** Set <b>cb</b> to be called with argument <b>arg</b> whenever <b>tls</b>
- * next gets a client-side renegotiate in the middle of a read. Do not
- * invoke this function until <em>after</em> initial handshaking is done!
+/** Set <b>cb</b> to be called with argument <b>arg</b> whenever
+ * <b>tls</b> next gets a client-side renegotiate in the middle of a
+ * read. Set <b>cb2</b> to be called with argument <b>arg</b> whenever
+ * <b>tls</b> gets excess renegotiation requests. Do not invoke this
+ * function until <em>after</em> initial handshaking is done!
*/
void
-tor_tls_set_renegotiate_callback(tor_tls_t *tls,
+tor_tls_set_renegotiate_callbacks(tor_tls_t *tls,
void (*cb)(tor_tls_t *, void *arg),
+ void (*cb2)(void *),
void *arg)
{
tls->negotiated_callback = cb;
+ tls->excess_renegotiations_callback = cb2;
tls->callback_arg = arg;
tls->got_renegotiate = 0;
-#ifdef V2_HANDSHAKE_SERVER
- if (cb) {
- SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(tls->ssl, NULL);
- }
-#endif
}
/** If this version of openssl requires it, turn on renegotiation on
* <b>tls</b>.
*/
-static void
+void
tor_tls_unblock_renegotiation(tor_tls_t *tls)
{
/* Yes, we know what we are doing here. No, we do not treat a renegotiation
@@ -1131,14 +1592,17 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls)
}
}
-/** If this version of openssl supports it, turn off renegotiation on
- * <b>tls</b>. (Our protocol never requires this for security, but it's nice
- * to use belt-and-suspenders here.)
- */
void
-tor_tls_block_renegotiation(tor_tls_t *tls)
+tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
{
- tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+ if (use_unsafe_renegotiation_flag) {
+ tor_assert(0 != (tls->ssl->s3->flags &
+ SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+ }
+ if (use_unsafe_renegotiation_op) {
+ long options = SSL_get_options(tls->ssl);
+ tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+ }
}
/** Return whether this tls initiated the connect (client) or
@@ -1156,23 +1620,20 @@ tor_tls_is_server(tor_tls_t *tls)
void
tor_tls_free(tor_tls_t *tls)
{
- tor_tls_t *removed;
if (!tls)
return;
tor_assert(tls->ssl);
- removed = HT_REMOVE(tlsmap, &tlsmap_root, tls);
- if (!removed) {
- log_warn(LD_BUG, "Freeing a TLS that was not in the ssl->tls map.");
- }
#ifdef SSL_set_tlsext_host_name
SSL_set_tlsext_host_name(tls->ssl, NULL);
#endif
SSL_free(tls->ssl);
tls->ssl = NULL;
tls->negotiated_callback = NULL;
+ tls->excess_renegotiations_callback = NULL;
if (tls->context)
tor_tls_context_decref(tls->context);
tor_free(tls->address);
+ tls->magic = 0x99999999;
tor_free(tls);
}
@@ -1190,19 +1651,30 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len)
tor_assert(tls->state == TOR_TLS_ST_OPEN);
tor_assert(len<INT_MAX);
r = SSL_read(tls->ssl, cp, (int)len);
- if (r > 0) {
+ if (r > 0) /* return the number of characters read */
+ return r;
+
+ /* If we got here, SSL_read() did not go as expected. */
+
+ err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
+
#ifdef V2_HANDSHAKE_SERVER
- if (tls->got_renegotiate) {
- /* Renegotiation happened! */
- log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
- if (tls->negotiated_callback)
- tls->negotiated_callback(tls, tls->callback_arg);
- tls->got_renegotiate = 0;
+ if (tls->got_renegotiate) {
+ if (tls->server_handshake_count != 2) {
+ log_warn(LD_BUG, "We did not notice renegotiation in a timely "
+ "fashion (%u)!", tls->server_handshake_count);
}
-#endif
+
+ /* Renegotiation happened! */
+ log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
+ if (tls->negotiated_callback)
+ tls->negotiated_callback(tls, tls->callback_arg);
+ tls->got_renegotiate = 0;
+
return r;
}
- err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
+#endif
+
if (err == _TOR_TLS_ZERORETURN || err == TOR_TLS_CLOSE) {
log_debug(LD_NET,"read returned r=%d; TLS is closed",r);
tls->state = TOR_TLS_ST_CLOSED;
@@ -1239,6 +1711,7 @@ tor_tls_write(tor_tls_t *tls, const char *cp, size_t n)
}
r = SSL_write(tls->ssl, cp, (int)n);
err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET);
+
if (err == TOR_TLS_DONE) {
return r;
}
@@ -1285,56 +1758,85 @@ tor_tls_handshake(tor_tls_t *tls)
}
if (r == TOR_TLS_DONE) {
tls->state = TOR_TLS_ST_OPEN;
- if (tls->isServer) {
- SSL_set_info_callback(tls->ssl, NULL);
- SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
- /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
- tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
+ return tor_tls_finish_handshake(tls);
+ }
+ return r;
+}
+
+/** Perform the final part of the intial TLS handshake on <b>tls</b>. This
+ * should be called for the first handshake only: it determines whether the v1
+ * or the v2 handshake was used, and adjusts things for the renegotiation
+ * handshake as appropriate.
+ *
+ * tor_tls_handshake() calls this on its own; you only need to call this if
+ * bufferevent is doing the handshake for you.
+ */
+int
+tor_tls_finish_handshake(tor_tls_t *tls)
+{
+ int r = TOR_TLS_DONE;
+ if (tls->isServer) {
+ SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
+ /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
+ tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
#ifdef V2_HANDSHAKE_SERVER
- if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
- /* This check is redundant, but back when we did it in the callback,
- * we might have not been able to look up the tor_tls_t if the code
- * was buggy. Fixing that. */
- if (!tls->wasV2Handshake) {
- log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
- " get set. Fixing that.");
- }
- tls->wasV2Handshake = 1;
- log_debug(LD_HANDSHAKE,
- "Completed V2 TLS handshake with client; waiting "
- "for renegotiation.");
- } else {
- tls->wasV2Handshake = 0;
+ if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
+ /* This check is redundant, but back when we did it in the callback,
+ * we might have not been able to look up the tor_tls_t if the code
+ * was buggy. Fixing that. */
+ if (!tls->wasV2Handshake) {
+ log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
+ " get set. Fixing that.");
}
-#endif
+ tls->wasV2Handshake = 1;
+ log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
+ " for renegotiation.");
} else {
+ tls->wasV2Handshake = 0;
+ }
+#endif
+ } else {
#ifdef V2_HANDSHAKE_CLIENT
- /* If we got no ID cert, we're a v2 handshake. */
- X509 *cert = SSL_get_peer_certificate(tls->ssl);
- STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
- int n_certs = sk_X509_num(chain);
- if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
- log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
- "looks like a v1 handshake on %p", tls);
- tls->wasV2Handshake = 0;
- } else {
- log_debug(LD_HANDSHAKE,
- "Server sent back a single certificate; looks like "
- "a v2 handshake on %p.", tls);
- tls->wasV2Handshake = 1;
- }
- if (cert)
- X509_free(cert);
+ /* If we got no ID cert, we're a v2 handshake. */
+ X509 *cert = SSL_get_peer_certificate(tls->ssl);
+ STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
+ int n_certs = sk_X509_num(chain);
+ if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
+ log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
+ "looks like a v1 handshake on %p", tls);
+ tls->wasV2Handshake = 0;
+ } else {
+ log_debug(LD_HANDSHAKE,
+ "Server sent back a single certificate; looks like "
+ "a v2 handshake on %p.", tls);
+ tls->wasV2Handshake = 1;
+ }
+ if (cert)
+ X509_free(cert);
#endif
- if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
- tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
- r = TOR_TLS_ERROR_MISC;
- }
+ if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
+ tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
+ r = TOR_TLS_ERROR_MISC;
}
}
return r;
}
+#ifdef USE_BUFFEREVENTS
+/** Put <b>tls</b>, which must be a client connection, into renegotiation
+ * mode. */
+int
+tor_tls_start_renegotiating(tor_tls_t *tls)
+{
+ int r = SSL_renegotiate(tls->ssl);
+ if (r <= 0) {
+ return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN,
+ LD_HANDSHAKE);
+ }
+ return 0;
+}
+#endif
+
/** Client only: Renegotiate a TLS session. When finished, returns
* TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or
* TOR_TLS_WANTWRITE.
@@ -1440,9 +1942,21 @@ tor_tls_peer_has_cert(tor_tls_t *tls)
return 1;
}
+/** Return the peer certificate, or NULL if there isn't one. */
+tor_cert_t *
+tor_tls_get_peer_cert(tor_tls_t *tls)
+{
+ X509 *cert;
+ cert = SSL_get_peer_certificate(tls->ssl);
+ tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
+ if (!cert)
+ return NULL;
+ return tor_cert_new(cert);
+}
+
/** Warn that a certificate lifetime extends through a certain range. */
static void
-log_cert_lifetime(X509 *cert, const char *problem)
+log_cert_lifetime(int severity, const X509 *cert, const char *problem)
{
BIO *bio = NULL;
BUF_MEM *buf;
@@ -1452,9 +1966,10 @@ log_cert_lifetime(X509 *cert, const char *problem)
struct tm tm;
if (problem)
- log_warn(LD_GENERAL,
- "Certificate %s: is your system clock set incorrectly?",
- problem);
+ log(severity, LD_GENERAL,
+ "Certificate %s. Either their clock is set wrong, or your clock "
+ "is wrong.",
+ problem);
if (!(bio = BIO_new(BIO_s_mem()))) {
log_warn(LD_GENERAL, "Couldn't allocate BIO!"); goto end;
@@ -1476,9 +1991,9 @@ log_cert_lifetime(X509 *cert, const char *problem)
strftime(mytime, 32, "%b %d %H:%M:%S %Y GMT", tor_gmtime_r(&now, &tm));
- log_warn(LD_GENERAL,
- "(certificate lifetime runs from %s through %s. Your time is %s.)",
- s1,s2,mytime);
+ log(severity, LD_GENERAL,
+ "(certificate lifetime runs from %s through %s. Your time is %s.)",
+ s1,s2,mytime);
end:
/* Not expected to get invoked */
@@ -1551,6 +2066,8 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key)
log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
goto done;
}
+ tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");
+
if (!(id_pkey = X509_get_pubkey(id_cert)) ||
X509_verify(cert, id_pkey) <= 0) {
log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
@@ -1578,34 +2095,25 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key)
return r;
}
-/** Check whether the certificate set on the connection <b>tls</b> is
- * expired or not-yet-valid, give or take <b>tolerance</b>
- * seconds. Return 0 for valid, -1 for failure.
+/** Check whether the certificate set on the connection <b>tls</b> is expired
+ * give or take <b>past_tolerance</b> seconds, or not-yet-valid give or take
+ * <b>future_tolerance</b> seconds. Return 0 for valid, -1 for failure.
*
* NOTE: you should call tor_tls_verify before tor_tls_check_lifetime.
*/
int
-tor_tls_check_lifetime(tor_tls_t *tls, int tolerance)
+tor_tls_check_lifetime(int severity, tor_tls_t *tls,
+ int past_tolerance, int future_tolerance)
{
- time_t now, t;
X509 *cert;
int r = -1;
- now = time(NULL);
-
if (!(cert = SSL_get_peer_certificate(tls->ssl)))
goto done;
- t = now + tolerance;
- if (X509_cmp_time(X509_get_notBefore(cert), &t) > 0) {
- log_cert_lifetime(cert, "not yet valid");
- goto done;
- }
- t = now - tolerance;
- if (X509_cmp_time(X509_get_notAfter(cert), &t) < 0) {
- log_cert_lifetime(cert, "already expired");
+ if (check_cert_lifetime_internal(severity, cert,
+ past_tolerance, future_tolerance) < 0)
goto done;
- }
r = 0;
done:
@@ -1617,6 +2125,32 @@ tor_tls_check_lifetime(tor_tls_t *tls, int tolerance)
return r;
}
+/** Helper: check whether <b>cert</b> is expired give or take
+ * <b>past_tolerance</b> seconds, or not-yet-valid give or take
+ * <b>future_tolerance</b> seconds. If it is live, return 0. If it is not
+ * live, log a message and return -1. */
+static int
+check_cert_lifetime_internal(int severity, const X509 *cert,
+ int past_tolerance, int future_tolerance)
+{
+ time_t now, t;
+
+ now = time(NULL);
+
+ t = now + future_tolerance;
+ if (X509_cmp_time(X509_get_notBefore(cert), &t) > 0) {
+ log_cert_lifetime(severity, cert, "not yet valid");
+ return -1;
+ }
+ t = now - past_tolerance;
+ if (X509_cmp_time(X509_get_notAfter(cert), &t) < 0) {
+ log_cert_lifetime(severity, cert, "already expired");
+ return -1;
+ }
+
+ return 0;
+}
+
/** Return the number of bytes available for reading from <b>tls</b>.
*/
int
@@ -1700,6 +2234,138 @@ tor_tls_used_v1_handshake(tor_tls_t *tls)
return 1;
}
+/** Return true iff <b>name</b> is a DN of a kind that could only
+ * occur in a v3-handshake-indicating certificate */
+static int
+dn_indicates_v3_cert(X509_NAME *name)
+{
+#ifdef DISABLE_V3_LINKPROTO_CLIENTSIDE
+ (void)name;
+ return 0;
+#else
+ X509_NAME_ENTRY *entry;
+ int n_entries;
+ ASN1_OBJECT *obj;
+ ASN1_STRING *str;
+ unsigned char *s;
+ int len, r;
+
+ n_entries = X509_NAME_entry_count(name);
+ if (n_entries != 1)
+ return 1; /* More than one entry in the DN. */
+ entry = X509_NAME_get_entry(name, 0);
+
+ obj = X509_NAME_ENTRY_get_object(entry);
+ if (OBJ_obj2nid(obj) != OBJ_txt2nid("commonName"))
+ return 1; /* The entry isn't a commonName. */
+
+ str = X509_NAME_ENTRY_get_data(entry);
+ len = ASN1_STRING_to_UTF8(&s, str);
+ if (len < 0)
+ return 0;
+ r = fast_memneq(s + len - 4, ".net", 4);
+ OPENSSL_free(s);
+ return r;
+#endif
+}
+
+/** Return true iff the peer certificate we're received on <b>tls</b>
+ * indicates that this connection should use the v3 (in-protocol)
+ * authentication handshake.
+ *
+ * Only the connection initiator should use this, and only once the initial
+ * handshake is done; the responder detects a v1 handshake by cipher types,
+ * and a v3/v2 handshake by Versions cell vs renegotiation.
+ */
+int
+tor_tls_received_v3_certificate(tor_tls_t *tls)
+{
+ X509 *cert = SSL_get_peer_certificate(tls->ssl);
+ EVP_PKEY *key = NULL;
+ X509_NAME *issuer_name, *subject_name;
+ int is_v3 = 0;
+
+ if (!cert) {
+ log_warn(LD_BUG, "Called on a connection with no peer certificate");
+ goto done;
+ }
+
+ subject_name = X509_get_subject_name(cert);
+ issuer_name = X509_get_issuer_name(cert);
+
+ if (X509_name_cmp(subject_name, issuer_name) == 0) {
+ is_v3 = 1; /* purportedly self signed */
+ goto done;
+ }
+
+ if (dn_indicates_v3_cert(subject_name) ||
+ dn_indicates_v3_cert(issuer_name)) {
+ is_v3 = 1; /* DN is fancy */
+ goto done;
+ }
+
+ key = X509_get_pubkey(cert);
+ if (EVP_PKEY_bits(key) != 1024 ||
+ EVP_PKEY_type(key->type) != EVP_PKEY_RSA) {
+ is_v3 = 1; /* Key is fancy */
+ goto done;
+ }
+
+ done:
+ if (key)
+ EVP_PKEY_free(key);
+ if (cert)
+ X509_free(cert);
+
+ return is_v3;
+}
+
+/** Return the number of server handshakes that we've noticed doing on
+ * <b>tls</b>. */
+int
+tor_tls_get_num_server_handshakes(tor_tls_t *tls)
+{
+ return tls->server_handshake_count;
+}
+
+/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
+ * request it was waiting for. */
+int
+tor_tls_server_got_renegotiate(tor_tls_t *tls)
+{
+ return tls->got_renegotiate;
+}
+
+/** Set the DIGEST256_LEN buffer at <b>secrets_out</b> to the value used in
+ * the v3 handshake to prove that the client knows the TLS secrets for the
+ * connection <b>tls</b>. Return 0 on success, -1 on failure.
+ */
+int
+tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out)
+{
+#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification"
+ char buf[128];
+ size_t len;
+ tor_assert(tls);
+ tor_assert(tls->ssl);
+ tor_assert(tls->ssl->s3);
+ tor_assert(tls->ssl->session);
+ /*
+ The value is an HMAC, using the TLS master key as the HMAC key, of
+ client_random | server_random | TLSSECRET_MAGIC
+ */
+ memcpy(buf + 0, tls->ssl->s3->client_random, 32);
+ memcpy(buf + 32, tls->ssl->s3->server_random, 32);
+ memcpy(buf + 64, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1);
+ len = 64 + strlen(TLSSECRET_MAGIC) + 1;
+ crypto_hmac_sha256((char*)secrets_out,
+ (char*)tls->ssl->session->master_key,
+ tls->ssl->session->master_key_length,
+ buf, len);
+ memset(buf, 0, sizeof(buf));
+ return 0;
+}
+
/** Examine the amount of memory used and available for buffers in <b>tls</b>.
* Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
* buffer and *<b>rbuf_bytes</b> to the amount actually used.
@@ -1722,3 +2388,75 @@ tor_tls_get_buffer_sizes(tor_tls_t *tls,
*wbuf_bytes = tls->ssl->s3->wbuf.left;
}
+#ifdef USE_BUFFEREVENTS
+/** Construct and return an TLS-encrypting bufferevent to send data over
+ * <b>socket</b>, which must match the socket of the underlying bufferevent
+ * <b>bufev_in</b>. The TLS object <b>tls</b> is used for encryption.
+ *
+ * This function will either create a filtering bufferevent that wraps around
+ * <b>bufev_in</b>, or it will free bufev_in and return a new bufferevent that
+ * uses the <b>tls</b> to talk to the network directly. Do not use
+ * <b>bufev_in</b> after calling this function.
+ *
+ * The connection will start out doing a server handshake if <b>receiving</b>
+ * is strue, and a client handshake otherwise.
+ *
+ * Returns NULL on failure.
+ */
+struct bufferevent *
+tor_tls_init_bufferevent(tor_tls_t *tls, struct bufferevent *bufev_in,
+ evutil_socket_t socket, int receiving,
+ int filter)
+{
+ struct bufferevent *out;
+ const enum bufferevent_ssl_state state = receiving ?
+ BUFFEREVENT_SSL_ACCEPTING : BUFFEREVENT_SSL_CONNECTING;
+
+ if (filter || tor_libevent_using_iocp_bufferevents()) {
+ /* Grab an extra reference to the SSL, since BEV_OPT_CLOSE_ON_FREE
+ means that the SSL will get freed too.
+
+ This increment makes our SSL usage not-threadsafe, BTW. We should
+ see if we're allowed to use CRYPTO_add from outside openssl. */
+ tls->ssl->references += 1;
+ out = bufferevent_openssl_filter_new(tor_libevent_get_base(),
+ bufev_in,
+ tls->ssl,
+ state,
+ BEV_OPT_DEFER_CALLBACKS|
+ BEV_OPT_CLOSE_ON_FREE);
+ /* Tell the underlying bufferevent when to accept more data from the SSL
+ filter (only when it's got less than 32K to write), and when to notify
+ the SSL filter that it could write more (when it drops under 24K). */
+ bufferevent_setwatermark(bufev_in, EV_WRITE, 24*1024, 32*1024);
+ } else {
+ if (bufev_in) {
+ evutil_socket_t s = bufferevent_getfd(bufev_in);
+ tor_assert(s == -1 || s == socket);
+ tor_assert(evbuffer_get_length(bufferevent_get_input(bufev_in)) == 0);
+ tor_assert(evbuffer_get_length(bufferevent_get_output(bufev_in)) == 0);
+ tor_assert(BIO_number_read(SSL_get_rbio(tls->ssl)) == 0);
+ tor_assert(BIO_number_written(SSL_get_rbio(tls->ssl)) == 0);
+ bufferevent_free(bufev_in);
+ }
+
+ /* Current versions (as of 2.0.x) of Libevent need to defer
+ * bufferevent_openssl callbacks, or else our callback functions will
+ * get called reentrantly, which is bad for us.
+ */
+ out = bufferevent_openssl_socket_new(tor_libevent_get_base(),
+ socket,
+ tls->ssl,
+ state,
+ BEV_OPT_DEFER_CALLBACKS);
+ }
+ tls->state = TOR_TLS_ST_BUFFEREVENT;
+
+ /* Unblock _after_ creating the bufferevent, since accept/connect tend to
+ * clear flags. */
+ tor_tls_unblock_renegotiation(tls);
+
+ return out;
+}
+#endif
+
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 55fee81aea..9f86e37127 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -13,10 +13,14 @@
#include "crypto.h"
#include "compat.h"
+#include "compat_libevent.h"
/* Opaque structure to hold a TLS connection. */
typedef struct tor_tls_t tor_tls_t;
+/* Opaque structure to hold an X509 certificate. */
+typedef struct tor_cert_t tor_cert_t;
+
/* Possible return values for most tor_tls_* functions. */
#define _MIN_TOR_TLS_ERROR_VAL -9
#define TOR_TLS_ERROR_MISC -9
@@ -48,6 +52,7 @@ typedef struct tor_tls_t tor_tls_t;
#define TOR_TLS_IS_ERROR(rv) ((rv) < TOR_TLS_CLOSE)
const char *tor_tls_err_to_string(int err);
+void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz);
void tor_tls_free_all(void);
int tor_tls_context_init(int is_public_server,
@@ -56,19 +61,25 @@ int tor_tls_context_init(int is_public_server,
unsigned int key_lifetime);
tor_tls_t *tor_tls_new(int sock, int is_server);
void tor_tls_set_logged_address(tor_tls_t *tls, const char *address);
-void tor_tls_set_renegotiate_callback(tor_tls_t *tls,
+void tor_tls_set_renegotiate_callbacks(tor_tls_t *tls,
void (*cb)(tor_tls_t *, void *arg),
+ void (*cb2)(void *),
void *arg);
int tor_tls_is_server(tor_tls_t *tls);
void tor_tls_free(tor_tls_t *tls);
int tor_tls_peer_has_cert(tor_tls_t *tls);
+tor_cert_t *tor_tls_get_peer_cert(tor_tls_t *tls);
int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity);
-int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance);
+int tor_tls_check_lifetime(int severity,
+ tor_tls_t *tls, int past_tolerance,
+ int future_tolerance);
int tor_tls_read(tor_tls_t *tls, char *cp, size_t len);
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
int tor_tls_handshake(tor_tls_t *tls);
+int tor_tls_finish_handshake(tor_tls_t *tls);
int tor_tls_renegotiate(tor_tls_t *tls);
-void tor_tls_block_renegotiation(tor_tls_t *tls);
+void tor_tls_unblock_renegotiation(tor_tls_t *tls);
+void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls);
int tor_tls_shutdown(tor_tls_t *tls);
int tor_tls_get_pending_bytes(tor_tls_t *tls);
size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
@@ -81,12 +92,44 @@ void tor_tls_get_buffer_sizes(tor_tls_t *tls,
size_t *wbuf_capacity, size_t *wbuf_bytes);
int tor_tls_used_v1_handshake(tor_tls_t *tls);
+int tor_tls_received_v3_certificate(tor_tls_t *tls);
+int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
+int tor_tls_server_got_renegotiate(tor_tls_t *tls);
+int tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out);
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
*/
#define check_no_tls_errors() _check_no_tls_errors(__FILE__,__LINE__)
void _check_no_tls_errors(const char *fname, int line);
+void tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
+ int severity, int domain, const char *doing);
+
+#ifdef USE_BUFFEREVENTS
+int tor_tls_start_renegotiating(tor_tls_t *tls);
+struct bufferevent *tor_tls_init_bufferevent(tor_tls_t *tls,
+ struct bufferevent *bufev_in,
+ evutil_socket_t socket, int receiving,
+ int filter);
+#endif
+
+void tor_cert_free(tor_cert_t *cert);
+tor_cert_t *tor_cert_decode(const uint8_t *certificate,
+ size_t certificate_len);
+void tor_cert_get_der(const tor_cert_t *cert,
+ const uint8_t **encoded_out, size_t *size_out);
+const digests_t *tor_cert_get_id_digests(const tor_cert_t *cert);
+const digests_t *tor_cert_get_cert_digests(const tor_cert_t *cert);
+int tor_tls_get_my_certs(int server,
+ const tor_cert_t **link_cert_out,
+ const tor_cert_t **id_cert_out);
+crypto_pk_env_t *tor_tls_get_my_client_auth_key(void);
+crypto_pk_env_t *tor_tls_cert_get_key(tor_cert_t *cert);
+int tor_tls_cert_matches_key(const tor_tls_t *tls, const tor_cert_t *cert);
+int tor_tls_cert_is_valid(int severity,
+ const tor_cert_t *cert,
+ const tor_cert_t *signing_cert,
+ int check_rsa_1024);
#endif
diff --git a/src/common/util.c b/src/common/util.c
index de1ca3684d..6d488d9963 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -14,6 +14,10 @@
#define _GNU_SOURCE
#include "orconfig.h"
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#define UTIL_PRIVATE
#include "util.h"
#include "torlog.h"
#undef log
@@ -27,6 +31,7 @@
#include <direct.h>
#include <process.h>
#include <tchar.h>
+#include <Winbase.h>
#else
#include <dirent.h>
#include <pwd.h>
@@ -42,6 +47,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <signal.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -67,9 +73,6 @@
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
@@ -87,6 +90,9 @@
#ifdef HAVE_MALLOC_NP_H
#include <malloc_np.h>
#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
/* =====
* Memory management
@@ -417,6 +423,32 @@ round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
return number;
}
+/** Return the number of bits set in <b>v</b>. */
+int
+n_bits_set_u8(uint8_t v)
+{
+ static const int nybble_table[] = {
+ 0, /* 0000 */
+ 1, /* 0001 */
+ 1, /* 0010 */
+ 2, /* 0011 */
+ 1, /* 0100 */
+ 2, /* 0101 */
+ 2, /* 0110 */
+ 3, /* 0111 */
+ 1, /* 1000 */
+ 2, /* 1001 */
+ 2, /* 1010 */
+ 3, /* 1011 */
+ 2, /* 1100 */
+ 3, /* 1101 */
+ 3, /* 1110 */
+ 4, /* 1111 */
+ };
+
+ return nybble_table[v & 15] + nybble_table[v>>4];
+}
+
/* =====
* String manipulation
* ===== */
@@ -500,6 +532,23 @@ tor_strisnonupper(const char *s)
return 1;
}
+/** As strcmp, except that either string may be NULL. The NULL string is
+ * considered to be before any non-NULL string. */
+int
+strcmp_opt(const char *s1, const char *s2)
+{
+ if (!s1) {
+ if (!s2)
+ return 0;
+ else
+ return -1;
+ } else if (!s2) {
+ return 1;
+ } else {
+ return strcmp(s1, s2);
+ }
+}
+
/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
* strcmp.
*/
@@ -722,6 +771,34 @@ find_str_at_start_of_line(const char *haystack, const char *needle)
return NULL;
}
+/** Returns true if <b>string</b> could be a C identifier.
+ A C identifier must begin with a letter or an underscore and the
+ rest of its characters can be letters, numbers or underscores. No
+ length limit is imposed. */
+int
+string_is_C_identifier(const char *string)
+{
+ size_t iter;
+ size_t length = strlen(string);
+ if (!length)
+ return 0;
+
+ for (iter = 0; iter < length ; iter++) {
+ if (iter == 0) {
+ if (!(TOR_ISALPHA(string[iter]) ||
+ string[iter] == '_'))
+ return 0;
+ } else {
+ if (!(TOR_ISALPHA(string[iter]) ||
+ TOR_ISDIGIT(string[iter]) ||
+ string[iter] == '_'))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/** Return true iff the 'len' bytes at 'mem' are all zero. */
int
tor_mem_is_zero(const char *mem, size_t len)
@@ -958,7 +1035,7 @@ esc_for_log(const char *s)
char *result, *outp;
size_t len = 3;
if (!s) {
- return tor_strdup("");
+ return tor_strdup("(null)");
}
for (cp = s; *cp; ++cp) {
@@ -1698,6 +1775,8 @@ check_private_dir(const char *dirname, cpd_check_t check,
struct passwd *pw = NULL;
uid_t running_uid;
gid_t running_gid;
+#else
+ (void)effective_user;
#endif
tor_assert(dirname);
@@ -1897,7 +1976,7 @@ start_writing_to_file(const char *fname, int open_flags, int mode,
if (open_flags & O_BINARY)
new_file->binary = 1;
- new_file->fd = open(open_name, open_flags, mode);
+ new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
if (new_file->fd < 0) {
log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
open_name, fname, strerror(errno));
@@ -2058,13 +2137,12 @@ write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin)
return write_chunks_to_file_impl(fname, chunks, flags);
}
-/** As write_str_to_file, but does not assume a NUL-terminated
- * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
-int
-write_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin)
+/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b>
+ using the open() flags passed in <b>flags</b>. */
+static int
+write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
+ int flags)
{
- int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
int r;
sized_chunk_t c = { str, len };
smartlist_t *chunks = smartlist_create();
@@ -2074,20 +2152,35 @@ write_bytes_to_file(const char *fname, const char *str, size_t len,
return r;
}
+/** As write_str_to_file, but does not assume a NUL-terminated
+ * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
+int
+write_bytes_to_file(const char *fname, const char *str, size_t len,
+ int bin)
+{
+ return write_bytes_to_file_impl(fname, str, len,
+ OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
+}
+
/** As write_bytes_to_file, but if the file already exists, append the bytes
* to the end of the file instead of overwriting it. */
int
append_bytes_to_file(const char *fname, const char *str, size_t len,
int bin)
{
- int flags = OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT);
- int r;
- sized_chunk_t c = { str, len };
- smartlist_t *chunks = smartlist_create();
- smartlist_add(chunks, &c);
- r = write_chunks_to_file_impl(fname, chunks, flags);
- smartlist_free(chunks);
- return r;
+ return write_bytes_to_file_impl(fname, str, len,
+ OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
+}
+
+/** Like write_str_to_file(), but also return -1 if there was a file
+ already residing in <b>fname</b>. */
+int
+write_bytes_to_new_file(const char *fname, const char *str, size_t len,
+ int bin)
+{
+ return write_bytes_to_file_impl(fname, str, len,
+ OPEN_FLAGS_DONT_REPLACE|
+ (bin?O_BINARY:O_TEXT));
}
/** Read the contents of <b>filename</b> into a newly allocated
@@ -2118,7 +2211,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
tor_assert(filename);
- fd = open(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
+ fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
if (fd<0) {
int severity = LOG_WARN;
int save_errno = errno;
@@ -2504,18 +2597,21 @@ digit_to_num(char d)
* success, store the result in <b>out</b>, advance bufp to the next
* character, and return 0. On failure, return -1. */
static int
-scan_unsigned(const char **bufp, unsigned *out, int width)
+scan_unsigned(const char **bufp, unsigned *out, int width, int base)
{
unsigned result = 0;
int scanned_so_far = 0;
+ const int hex = base==16;
+ tor_assert(base == 10 || base == 16);
if (!bufp || !*bufp || !out)
return -1;
if (width<0)
width=MAX_SCANF_WIDTH;
- while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
- int digit = digit_to_num(*(*bufp)++);
- unsigned new_result = result * 10 + digit;
+ while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
+ && scanned_so_far < width) {
+ int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
+ unsigned new_result = result * base + digit;
if (new_result > UINT32_MAX || new_result < result)
return -1; /* over/underflow. */
result = new_result;
@@ -2577,11 +2673,12 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
if (!width) /* No zero-width things. */
return -1;
}
- if (*pattern == 'u') {
+ if (*pattern == 'u' || *pattern == 'x') {
unsigned *u = va_arg(ap, unsigned *);
+ const int base = (*pattern == 'u') ? 10 : 16;
if (!*buf)
return n_matched;
- if (scan_unsigned(&buf, u, width)<0)
+ if (scan_unsigned(&buf, u, width, base)<0)
return n_matched;
++pattern;
++n_matched;
@@ -2618,9 +2715,9 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b>
* and store the results in the corresponding argument fields. Differs from
- * sscanf in that it: Only handles %u and %Ns. Does not handle arbitrarily
- * long widths. %u does not consume any space. Is locale-independent.
- * Returns -1 on malformed patterns.
+ * sscanf in that it: Only handles %u and %x and %Ns. Does not handle
+ * arbitrarily long widths. %u and %x do not consume any space. Is
+ * locale-independent. Returns -1 on malformed patterns.
*
* (As with other locale-independent functions, we need this to parse data that
* is in ASCII without worrying that the C library's locale-handling will make
@@ -2637,6 +2734,30 @@ tor_sscanf(const char *buf, const char *pattern, ...)
return r;
}
+/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>)
+ * to <b>sl</b>. */
+void
+smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...)
+{
+ va_list ap;
+ va_start(ap, pattern);
+ smartlist_vasprintf_add(sl, pattern, ap);
+ va_end(ap);
+}
+
+/** va_list-based backend of smartlist_asprintf_add. */
+void
+smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern,
+ va_list args)
+{
+ char *str = NULL;
+
+ tor_vasprintf(&str, pattern, args);
+ tor_assert(str != NULL);
+
+ smartlist_add(sl, str);
+}
+
/** Return a new list containing the filenames in the directory <b>dirname</b>.
* Return NULL on error or if <b>dirname</b> is not a directory.
*/
@@ -2814,7 +2935,7 @@ finish_daemon(const char *desired_cwd)
exit(1);
}
- nullfd = open("/dev/null", O_RDWR);
+ nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
if (nullfd < 0) {
log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
exit(1);
@@ -2885,3 +3006,1166 @@ load_windows_system_library(const TCHAR *library_name)
}
#endif
+/** Format a single argument for being put on a Windows command line.
+ * Returns a newly allocated string */
+static char *
+format_win_cmdline_argument(const char *arg)
+{
+ char *formatted_arg;
+ char need_quotes;
+ const char *c;
+ int i;
+ int bs_counter = 0;
+ /* Backslash we can point to when one is inserted into the string */
+ const char backslash = '\\';
+
+ /* Smartlist of *char */
+ smartlist_t *arg_chars;
+ arg_chars = smartlist_create();
+
+ /* Quote string if it contains whitespace or is empty */
+ need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]);
+
+ /* Build up smartlist of *chars */
+ for (c=arg; *c != '\0'; c++) {
+ if ('"' == *c) {
+ /* Double up backslashes preceding a quote */
+ for (i=0; i<(bs_counter*2); i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+ bs_counter = 0;
+ /* Escape the quote */
+ smartlist_add(arg_chars, (void*)&backslash);
+ smartlist_add(arg_chars, (void*)c);
+ } else if ('\\' == *c) {
+ /* Count backslashes until we know whether to double up */
+ bs_counter++;
+ } else {
+ /* Don't double up slashes preceding a non-quote */
+ for (i=0; i<bs_counter; i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+ bs_counter = 0;
+ smartlist_add(arg_chars, (void*)c);
+ }
+ }
+ /* Don't double up trailing backslashes */
+ for (i=0; i<bs_counter; i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+
+ /* Allocate space for argument, quotes (if needed), and terminator */
+ formatted_arg = tor_malloc(sizeof(char) *
+ (smartlist_len(arg_chars) + (need_quotes?2:0) + 1));
+
+ /* Add leading quote */
+ i=0;
+ if (need_quotes)
+ formatted_arg[i++] = '"';
+
+ /* Add characters */
+ SMARTLIST_FOREACH(arg_chars, char*, c,
+ {
+ formatted_arg[i++] = *c;
+ });
+
+ /* Add trailing quote */
+ if (need_quotes)
+ formatted_arg[i++] = '"';
+ formatted_arg[i] = '\0';
+
+ smartlist_free(arg_chars);
+ return formatted_arg;
+}
+
+/** Format a command line for use on Windows, which takes the command as a
+ * string rather than string array. Follows the rules from "Parsing C++
+ * Command-Line Arguments" in MSDN. Algorithm based on list2cmdline in the
+ * Python subprocess module. Returns a newly allocated string */
+char *
+tor_join_win_cmdline(const char *argv[])
+{
+ smartlist_t *argv_list;
+ char *joined_argv;
+ int i;
+
+ /* Format each argument and put the result in a smartlist */
+ argv_list = smartlist_create();
+ for (i=0; argv[i] != NULL; i++) {
+ smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i]));
+ }
+
+ /* Join the arguments with whitespace */
+ joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL);
+
+ /* Free the newly allocated arguments, and the smartlist */
+ SMARTLIST_FOREACH(argv_list, char *, arg,
+ {
+ tor_free(arg);
+ });
+ smartlist_free(argv_list);
+
+ return joined_argv;
+}
+
+/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
+ * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
+ * safe.
+ *
+ * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE bytes available.
+ *
+ * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
+ * with spaces. Note that there is no trailing \0. CHILD_STATE indicates where
+ * in the processs of starting the child process did the failure occur (see
+ * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
+ * errno when the failure occurred.
+ */
+
+void
+format_helper_exit_status(unsigned char child_state, int saved_errno,
+ char *hex_errno)
+{
+ unsigned int unsigned_errno;
+ char *cur;
+ size_t i;
+
+ /* Fill hex_errno with spaces, and a trailing newline (memset may
+ not be signal handler safe, so we can't use it) */
+ for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
+ hex_errno[i] = ' ';
+ hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
+
+ /* Convert errno to be unsigned for hex conversion */
+ if (saved_errno < 0) {
+ unsigned_errno = (unsigned int) -saved_errno;
+ } else {
+ unsigned_errno = (unsigned int) saved_errno;
+ }
+
+ /* Convert errno to hex (start before \n) */
+ cur = hex_errno + HEX_ERRNO_SIZE - 2;
+
+ /* Check for overflow on first iteration of the loop */
+ if (cur < hex_errno)
+ return;
+
+ do {
+ *cur-- = "0123456789ABCDEF"[unsigned_errno % 16];
+ unsigned_errno /= 16;
+ } while (unsigned_errno != 0 && cur >= hex_errno);
+
+ /* Prepend the minus sign if errno was negative */
+ if (saved_errno < 0 && cur >= hex_errno)
+ *cur-- = '-';
+
+ /* Leave a gap */
+ if (cur >= hex_errno)
+ *cur-- = '/';
+
+ /* Check for overflow on first iteration of the loop */
+ if (cur < hex_errno)
+ return;
+
+ /* Convert child_state to hex */
+ do {
+ *cur-- = "0123456789ABCDEF"[child_state % 16];
+ child_state /= 16;
+ } while (child_state != 0 && cur >= hex_errno);
+}
+
+/* Maximum number of file descriptors, if we cannot get it via sysconf() */
+#define DEFAULT_MAX_FD 256
+
+/** Terminate the process of <b>process_handle</b>.
+ * Code borrowed from Python's os.kill. */
+int
+tor_terminate_process(process_handle_t *process_handle)
+{
+#ifdef MS_WINDOWS
+ if (tor_get_exit_code(process_handle, 0, NULL) == PROCESS_EXIT_RUNNING) {
+ HANDLE handle;
+ /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
+ attempt to open and terminate the process. */
+ handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE,
+ process_handle->pid.dwProcessId);
+ if (!handle)
+ return -1;
+
+ if (!TerminateProcess(handle, 0))
+ return -1;
+ else
+ return 0;
+ }
+#else /* Unix */
+ return kill(process_handle->pid, SIGTERM);
+#endif
+
+ return -1;
+}
+
+/** Return the Process ID of <b>process_handle</b>. */
+int
+tor_process_get_pid(process_handle_t *process_handle)
+{
+#ifdef MS_WINDOWS
+ return (int) process_handle->pid.dwProcessId;
+#else
+ return (int) process_handle->pid;
+#endif
+}
+
+#ifdef MS_WINDOWS
+HANDLE
+tor_process_get_stdout_pipe(process_handle_t *process_handle)
+{
+ return process_handle->stdout_pipe;
+}
+#else
+FILE *
+tor_process_get_stdout_pipe(process_handle_t *process_handle)
+{
+ return process_handle->stdout_handle;
+}
+#endif
+
+static process_handle_t *
+process_handle_new(void)
+{
+ process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t));
+
+#ifndef MS_WINDOWS
+ out->stdout_pipe = -1;
+ out->stderr_pipe = -1;
+#endif
+
+ return out;
+}
+
+/*DOCDOC*/
+#define CHILD_STATE_INIT 0
+#define CHILD_STATE_PIPE 1
+#define CHILD_STATE_MAXFD 2
+#define CHILD_STATE_FORK 3
+#define CHILD_STATE_DUPOUT 4
+#define CHILD_STATE_DUPERR 5
+#define CHILD_STATE_REDIRECT 6
+#define CHILD_STATE_CLOSEFD 7
+#define CHILD_STATE_EXEC 8
+#define CHILD_STATE_FAILEXEC 9
+
+/** Start a program in the background. If <b>filename</b> contains a '/', then
+ * it will be treated as an absolute or relative path. Otherwise, on
+ * non-Windows systems, the system path will be searched for <b>filename</b>.
+ * On Windows, only the current directory will be searched. Here, to search the
+ * system path (as well as the application directory, current working
+ * directory, and system directories), set filename to NULL.
+ *
+ * The strings in <b>argv</b> will be passed as the command line arguments of
+ * the child program (following convention, argv[0] should normally be the
+ * filename of the executable, and this must be the case if <b>filename</b> is
+ * NULL). The last element of argv must be NULL. A handle to the child process
+ * will be returned in process_handle (which must be non-NULL). Read
+ * process_handle.status to find out if the process was successfully launched.
+ * For convenience, process_handle.status is returned by this function.
+ *
+ * Some parts of this code are based on the POSIX subprocess module from
+ * Python, and example code from
+ * http://msdn.microsoft.com/en-us/library/ms682499%28v=vs.85%29.aspx.
+ */
+int
+tor_spawn_background(const char *const filename, const char **argv,
+#ifdef MS_WINDOWS
+ LPVOID envp,
+#else
+ const char **envp,
+#endif
+ process_handle_t **process_handle_out)
+{
+#ifdef MS_WINDOWS
+ HANDLE stdout_pipe_read = NULL;
+ HANDLE stdout_pipe_write = NULL;
+ HANDLE stderr_pipe_read = NULL;
+ HANDLE stderr_pipe_write = NULL;
+ process_handle_t *process_handle;
+ int status;
+
+ STARTUPINFO siStartInfo;
+ BOOL retval = FALSE;
+
+ SECURITY_ATTRIBUTES saAttr;
+ char *joined_argv;
+
+ (void)envp; // Unused on Windows
+
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ /* TODO: should we set explicit security attributes? (#2046, comment 5) */
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Assume failure to start process */
+ status = PROCESS_STATUS_ERROR;
+
+ /* Set up pipe for stdout */
+ if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stdout communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return status;
+ }
+ if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stdout communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return status;
+ }
+
+ /* Set up pipe for stderr */
+ if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stderr communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return status;
+ }
+ if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stderr communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return status;
+ }
+
+ /* Create the child process */
+
+ /* Windows expects argv to be a whitespace delimited string, so join argv up
+ */
+ joined_argv = tor_join_win_cmdline(argv);
+
+ process_handle = process_handle_new();
+ process_handle->status = status;
+
+ ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = stderr_pipe_write;
+ siStartInfo.hStdOutput = stdout_pipe_write;
+ siStartInfo.hStdInput = NULL;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ /* Create the child process */
+
+ retval = CreateProcess(filename, // module name
+ joined_argv, // command line
+ /* TODO: should we set explicit security attributes? (#2046, comment 5) */
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
+ * work?) */
+ 0, // creation flags
+ envp, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &(process_handle->pid)); // receives PROCESS_INFORMATION
+
+ tor_free(joined_argv);
+
+ if (!retval) {
+ log_warn(LD_GENERAL,
+ "Failed to create child process %s: %s", filename?filename:argv[0],
+ format_win32_error(GetLastError()));
+ tor_free(process_handle);
+ } else {
+ /* TODO: Close hProcess and hThread in process_handle->pid? */
+ process_handle->stdout_pipe = stdout_pipe_read;
+ process_handle->stderr_pipe = stderr_pipe_read;
+ status = process_handle->status = PROCESS_STATUS_RUNNING;
+ }
+
+ /* TODO: Close pipes on exit */
+ *process_handle_out = process_handle;
+ return status;
+#else // MS_WINDOWS
+ pid_t pid;
+ int stdout_pipe[2];
+ int stderr_pipe[2];
+ int fd, retval;
+ ssize_t nbytes;
+ process_handle_t *process_handle;
+ int status;
+
+ const char *error_message = SPAWN_ERROR_MESSAGE;
+ size_t error_message_length;
+
+ /* Represents where in the process of spawning the program is;
+ this is used for printing out the error message */
+ unsigned char child_state = CHILD_STATE_INIT;
+
+ char hex_errno[HEX_ERRNO_SIZE];
+
+ static int max_fd = -1;
+
+ status = PROCESS_STATUS_ERROR;
+
+ /* We do the strlen here because strlen() is not signal handler safe,
+ and we are not allowed to use unsafe functions between fork and exec */
+ error_message_length = strlen(error_message);
+
+ child_state = CHILD_STATE_PIPE;
+
+ /* Set up pipe for redirecting stdout and stderr of child */
+ retval = pipe(stdout_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stdout communication with child process: %s",
+ strerror(errno));
+ return status;
+ }
+
+ retval = pipe(stderr_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stderr communication with child process: %s",
+ strerror(errno));
+ return status;
+ }
+
+ child_state = CHILD_STATE_MAXFD;
+
+#ifdef _SC_OPEN_MAX
+ if (-1 != max_fd) {
+ max_fd = (int) sysconf(_SC_OPEN_MAX);
+ if (max_fd == -1)
+ max_fd = DEFAULT_MAX_FD;
+ log_warn(LD_GENERAL,
+ "Cannot find maximum file descriptor, assuming %d", max_fd);
+ }
+#else
+ max_fd = DEFAULT_MAX_FD;
+#endif
+
+ child_state = CHILD_STATE_FORK;
+
+ pid = fork();
+ if (0 == pid) {
+ /* In child */
+
+ child_state = CHILD_STATE_DUPOUT;
+
+ /* Link child stdout to the write end of the pipe */
+ retval = dup2(stdout_pipe[1], STDOUT_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_DUPERR;
+
+ /* Link child stderr to the write end of the pipe */
+ retval = dup2(stderr_pipe[1], STDERR_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_REDIRECT;
+
+ /* Link stdin to /dev/null */
+ fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */
+ if (fd != -1)
+ dup2(fd, STDIN_FILENO);
+ else
+ goto error;
+
+ child_state = CHILD_STATE_CLOSEFD;
+
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(fd);
+
+ /* Close all other fds, including the read end of the pipe */
+ /* XXX: We should now be doing enough FD_CLOEXEC setting to make
+ * this needless. */
+ for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
+ close(fd);
+ }
+
+ child_state = CHILD_STATE_EXEC;
+
+ /* Call the requested program. We need the cast because
+ execvp doesn't define argv as const, even though it
+ does not modify the arguments */
+ if (envp)
+ execve(filename, (char *const *) argv, (char*const*)envp);
+ else
+ execvp(filename, (char *const *) argv);
+
+ /* If we got here, the exec or open(/dev/null) failed */
+
+ child_state = CHILD_STATE_FAILEXEC;
+
+ error:
+ /* XXX: are we leaking fds from the pipe? */
+
+ format_helper_exit_status(child_state, errno, hex_errno);
+
+ /* Write the error message. GCC requires that we check the return
+ value, but there is nothing we can do if it fails */
+ /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */
+ nbytes = write(STDOUT_FILENO, error_message, error_message_length);
+ nbytes = write(STDOUT_FILENO, hex_errno, sizeof(hex_errno));
+
+ (void) nbytes;
+
+ _exit(255);
+ /* Never reached, but avoids compiler warning */
+ return status;
+ }
+
+ /* In parent */
+
+ if (-1 == pid) {
+ log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ return status;
+ }
+
+ process_handle = process_handle_new();
+ process_handle->status = status;
+ process_handle->pid = pid;
+
+ /* TODO: If the child process forked but failed to exec, waitpid it */
+
+ /* Return read end of the pipes to caller, and close write end */
+ process_handle->stdout_pipe = stdout_pipe[0];
+ retval = close(stdout_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stdout pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ process_handle->stderr_pipe = stderr_pipe[0];
+ retval = close(stderr_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stderr pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ status = process_handle->status = PROCESS_STATUS_RUNNING;
+ /* Set stdout/stderr pipes to be non-blocking */
+ fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK);
+ fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK);
+ /* Open the buffered IO streams */
+ process_handle->stdout_handle = fdopen(process_handle->stdout_pipe, "r");
+ process_handle->stderr_handle = fdopen(process_handle->stderr_pipe, "r");
+
+ *process_handle_out = process_handle;
+ return process_handle->status;
+#endif // MS_WINDOWS
+}
+
+/** Destroy all resources allocated by the process handle in
+ * <b>process_handle</b>.
+ * If <b>also_terminate_process</b> is true, also terminate the
+ * process of the process handle. */
+void
+tor_process_handle_destroy(process_handle_t *process_handle,
+ int also_terminate_process)
+{
+ if (!process_handle)
+ return;
+
+ if (also_terminate_process) {
+ if (tor_terminate_process(process_handle) < 0) {
+ log_notice(LD_GENERAL, "Failed to terminate process with PID '%d'",
+ tor_process_get_pid(process_handle));
+ } else {
+ log_info(LD_GENERAL, "Terminated process with PID '%d'",
+ tor_process_get_pid(process_handle));
+ }
+ }
+
+ process_handle->status = PROCESS_STATUS_NOTRUNNING;
+
+#ifdef MS_WINDOWS
+ if (process_handle->stdout_pipe)
+ CloseHandle(process_handle->stdout_pipe);
+
+ if (process_handle->stderr_pipe)
+ CloseHandle(process_handle->stderr_pipe);
+#else
+ if (process_handle->stdout_handle)
+ fclose(process_handle->stdout_handle);
+
+ if (process_handle->stderr_handle)
+ fclose(process_handle->stderr_handle);
+#endif
+
+ memset(process_handle, 0x0f, sizeof(process_handle_t));
+ tor_free(process_handle);
+}
+
+/** Get the exit code of a process specified by <b>process_handle</b> and store
+ * it in <b>exit_code</b>, if set to a non-NULL value. If <b>block</b> is set
+ * to true, the call will block until the process has exited. Otherwise if
+ * the process is still running, the function will return
+ * PROCESS_EXIT_RUNNING, and exit_code will be left unchanged. Returns
+ * PROCESS_EXIT_EXITED if the process did exit. If there is a failure,
+ * PROCESS_EXIT_ERROR will be returned and the contents of exit_code (if
+ * non-NULL) will be undefined. N.B. Under *nix operating systems, this will
+ * probably not work in Tor, because waitpid() is called in main.c to reap any
+ * terminated child processes.*/
+int
+tor_get_exit_code(const process_handle_t *process_handle,
+ int block, int *exit_code)
+{
+#ifdef MS_WINDOWS
+ DWORD retval;
+ BOOL success;
+
+ if (block) {
+ /* Wait for the process to exit */
+ retval = WaitForSingleObject(process_handle->pid.hProcess, INFINITE);
+ if (retval != WAIT_OBJECT_0) {
+ log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
+ (int)retval, format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ } else {
+ retval = WaitForSingleObject(process_handle->pid.hProcess, 0);
+ if (WAIT_TIMEOUT == retval) {
+ /* Process has not exited */
+ return PROCESS_EXIT_RUNNING;
+ } else if (retval != WAIT_OBJECT_0) {
+ log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
+ (int)retval, format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ }
+
+ if (exit_code != NULL) {
+ success = GetExitCodeProcess(process_handle->pid.hProcess,
+ (PDWORD)exit_code);
+ if (!success) {
+ log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s",
+ format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ }
+#else
+ int stat_loc;
+ int retval;
+
+ retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG);
+ if (!block && 0 == retval) {
+ /* Process has not exited */
+ return PROCESS_EXIT_RUNNING;
+ } else if (retval != process_handle->pid) {
+ log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s",
+ process_handle->pid, strerror(errno));
+ return PROCESS_EXIT_ERROR;
+ }
+
+ if (!WIFEXITED(stat_loc)) {
+ log_warn(LD_GENERAL, "Process %d did not exit normally",
+ process_handle->pid);
+ return PROCESS_EXIT_ERROR;
+ }
+
+ if (exit_code != NULL)
+ *exit_code = WEXITSTATUS(stat_loc);
+#endif // MS_WINDOWS
+
+ return PROCESS_EXIT_EXITED;
+}
+
+#ifdef MS_WINDOWS
+/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
+ * <b>hProcess</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise <b>hProcess</b> should be set to the handle
+ * to the process owning the <b>h</b>. In this case, the function will exit
+ * only once the process has exited, or <b>count</b> bytes are read. Returns
+ * the number of bytes read, or -1 on error. */
+ssize_t
+tor_read_all_handle(HANDLE h, char *buf, size_t count,
+ const process_handle_t *process)
+{
+ size_t numread = 0;
+ BOOL retval;
+ DWORD byte_count;
+ BOOL process_exited = FALSE;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
+ return -1;
+
+ while (numread != count) {
+ /* Check if there is anything to read */
+ retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL);
+ if (!retval) {
+ log_warn(LD_GENERAL,
+ "Failed to peek from handle: %s",
+ format_win32_error(GetLastError()));
+ return -1;
+ } else if (0 == byte_count) {
+ /* Nothing available: process exited or it is busy */
+
+ /* Exit if we don't know whether the process is running */
+ if (NULL == process)
+ break;
+
+ /* The process exited and there's nothing left to read from it */
+ if (process_exited)
+ break;
+
+ /* If process is not running, check for output one more time in case
+ it wrote something after the peek was performed. Otherwise keep on
+ waiting for output */
+ tor_assert(process != NULL);
+ byte_count = WaitForSingleObject(process->pid.hProcess, 0);
+ if (WAIT_TIMEOUT != byte_count)
+ process_exited = TRUE;
+
+ continue;
+ }
+
+ /* There is data to read; read it */
+ retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL);
+ tor_assert(byte_count + numread <= count);
+ if (!retval) {
+ log_warn(LD_GENERAL, "Failed to read from handle: %s",
+ format_win32_error(GetLastError()));
+ return -1;
+ } else if (0 == byte_count) {
+ /* End of file */
+ break;
+ }
+ numread += byte_count;
+ }
+ return (ssize_t)numread;
+}
+#else
+/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
+ * <b>process</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise data will be read until end of file, or
+ * <b>count</b> bytes are read. Returns the number of bytes read, or -1 on
+ * error. Sets <b>eof</b> to true if <b>eof</b> is not NULL and the end of the
+ * file has been reached. */
+ssize_t
+tor_read_all_handle(FILE *h, char *buf, size_t count,
+ const process_handle_t *process,
+ int *eof)
+{
+ size_t numread = 0;
+ char *retval;
+
+ if (eof)
+ *eof = 0;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
+ return -1;
+
+ while (numread != count) {
+ /* Use fgets because that is what we use in log_from_pipe() */
+ retval = fgets(buf+numread, (int)(count-numread), h);
+ if (NULL == retval) {
+ if (feof(h)) {
+ log_debug(LD_GENERAL, "fgets() reached end of file");
+ if (eof)
+ *eof = 1;
+ break;
+ } else {
+ if (EAGAIN == errno) {
+ if (process)
+ continue;
+ else
+ break;
+ } else {
+ log_warn(LD_GENERAL, "fgets() from handle failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+ }
+ tor_assert(retval != NULL);
+ tor_assert(strlen(retval) + numread <= count);
+ numread += strlen(retval);
+ }
+
+ log_debug(LD_GENERAL, "fgets() read %d bytes from handle", (int)numread);
+ return (ssize_t)numread;
+}
+#endif
+
+/** Read from stdout of a process until the process exits. */
+ssize_t
+tor_read_all_from_process_stdout(const process_handle_t *process_handle,
+ char *buf, size_t count)
+{
+#ifdef MS_WINDOWS
+ return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
+ process_handle);
+#else
+ return tor_read_all_handle(process_handle->stdout_handle, buf, count,
+ process_handle, NULL);
+#endif
+}
+
+/** Read from stdout of a process until the process exits. */
+ssize_t
+tor_read_all_from_process_stderr(const process_handle_t *process_handle,
+ char *buf, size_t count)
+{
+#ifdef MS_WINDOWS
+ return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
+ process_handle);
+#else
+ return tor_read_all_handle(process_handle->stderr_handle, buf, count,
+ process_handle, NULL);
+#endif
+}
+
+/** Split buf into lines, and add to smartlist. The buffer <b>buf</b> will be
+ * modified. The resulting smartlist will consist of pointers to buf, so there
+ * is no need to free the contents of sl. <b>buf</b> must be a NUL-terminated
+ * string. <b>len</b> should be set to the length of the buffer excluding the
+ * NUL. Non-printable characters (including NUL) will be replaced with "." */
+int
+tor_split_lines(smartlist_t *sl, char *buf, int len)
+{
+ /* Index in buf of the start of the current line */
+ int start = 0;
+ /* Index in buf of the current character being processed */
+ int cur = 0;
+ /* Are we currently in a line */
+ char in_line = 0;
+
+ /* Loop over string */
+ while (cur < len) {
+ /* Loop until end of line or end of string */
+ for (; cur < len; cur++) {
+ if (in_line) {
+ if ('\r' == buf[cur] || '\n' == buf[cur]) {
+ /* End of line */
+ buf[cur] = '\0';
+ /* Point cur to the next line */
+ cur++;
+ /* Line starts at start and ends with a nul */
+ break;
+ } else {
+ if (!TOR_ISPRINT(buf[cur]))
+ buf[cur] = '.';
+ }
+ } else {
+ if ('\r' == buf[cur] || '\n' == buf[cur]) {
+ /* Skip leading vertical space */
+ ;
+ } else {
+ in_line = 1;
+ start = cur;
+ if (!TOR_ISPRINT(buf[cur]))
+ buf[cur] = '.';
+ }
+ }
+ }
+ /* We are at the end of the line or end of string. If in_line is true there
+ * is a line which starts at buf+start and ends at a NUL. cur points to
+ * the character after the NUL. */
+ if (in_line)
+ smartlist_add(sl, (void *)(buf+start));
+ in_line = 0;
+ }
+ return smartlist_len(sl);
+}
+
+#ifdef MS_WINDOWS
+/** Read from stream, and send lines to log at the specified log level.
+ * Returns -1 if there is a error reading, and 0 otherwise.
+ * If the generated stream is flushed more often than on new lines, or
+ * a read exceeds 256 bytes, lines will be truncated. This should be fixed,
+ * along with the corresponding problem on *nix (see bug #2045).
+ */
+static int
+log_from_handle(HANDLE *pipe, int severity)
+{
+ char buf[256];
+ int pos;
+ smartlist_t *lines;
+
+ pos = tor_read_all_handle(pipe, buf, sizeof(buf) - 1, NULL);
+ if (pos < 0) {
+ /* Error */
+ log_warn(LD_GENERAL, "Failed to read data from subprocess");
+ return -1;
+ }
+
+ if (0 == pos) {
+ /* There's nothing to read (process is busy or has exited) */
+ log_debug(LD_GENERAL, "Subprocess had nothing to say");
+ return 0;
+ }
+
+ /* End with a null even if there isn't a \r\n at the end */
+ /* TODO: What if this is a partial line? */
+ buf[pos] = '\0';
+ log_debug(LD_GENERAL, "Subprocess had %d bytes to say", pos);
+
+ /* Split up the buffer */
+ lines = smartlist_create();
+ tor_split_lines(lines, buf, pos);
+
+ /* Log each line */
+ SMARTLIST_FOREACH(lines, char *, line,
+ {
+ log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", line);
+ });
+ smartlist_free(lines);
+
+ return 0;
+}
+
+#else
+
+/** Read from stream, and send lines to log at the specified log level.
+ * Returns 1 if stream is closed normally, -1 if there is a error reading, and
+ * 0 otherwise. Handles lines from tor-fw-helper and
+ * tor_spawn_background() specially.
+ */
+static int
+log_from_pipe(FILE *stream, int severity, const char *executable,
+ int *child_status)
+{
+ char buf[256];
+ enum stream_status r;
+
+ for (;;) {
+ r = get_string_from_pipe(stream, buf, sizeof(buf) - 1);
+
+ if (r == IO_STREAM_CLOSED) {
+ return 1;
+ } else if (r == IO_STREAM_EAGAIN) {
+ return 0;
+ } else if (r == IO_STREAM_TERM) {
+ return -1;
+ }
+
+ tor_assert(r == IO_STREAM_OKAY);
+
+ /* Check if buf starts with SPAWN_ERROR_MESSAGE */
+ if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) {
+ /* Parse error message */
+ int retval, child_state, saved_errno;
+ retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x",
+ &child_state, &saved_errno);
+ if (retval == 2) {
+ log_warn(LD_GENERAL,
+ "Failed to start child process \"%s\" in state %d: %s",
+ executable, child_state, strerror(saved_errno));
+ if (child_status)
+ *child_status = 1;
+ } else {
+ /* Failed to parse message from child process, log it as a
+ warning */
+ log_warn(LD_GENERAL,
+ "Unexpected message from port forwarding helper \"%s\": %s",
+ executable, buf);
+ }
+ } else {
+ log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf);
+ }
+ }
+
+ /* We should never get here */
+ return -1;
+}
+#endif
+
+/** Reads from <b>stream</b> and stores input in <b>buf_out</b> making
+ * sure it's below <b>count</b> bytes.
+ * If the string has a trailing newline, we strip it off.
+ *
+ * This function is specifically created to handle input from managed
+ * proxies, according to the pluggable transports spec. Make sure it
+ * fits your needs before using it.
+ *
+ * Returns:
+ * IO_STREAM_CLOSED: If the stream is closed.
+ * IO_STREAM_EAGAIN: If there is nothing to read and we should check back
+ * later.
+ * IO_STREAM_TERM: If something is wrong with the stream.
+ * IO_STREAM_OKAY: If everything went okay and we got a string
+ * in <b>buf_out</b>. */
+enum stream_status
+get_string_from_pipe(FILE *stream, char *buf_out, size_t count)
+{
+ char *retval;
+ size_t len;
+
+ tor_assert(count <= INT_MAX);
+
+ retval = fgets(buf_out, (int)count, stream);
+
+ if (!retval) {
+ if (feof(stream)) {
+ /* Program has closed stream (probably it exited) */
+ /* TODO: check error */
+ return IO_STREAM_CLOSED;
+ } else {
+ if (EAGAIN == errno) {
+ /* Nothing more to read, try again next time */
+ return IO_STREAM_EAGAIN;
+ } else {
+ /* There was a problem, abandon this child process */
+ return IO_STREAM_TERM;
+ }
+ }
+ } else {
+ len = strlen(buf_out);
+ tor_assert(len>0);
+
+ if (buf_out[len - 1] == '\n') {
+ /* Remove the trailing newline */
+ buf_out[len - 1] = '\0';
+ } else {
+ /* No newline; check whether we overflowed the buffer */
+ if (!feof(stream))
+ log_info(LD_GENERAL,
+ "Line from stream was truncated: %s", buf_out);
+ /* TODO: What to do with this error? */
+ }
+
+ return IO_STREAM_OKAY;
+ }
+
+ /* We should never get here */
+ return IO_STREAM_TERM;
+}
+
+void
+tor_check_port_forwarding(const char *filename, int dir_port, int or_port,
+ time_t now)
+{
+/* When fw-helper succeeds, how long do we wait until running it again */
+#define TIME_TO_EXEC_FWHELPER_SUCCESS 300
+/* When fw-helper failed to start, how long do we wait until running it again
+ */
+#define TIME_TO_EXEC_FWHELPER_FAIL 60
+
+ /* Static variables are initialized to zero, so child_handle.status=0
+ * which corresponds to it not running on startup */
+ static process_handle_t *child_handle=NULL;
+
+ static time_t time_to_run_helper = 0;
+ int stdout_status, stderr_status, retval;
+ const char *argv[10];
+ char s_dirport[6], s_orport[6];
+
+ tor_assert(filename);
+
+ /* Set up command line for tor-fw-helper */
+ snprintf(s_dirport, sizeof s_dirport, "%d", dir_port);
+ snprintf(s_orport, sizeof s_orport, "%d", or_port);
+
+ /* TODO: Allow different internal and external ports */
+ argv[0] = filename;
+ argv[1] = "--internal-or-port";
+ argv[2] = s_orport;
+ argv[3] = "--external-or-port";
+ argv[4] = s_orport;
+ argv[5] = "--internal-dir-port";
+ argv[6] = s_dirport;
+ argv[7] = "--external-dir-port";
+ argv[8] = s_dirport;
+ argv[9] = NULL;
+
+ /* Start the child, if it is not already running */
+ if ((!child_handle || child_handle->status != PROCESS_STATUS_RUNNING) &&
+ time_to_run_helper < now) {
+ int status;
+
+ /* Assume tor-fw-helper will succeed, start it later*/
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS;
+
+ if (child_handle) {
+ tor_process_handle_destroy(child_handle, 1);
+ child_handle = NULL;
+ }
+
+#ifdef MS_WINDOWS
+ /* Passing NULL as lpApplicationName makes Windows search for the .exe */
+ status = tor_spawn_background(NULL, argv, NULL, &child_handle);
+#else
+ status = tor_spawn_background(filename, argv, NULL, &child_handle);
+#endif
+
+ if (PROCESS_STATUS_ERROR == status) {
+ log_warn(LD_GENERAL, "Failed to start port forwarding helper %s",
+ filename);
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
+ return;
+ }
+
+ log_info(LD_GENERAL,
+ "Started port forwarding helper (%s) with pid '%d'",
+ filename, tor_process_get_pid(child_handle));
+ }
+
+ /* If child is running, read from its stdout and stderr) */
+ if (child_handle && PROCESS_STATUS_RUNNING == child_handle->status) {
+ /* Read from stdout/stderr and log result */
+ retval = 0;
+#ifdef MS_WINDOWS
+ stdout_status = log_from_handle(child_handle->stdout_pipe, LOG_INFO);
+ stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_WARN);
+ /* If we got this far (on Windows), the process started */
+ retval = 0;
+#else
+ stdout_status = log_from_pipe(child_handle->stdout_handle,
+ LOG_INFO, filename, &retval);
+ stderr_status = log_from_pipe(child_handle->stderr_handle,
+ LOG_WARN, filename, &retval);
+#endif
+ if (retval) {
+ /* There was a problem in the child process */
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
+ }
+
+ /* Combine the two statuses in order of severity */
+ if (-1 == stdout_status || -1 == stderr_status)
+ /* There was a failure */
+ retval = -1;
+#ifdef MS_WINDOWS
+ else if (!child_handle || tor_get_exit_code(child_handle, 0, NULL) !=
+ PROCESS_EXIT_RUNNING) {
+ /* process has exited or there was an error */
+ /* TODO: Do something with the process return value */
+ /* TODO: What if the process output something since
+ * between log_from_handle and tor_get_exit_code? */
+ retval = 1;
+ }
+#else
+ else if (1 == stdout_status || 1 == stderr_status)
+ /* stdout or stderr was closed, the process probably
+ * exited. It will be reaped by waitpid() in main.c */
+ /* TODO: Do something with the process return value */
+ retval = 1;
+#endif
+ else
+ /* Both are fine */
+ retval = 0;
+
+ /* If either pipe indicates a failure, act on it */
+ if (0 != retval) {
+ if (1 == retval) {
+ log_info(LD_GENERAL, "Port forwarding helper terminated");
+ child_handle->status = PROCESS_STATUS_NOTRUNNING;
+ } else {
+ log_warn(LD_GENERAL, "Failed to read from port forwarding helper");
+ child_handle->status = PROCESS_STATUS_ERROR;
+ }
+
+ /* TODO: The child might not actually be finished (maybe it failed or
+ closed stdout/stderr), so maybe we shouldn't start another? */
+ }
+ }
+}
+
diff --git a/src/common/util.h b/src/common/util.h
index b9db25ca73..3a68f3993d 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -160,6 +160,7 @@ uint64_t round_to_power_of_2(uint64_t u64);
unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
+int n_bits_set_u8(uint8_t v);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
* and positive <b>b</b>. Works on integer types only. Not defined if a+b can
@@ -172,18 +173,15 @@ uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
#define HEX_CHARACTERS "0123456789ABCDEFabcdef"
void tor_strlower(char *s) ATTR_NONNULL((1));
void tor_strupper(char *s) ATTR_NONNULL((1));
-int tor_strisprint(const char *s) ATTR_PURE ATTR_NONNULL((1));
-int tor_strisnonupper(const char *s) ATTR_PURE ATTR_NONNULL((1));
-int strcmpstart(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2));
-int strcmp_len(const char *s1, const char *s2, size_t len)
- ATTR_PURE ATTR_NONNULL((1,2));
-int strcasecmpstart(const char *s1, const char *s2)
- ATTR_PURE ATTR_NONNULL((1,2));
-int strcmpend(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2));
-int strcasecmpend(const char *s1, const char *s2)
- ATTR_PURE ATTR_NONNULL((1,2));
-int fast_memcmpstart(const void *mem, size_t memlen,
- const char *prefix) ATTR_PURE;
+int tor_strisprint(const char *s) ATTR_NONNULL((1));
+int tor_strisnonupper(const char *s) ATTR_NONNULL((1));
+int strcmp_opt(const char *s1, const char *s2);
+int strcmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2));
+int strcmp_len(const char *s1, const char *s2, size_t len) ATTR_NONNULL((1,2));
+int strcasecmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2));
+int strcmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2));
+int strcasecmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2));
+int fast_memcmpstart(const void *mem, size_t memlen, const char *prefix);
void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2));
long tor_parse_long(const char *s, int base, long min,
@@ -195,17 +193,19 @@ double tor_parse_double(const char *s, double min, double max, int *ok,
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min,
uint64_t max, int *ok, char **next);
const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1));
-const char *eat_whitespace(const char *s) ATTR_PURE;
-const char *eat_whitespace_eos(const char *s, const char *eos) ATTR_PURE;
-const char *eat_whitespace_no_nl(const char *s) ATTR_PURE;
-const char *eat_whitespace_eos_no_nl(const char *s, const char *eos) ATTR_PURE;
-const char *find_whitespace(const char *s) ATTR_PURE;
-const char *find_whitespace_eos(const char *s, const char *eos) ATTR_PURE;
-const char *find_str_at_start_of_line(const char *haystack, const char *needle)
- ATTR_PURE;
-int tor_mem_is_zero(const char *mem, size_t len) ATTR_PURE;
-int tor_digest_is_zero(const char *digest) ATTR_PURE;
-int tor_digest256_is_zero(const char *digest) ATTR_PURE;
+const char *eat_whitespace(const char *s);
+const char *eat_whitespace_eos(const char *s, const char *eos);
+const char *eat_whitespace_no_nl(const char *s);
+const char *eat_whitespace_eos_no_nl(const char *s, const char *eos);
+const char *find_whitespace(const char *s);
+const char *find_whitespace_eos(const char *s, const char *eos);
+const char *find_str_at_start_of_line(const char *haystack,
+ const char *needle);
+int string_is_C_identifier(const char *string);
+
+int tor_mem_is_zero(const char *mem, size_t len);
+int tor_digest_is_zero(const char *digest);
+int tor_digest256_is_zero(const char *digest);
char *esc_for_log(const char *string) ATTR_MALLOC;
const char *escaped(const char *string);
struct smartlist_t;
@@ -218,6 +218,11 @@ int tor_sscanf(const char *buf, const char *pattern, ...)
#endif
;
+void smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...)
+ CHECK_PRINTF(2, 3);
+void smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern,
+ va_list args);
+
int hex_decode_digit(char c);
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen);
@@ -279,6 +284,16 @@ char *rate_limit_log(ratelim_t *lim, time_t now);
ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket);
ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket);
+/** Status of an I/O stream. */
+enum stream_status {
+ IO_STREAM_OKAY,
+ IO_STREAM_EAGAIN,
+ IO_STREAM_TERM,
+ IO_STREAM_CLOSED
+};
+
+enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count);
+
/** Return values from file_status(); see that function's documentation
* for details. */
typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR } file_status_t;
@@ -296,6 +311,7 @@ int check_private_dir(const char *dirname, cpd_check_t check,
const char *effective_user);
#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
+#define OPEN_FLAGS_DONT_REPLACE (O_CREAT|O_EXCL|O_APPEND|O_WRONLY)
typedef struct open_file_t open_file_t;
int start_writing_to_file(const char *fname, int open_flags, int mode,
open_file_t **data_out);
@@ -317,6 +333,8 @@ int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks,
int bin);
int append_bytes_to_file(const char *fname, const char *str, size_t len,
int bin);
+int write_bytes_to_new_file(const char *fname, const char *str, size_t len,
+ int bin);
/** Flag for read_file_to_str: open the file in binary mode. */
#define RFTS_BIN 1
@@ -330,17 +348,101 @@ const char *parse_config_line_from_str(const char *line,
char **key_out, char **value_out);
char *expand_filename(const char *filename);
struct smartlist_t *tor_listdir(const char *dirname);
-int path_is_relative(const char *filename) ATTR_PURE;
+int path_is_relative(const char *filename);
/* Process helpers */
void start_daemon(void);
void finish_daemon(const char *desired_cwd);
void write_pidfile(char *filename);
+/* Port forwarding */
+void tor_check_port_forwarding(const char *filename,
+ int dir_port, int or_port, time_t now);
+
+typedef struct process_handle_t process_handle_t;
+int tor_spawn_background(const char *const filename, const char **argv,
+#ifdef MS_WINDOWS
+ LPVOID envp,
+#else
+ const char **envp,
+#endif
+ process_handle_t **process_handle_out);
+
+#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code "
+
#ifdef MS_WINDOWS
HANDLE load_windows_system_library(const TCHAR *library_name);
#endif
+/* Values of process_handle_t.status. PROCESS_STATUS_NOTRUNNING must be
+ * 0 because tor_check_port_forwarding depends on this being the initial
+ * statue of the static instance of process_handle_t */
+#define PROCESS_STATUS_NOTRUNNING 0
+#define PROCESS_STATUS_RUNNING 1
+#define PROCESS_STATUS_ERROR -1
+
+#ifdef UTIL_PRIVATE
+/*DOCDOC*/
+struct process_handle_t {
+ int status;
+#ifdef MS_WINDOWS
+ HANDLE stdout_pipe;
+ HANDLE stderr_pipe;
+ PROCESS_INFORMATION pid;
+#else
+ int stdout_pipe;
+ int stderr_pipe;
+ FILE *stdout_handle;
+ FILE *stderr_handle;
+ pid_t pid;
+#endif // MS_WINDOWS
+};
+#endif
+
+/* Return values of tor_get_exit_code() */
+#define PROCESS_EXIT_RUNNING 1
+#define PROCESS_EXIT_EXITED 0
+#define PROCESS_EXIT_ERROR -1
+int tor_get_exit_code(const process_handle_t *process_handle,
+ int block, int *exit_code);
+int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
+#ifdef MS_WINDOWS
+ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
+ const process_handle_t *process);
+#else
+ssize_t tor_read_all_handle(FILE *h, char *buf, size_t count,
+ const process_handle_t *process,
+ int *eof);
+#endif
+ssize_t tor_read_all_from_process_stdout(
+ const process_handle_t *process_handle, char *buf, size_t count);
+ssize_t tor_read_all_from_process_stderr(
+ const process_handle_t *process_handle, char *buf, size_t count);
+char *tor_join_win_cmdline(const char *argv[]);
+
+int tor_process_get_pid(process_handle_t *process_handle);
+#ifdef MS_WINDOWS
+HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle);
+#else
+FILE *tor_process_get_stdout_pipe(process_handle_t *process_handle);
+#endif
+
+int tor_terminate_process(process_handle_t *process_handle);
+void tor_process_handle_destroy(process_handle_t *process_handle,
+ int also_terminate_process);
+
+#ifdef UTIL_PRIVATE
+/* Prototypes for private functions only used by util.c (and unit tests) */
+
+void format_helper_exit_status(unsigned char child_state,
+ int saved_errno, char *hex_errno);
+
+/* Space for hex values of child state, a slash, saved_errno (with
+ leading minus) and newline (no null) */
+#define HEX_ERRNO_SIZE (sizeof(char) * 2 + 1 + \
+ 1 + sizeof(int) * 2 + 1)
+#endif
+
const char *libor_get_digests(void);
#endif
diff --git a/src/config/geoip b/src/config/geoip
index 8043d8ebf2..9ada6a3017 100644
--- a/src/config/geoip
+++ b/src/config/geoip
@@ -1,4 +1,4 @@
-# Last updated based on September 6 2011 Maxmind GeoLite Country
+# Last updated based on November 1 2011 Maxmind GeoLite Country
# wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
# cut -d, -f3-5 < GeoIPCountryWhois.csv|sed 's/"//g' > geoip
16777216,16777471,AU
@@ -68,7 +68,8 @@
29884416,29949951,TW
29949952,30015487,KR
30015488,30408703,CN
-30408704,33554431,KR
+30408704,33488895,KR
+33488896,33554431,AU
33554432,34603007,FR
34603008,34604543,EU
34604544,34605055,DE
@@ -112,8 +113,7 @@
34928640,34930687,EU
34930688,34938879,DE
34938880,34947071,FR
-34947072,34952703,EU
-34952704,34953215,SE
+34947072,34953215,EU
34953216,34954751,AT
34954752,34955263,NL
34955264,34959359,AT
@@ -126,16 +126,29 @@
34994176,34995711,FR
34995712,34995967,EU
34995968,34996223,NL
-34996224,35000319,EU
-35000320,35002367,SE
-35002368,35054079,EU
+34996224,34999295,EU
+34999296,35001343,GB
+35001344,35002367,FR
+35002368,35008511,EU
+35008512,35009023,FR
+35009024,35010303,EU
+35010304,35010559,BE
+35010560,35011583,FR
+35011584,35020799,EU
+35020800,35037183,GB
+35037184,35054079,FR
35054080,35054591,SE
-35054592,35055615,EU
+35054592,35055103,EU
+35055104,35055359,ES
+35055360,35055615,EU
35055616,35055871,GB
35055872,35056127,NL
-35056128,35069951,EU
-35069952,35074047,SE
-35074048,35090431,EU
+35056128,35059199,EU
+35059200,35059711,GB
+35059712,35060735,EU
+35060736,35061247,GB
+35061248,35061759,FR
+35061760,35090431,EU
35090432,35094527,GR
35094528,35127295,EU
35127296,35651583,GB
@@ -295,11 +308,12 @@
203658384,203658399,US
203658400,203658415,PR
203658416,203658423,VI
-203658424,203658479,US
+203658424,203658431,US
+203658432,203658479,VI
203658480,203658751,PR
203658752,203658831,VI
-203658832,203658847,US
-203658848,203658911,PR
+203658832,203658863,US
+203658864,203658911,PR
203658912,203658935,VI
203658936,203658951,PR
203658952,203658967,US
@@ -327,7 +341,7 @@
204047248,204047255,US
204047256,204047263,VI
204047264,204047279,US
-204047280,204047295,VI
+204047280,204047295,PR
204047296,204047303,US
204047304,204047311,PR
204047312,204047335,VI
@@ -508,14 +522,10 @@
212791456,212791479,VI
212791480,212791807,PR
212791808,212791815,US
-212791816,212791839,VI
-212791840,212791935,US
-212791936,212792063,VI
+212791816,212792063,VI
212792064,212792191,US
212792192,212792199,PR
-212792200,212792207,VI
-212792208,212792215,PR
-212792216,212792231,VI
+212792200,212792231,VI
212792232,212792239,US
212792240,212792247,PR
212792248,212792271,US
@@ -535,8 +545,8 @@
212793328,212793343,US
212793344,212794367,VI
212794368,212794559,PR
-212794560,212794575,US
-212794576,212794583,VI
+212794560,212794567,US
+212794568,212794583,VI
212794584,212794599,US
212794600,212794783,PR
212794784,212794791,VI
@@ -618,8 +628,9 @@
214187816,214187823,US
214187824,214187831,PR
214187832,214187839,US
-214187840,214187855,PR
-214187856,214187887,US
+214187840,214187863,PR
+214187864,214187871,VI
+214187872,214187887,US
214187888,214187903,PR
214187904,214188031,VI
214188032,214237247,US
@@ -705,7 +716,6 @@
234951680,234952703,HK
234952704,234954751,JP
234954752,234971135,NZ
-234971136,234979327,IN
234979328,235012095,MY
235012096,235077631,AU
235077632,235143167,JP
@@ -723,7 +733,6 @@
241602560,241604607,MY
241604608,241605631,ID
241605632,241606655,CN
-241606656,241614847,IN
241614848,241623039,JP
241623040,241627135,IN
241627136,241631231,HK
@@ -777,12 +786,18 @@
355993888,355993895,IT
355993896,368674047,US
368674048,368674303,ES
-368674304,405012479,US
+368674304,386924543,US
+386924544,387055615,CA
+387055616,387121151,PR
+387121152,387164415,US
+387164416,387164671,CA
+387164672,387448831,US
+387973120,390332415,US
+402653184,405012479,US
405012480,405143551,CA
405143552,405180415,US
405180416,405184511,CA
-405184512,405192703,US
-405209088,405372927,US
+405184512,405372927,US
405372928,405422079,PR
405422080,405798911,US
405798912,405831679,CA
@@ -798,7 +813,7 @@
406003712,406011903,US
406011904,406028287,BS
406028288,406110207,US
-406110208,406126591,CA
+406110208,406142975,CA
406142976,406147071,US
406147072,406151167,CA
406159360,406175743,US
@@ -817,16 +832,19 @@
408518656,408535039,US
408535040,408551423,CA
408551424,408719359,US
-408719360,408721407,LC
-408721408,408723455,VC
+408719360,408723455,LC
408723456,409337855,US
409337856,409354239,CA
409370624,409731071,US
409731072,409862143,CA
409862144,410124287,US
-410124288,410177751,CA
+410124288,410174779,CA
+410174780,410174787,US
+410174788,410177751,CA
410177752,410177755,US
-410177756,410178463,CA
+410177756,410178343,CA
+410178344,410178347,US
+410178348,410178463,CA
410178464,410178467,US
410178468,410180643,CA
410180644,410180647,US
@@ -834,15 +852,13 @@
410180696,410180703,US
410180704,410180711,CA
410180712,410180715,US
-410180716,410180771,CA
+410180716,410180759,CA
+410180760,410180763,US
+410180764,410180771,CA
410180772,410180775,US
-410180776,410185355,CA
-410185356,410185359,US
-410185360,410185407,CA
+410180776,410185407,CA
410185408,410185411,US
-410185412,410185519,CA
-410185520,410185523,US
-410185524,410185539,CA
+410185412,410185539,CA
410185540,410185543,US
410185544,410185551,CA
410185552,410185559,US
@@ -883,7 +899,9 @@
411779072,411828223,PR
411828224,411893759,US
411893760,411975679,CA
-411975680,412221439,US
+411975680,411979775,US
+411979776,411983871,CA
+411983872,412221439,US
412221440,412229631,CA
412254208,412483583,US
412483584,412549119,CA
@@ -896,6 +914,7 @@
412708864,412909567,US
412909568,412942335,CA
412942336,412946431,US
+412975104,413007871,CA
413007872,413908991,US
413908992,413925375,PR
413925376,415760383,US
@@ -908,8 +927,7 @@
416546816,416579583,CA
416612352,416628735,US
416628736,416636927,CA
-416636928,416641023,US
-416645120,416743423,US
+416636928,416743423,US
416743424,416776191,CA
416776192,417202175,US
417202176,417267711,CA
@@ -1220,16 +1238,23 @@
520355840,520421375,ES
520421376,520486911,AT
520486912,520488959,NL
-520488960,520491007,IT
+520488960,520489983,IT
+520489984,520491007,RU
520491008,520493567,GB
-520493568,520494079,FR
-520494080,520495871,IT
-520495872,520496383,DE
-520496384,520497663,IT
-520497664,520497919,FR
-520497920,520500479,IT
-520500480,520500735,DE
-520500736,520501759,IT
+520493568,520494335,FR
+520494336,520494591,TR
+520494592,520495103,CH
+520495104,520496383,DE
+520496384,520496895,TR
+520496896,520497151,ES
+520497152,520497407,FR
+520497408,520497663,ES
+520497664,520498175,FR
+520498176,520498687,CH
+520498688,520499711,FR
+520499712,520501247,DE
+520501248,520501503,IL
+520501504,520501759,AE
520501760,520503295,GB
520503296,520505343,PL
520505344,520507391,GB
@@ -1247,7 +1272,10 @@
520589312,520593407,IT
520593408,520595455,AM
520595456,520597503,MK
-520597504,520601599,DE
+520597504,520598015,DE
+520598016,520598047,IT
+520598048,520598079,FR
+520598080,520601599,DE
520601600,520609791,SI
520609792,520613887,RU
520613888,520615935,CZ
@@ -1273,7 +1301,11 @@
520882176,520884223,IT
520884224,520888319,MK
520888320,520896511,DE
-520896512,520898559,BE
+520896512,520897023,BE
+520897024,520897151,LU
+520897152,520897791,BE
+520897792,520897807,LU
+520897808,520898559,BE
520898560,520902655,GB
520902656,520902784,NL
520902785,520912895,GB
@@ -1367,7 +1399,9 @@
521746432,521748479,NL
521748480,521750527,SE
521750528,521752575,PS
-521752576,521754623,FR
+521752576,521754367,FR
+521754368,521754383,US
+521754384,521754623,FR
521754624,521756671,IR
521756672,521758719,NL
521758720,521760767,IR
@@ -1479,7 +1513,10 @@
523018240,523022335,IT
523022336,523024639,RU
523024640,523024895,GB
-523024896,523026431,RU
+523024896,523025407,RU
+523025408,523025663,UA
+523025664,523025919,CH
+523025920,523026431,NL
523026432,523030527,TR
523030528,523034623,FR
523034624,523038719,SE
@@ -1600,13 +1637,13 @@
529596416,529661951,TR
529661952,529727487,GE
529727488,529793023,HR
-529793024,529826815,RU
-529826816,529827839,GB
-529827840,529828863,RO
+529793024,529825791,RU
+529825792,529826303,UA
+529826304,529826815,RU
+529826816,529827839,DE
+529827840,529828863,CZ
529828864,529829887,RU
-529829888,529830399,UA
-529830400,529830911,RU
-529830912,529831935,DE
+529829888,529831935,NL
529831936,529832959,UA
529832960,529835007,RU
529835008,529836031,KG
@@ -1624,7 +1661,8 @@
529846784,529848319,RU
529848320,529855487,CZ
529855488,529856511,RU
-529856512,529857535,CZ
+529856512,529857279,CZ
+529857280,529857535,KZ
529857536,529858559,UA
529858560,529924095,NL
529924096,529989631,DE
@@ -1655,7 +1693,8 @@
531234816,531236863,IE
531236864,531238911,FR
531238912,531240959,LV
-531240960,531243007,SE
+531240960,531242751,SE
+531242752,531243007,DE
531243008,531245055,RU
531245056,531247103,IT
531247104,531251199,IR
@@ -1702,9 +1741,9 @@
531400704,531402751,UA
531402752,531404799,LU
531404800,531406847,FI
-531406848,531415039,IM
531415040,531423231,RU
-531423232,531425279,NO
+531423232,531423487,GB
+531423488,531425279,NO
531425280,531425325,FR
531425326,531425327,GB
531425328,531425391,FR
@@ -1790,37 +1829,7 @@
532736000,532738047,RU
532738048,532740095,GB
532740096,532742143,KG
-532742144,532742655,GB
-532742656,532742783,CN
-532742784,532742911,GB
-532742912,532743735,CN
-532743736,532743743,AZ
-532743744,532743935,CN
-532743936,532744095,GB
-532744096,532744127,CN
-532744128,532744191,GB
-532744192,532744319,IN
-532744320,532744383,US
-532744384,532744479,CN
-532744480,532744511,IN
-532744512,532744575,BE
-532744576,532744639,GB
-532744640,532745215,CN
-532745216,532745599,GB
-532745600,532745663,CN
-532745664,532745727,US
-532745728,532745791,CN
-532745792,532745855,GB
-532745856,532745983,CN
-532745984,532746015,BE
-532746016,532746047,CN
-532746048,532746111,AU
-532746112,532746143,BE
-532746144,532746207,GB
-532746208,532746215,CN
-532746216,532746223,ES
-532746224,532746231,GB
-532746232,532746239,CN
+532742144,532746239,GB
532746240,532750335,IT
532750336,532752383,SM
532752384,532754431,BE
@@ -2283,15 +2292,31 @@
533817344,533817344,TR
533817345,533819391,CY
533819392,533823487,DE
-533823488,533823743,CD
-533823744,533825535,BE
+533823488,533823551,CD
+533823552,533823552,BE
+533823553,533823612,CD
+533823613,533823616,BE
+533823617,533823644,CD
+533823645,533823648,BE
+533823649,533823660,CD
+533823661,533823664,BE
+533823665,533823676,CD
+533823677,533823680,BE
+533823681,533823692,CD
+533823693,533823696,BE
+533823697,533823708,CD
+533823709,533823712,BE
+533823713,533823724,CD
+533823725,533825535,BE
533825536,533831679,IS
533831680,533835775,DE
533835776,533837823,SE
533837824,533839871,DE
533839872,533856255,IS
533856256,533858303,FR
-533858304,533860351,HU
+533858304,533859343,HU
+533859344,533859351,SK
+533859352,533860351,HU
533860352,533861375,DE
533861376,533862399,NL
533862400,533864447,GB
@@ -2318,7 +2343,11 @@
534118400,534151167,KW
534151168,534157759,DE
534157760,534157823,US
-534157824,534175743,DE
+534157824,534166527,DE
+534166528,534166783,AU
+534166784,534167039,PL
+534167040,534167295,TR
+534167296,534175743,DE
534175744,534179839,NL
534179840,534181887,US
534181888,534183935,DE
@@ -2339,7 +2368,9 @@
534296576,534298623,BA
534298624,534306815,HR
534306816,534308863,SE
-534308864,534310911,IE
+534308864,534309943,IE
+534309944,534309967,GB
+534309968,534310911,IE
534310912,534315007,IT
534315008,534347775,HR
534347776,534355967,GB
@@ -2365,7 +2396,9 @@
534648832,534650879,CH
534650880,534652927,RU
534652928,534654975,AL
-534654976,534663167,GB
+534654976,534659583,GB
+534659584,534661119,CZ
+534661120,534663167,US
534663168,534675455,ES
534675456,534691839,GB
534691840,534693887,FR
@@ -2474,7 +2507,8 @@
540813184,540813247,NL
540813248,540813287,US
540813288,540813295,DE
-540813296,540813311,US
+540813296,540813303,SG
+540813304,540813311,US
540813312,540813567,NL
540813568,540813639,DE
540813640,540813671,TW
@@ -2566,7 +2600,8 @@
654835712,655359999,TW
655360000,656408575,KR
656408576,658505727,PK
-658505728,661651455,CN
+658505728,660602879,CN
+660602880,661651455,HK
661651456,662700031,KR
662700032,666894335,CN
666894336,671088639,ID
@@ -2682,6 +2717,7 @@
692942848,692944895,GA
692944896,692946943,MZ
692946944,692948991,EG
+692948992,692951039,ZM
692969472,692971519,TZ
692973568,692975615,MZ
692975616,692977663,EG
@@ -2694,7 +2730,7 @@
692984832,692987903,ZA
692987904,692988927,GH
692988928,692989951,ZW
-692989952,692990975,BF
+692989952,692991999,BF
692992000,692993023,MW
692993024,692994047,EG
692994048,692995071,TZ
@@ -2760,8 +2796,15 @@
693064704,693065727,GH
693065728,693066751,MW
693066752,693067775,ZA
+693067776,693068799,GH
693068800,693069823,TZ
693069824,693071871,ZA
+693071872,693072895,ZW
+693072896,693073919,NG
+693074944,693075967,CV
+693075968,693076991,CM
+693076992,693078015,ZW
+693084160,693085183,MU
693101568,693102591,KE
693102592,693103615,CD
693103616,693104639,GN
@@ -2868,7 +2911,7 @@
700342272,700350463,NA
700350464,700358655,UG
700358656,700366847,MZ
-700366848,700375039,UG
+700366848,700375039,MW
700375040,700376063,CM
700376064,700377087,NE
700377088,700378111,KE
@@ -2910,7 +2953,9 @@
700588032,700588286,KM
700588287,700589567,A2
700589568,700589695,TZ
-700589696,700592383,A2
+700589696,700590335,A2
+700590336,700590591,NE
+700590592,700592383,A2
700592384,700592639,KE
700592640,700593151,A2
700593152,700594175,NG
@@ -2959,7 +3004,9 @@
701382656,701390847,CI
701390848,701399039,GA
701399040,701407231,EG
-701407232,701415423,CA
+701407232,701408511,CA
+701408512,701408767,ZA
+701408768,701415423,CA
701415424,701423615,ZA
701423616,701431807,NG
701431808,701439999,CI
@@ -3235,7 +3282,9 @@
771751936,771817471,RU
771817472,771948543,TR
771948544,772014079,RU
-772014080,772050575,DE
+772014080,772047647,DE
+772047648,772047663,IT
+772047664,772050575,DE
772050576,772050583,TR
772050584,772051223,DE
772051224,772051231,CH
@@ -3287,7 +3336,9 @@
772844800,772845311,US
772845312,772845567,IT
772845568,772847615,RU
-772847616,772849663,GB
+772847616,772848128,GB
+772848129,772848191,JO
+772848192,772849663,GB
772849664,772851711,BG
772851712,772853759,CH
772853760,772855807,GB
@@ -3336,7 +3387,9 @@
772927488,772929535,UA
772929536,772931583,RU
772931584,772933631,UA
-772933632,772935679,GB
+772933632,772933920,GB
+772933921,772933928,IE
+772933929,772935679,GB
772935680,772937727,PS
772937728,772939775,IT
772939776,772941823,BE
@@ -3405,9 +3458,7 @@
773062912,773063167,US
773063168,773063424,TR
773063425,773063436,US
-773063437,773064447,TR
-773064448,773064703,US
-773064704,773065088,TR
+773063437,773065088,TR
773065089,773065215,US
773065216,773065584,TR
773065585,773065590,GB
@@ -3444,20 +3495,26 @@
773154816,773155583,SE
773155584,773155839,US
773155840,773156863,SE
-773156864,773157887,FR
-773157888,773158911,DE
+773156864,773158143,FR
+773158144,773158911,DE
773158912,773160447,FR
773160448,773160959,ES
773160960,773165055,FR
773165056,773166591,NL
-773166592,773167359,US
+773166592,773167207,US
+773167208,773167215,NL
+773167216,773167359,US
773167360,773167615,NL
773167616,773168639,US
773168640,773168671,NL
773168672,773169151,US
773169152,773171343,NL
773171344,773171359,BE
-773171360,773172223,NL
+773171360,773171599,NL
+773171600,773171607,BE
+773171608,773171615,NL
+773171616,773171647,BE
+773171648,773172223,NL
773172224,773172287,BE
773172288,773172351,GB
773172352,773172479,NL
@@ -3566,7 +3623,7 @@
773685248,773687295,UA
773687296,773689343,HU
773689344,773691391,PL
-773691392,773695487,RU
+773691392,773693439,RU
773695488,773697535,MK
773697536,773699583,LU
773699584,773701631,CZ
@@ -3577,9 +3634,7 @@
773709824,773711871,CZ
773711872,773713919,RU
773713920,773715967,NL
-773715968,773715999,SE
-773716000,773716063,US
-773716064,773716991,SE
+773715968,773716991,SE
773716992,773718015,US
773718016,773720063,DE
773720064,773722111,GB
@@ -3671,9 +3726,11 @@
773980160,773988351,GB
773988352,774003199,ES
774003200,774003263,TR
-774003264,774003327,ES
-774003328,774003391,TR
-774003392,774003711,ES
+774003264,774003311,ES
+774003312,774003391,TR
+774003392,774003439,ES
+774003440,774003455,TR
+774003456,774003711,ES
774003712,774004223,BE
774004224,774004479,ES
774004480,774004511,BE
@@ -3684,9 +3741,7 @@
774029312,774037503,RO
774037504,774045695,SK
774045696,774053887,FR
-774053888,774055679,DE
-774055680,774055807,BZ
-774055808,774055935,DE
+774053888,774055935,DE
774055936,774057983,US
774057984,774058359,DE
774058360,774058367,HR
@@ -3694,9 +3749,7 @@
774059216,774059223,ZA
774059224,774060031,DE
774060032,774060047,ES
-774060048,774060671,DE
-774060672,774060799,HR
-774060800,774061007,DE
+774060048,774061007,DE
774061008,774061023,CZ
774061024,774061103,DE
774061104,774061111,GI
@@ -3808,9 +3861,7 @@
774161569,774161578,LC
774161579,774161588,VE
774161589,774161598,TC
-774161599,774161608,US
-774161609,774161618,LI
-774161619,774161628,US
+774161599,774161628,US
774161629,774161638,PA
774161639,774161648,RU
774161649,774161658,HK
@@ -3911,7 +3962,15 @@
774162307,774162316,RE
774162317,774162326,TK
774162327,774162336,CV
-774162337,774162432,VA
+774162337,774162346,AZ
+774162347,774162366,US
+774162367,774162376,MX
+774162377,774162386,GB
+774162387,774162396,ZW
+774162397,774162406,SZ
+774162407,774162416,SD
+774162417,774162426,BF
+774162427,774162432,VA
774162433,774162442,GB
774162443,774162452,BA
774162453,774162462,WS
@@ -3934,8 +3993,13 @@
774162638,774162642,NF
774162643,774162687,US
774162688,774162688,VA
-774162689,774162718,US
-774162719,774162943,VA
+774162689,774162748,US
+774162749,774162753,PR
+774162754,774162778,US
+774162779,774162798,CA
+774162799,774162803,BN
+774162804,774162808,TM
+774162809,774162943,VA
774162944,774163199,CH
774163200,774168575,VA
774168576,774176767,PL
@@ -3943,239 +4007,7 @@
774184960,774193151,GB
774193152,774209535,ES
774209536,774217727,RU
-774217728,774217823,GB
-774217824,774217855,AE
-774217856,774217887,US
-774217888,774217927,GB
-774217928,774217935,LK
-774217936,774217983,CN
-774217984,774218047,CA
-774218048,774218111,GB
-774218112,774218495,US
-774218496,774218503,SG
-774218504,774218519,CN
-774218520,774218527,PK
-774218528,774218535,CN
-774218536,774218543,IN
-774218544,774218551,HR
-774218552,774218559,CN
-774218560,774218567,GB
-774218568,774218575,TW
-774218576,774218591,GB
-774218592,774218599,CN
-774218600,774218607,PT
-774218608,774218615,TR
-774218616,774218631,PT
-774218632,774218639,IN
-774218640,774218647,TW
-774218648,774218655,PT
-774218656,774218663,RU
-774218664,774218671,PT
-774218672,774218679,CL
-774218680,774218687,CN
-774218688,774218695,GB
-774218696,774218703,SG
-774218704,774218711,CN
-774218712,774218719,GB
-774218720,774218727,CN
-774218728,774218735,RU
-774218736,774218743,TW
-774218744,774219007,GB
-774219008,774219263,US
-774219264,774219271,CN
-774219272,774219279,TR
-774219280,774219287,GB
-774219288,774219295,CY
-774219296,774219327,GB
-774219328,774219335,TW
-774219336,774219343,EG
-774219344,774219359,CN
-774219360,774219367,PT
-774219368,774219375,IN
-774219376,774219383,GB
-774219384,774219391,IN
-774219392,774219399,US
-774219400,774219407,IN
-774219408,774219423,CN
-774219424,774219431,IN
-774219432,774219439,HU
-774219440,774219447,CN
-774219448,774219455,ES
-774219456,774219479,CN
-774219480,774219487,HU
-774219488,774219495,CN
-774219496,774219503,EG
-774219504,774219511,CN
-774219512,774219519,SG
-774219520,774219551,CN
-774219552,774219559,PS
-774219560,774219575,CN
-774219576,774219583,GR
-774219584,774219591,TR
-774219592,774219599,US
-774219600,774219607,CN
-774219608,774219679,GB
-774219680,774219687,PK
-774219688,774219711,GB
-774219712,774219727,BE
-774219728,774219751,GB
-774219752,774219759,PK
-774219760,774219839,CN
-774219840,774219847,UA
-774219848,774219855,CN
-774219856,774219863,GB
-774219864,774219871,IT
-774219872,774219879,RU
-774219880,774219887,CN
-774219888,774219895,RU
-774219896,774219903,LK
-774219904,774219967,US
-774219968,774219975,PK
-774219976,774219991,CN
-774219992,774219999,RU
-774220000,774220007,GB
-774220008,774220015,CN
-774220016,774220023,GB
-774220024,774220031,PK
-774220032,774220159,GB
-774220160,774220191,US
-774220192,774220207,GB
-774220208,774220223,CN
-774220224,774220287,GB
-774220288,774220543,CN
-774220544,774221055,GB
-774221056,774221311,US
-774221312,774221567,CN
-774221568,774221823,US
-774221824,774222079,CN
-774222080,774222335,US
-774222336,774222495,GB
-774222496,774222511,FI
-774222512,774222527,CN
-774222528,774222591,GB
-774222592,774222655,CN
-774222656,774222687,BE
-774222688,774222719,GB
-774222720,774222783,CN
-774222784,774222799,GB
-774222800,774222815,UA
-774222816,774222847,CN
-774222848,774222863,UA
-774222864,774222879,IT
-774222880,774222895,US
-774222896,774222951,GB
-774222952,774222967,CN
-774222968,774222975,GR
-774222976,774223007,GB
-774223008,774223039,CN
-774223040,774223071,IT
-774223072,774223103,CN
-774223104,774223119,UA
-774223120,774223151,CN
-774223152,774223167,PK
-774223168,774223183,GB
-774223184,774223199,PK
-774223200,774223231,GB
-774223232,774223239,CN
-774223240,774223247,ME
-774223248,774223255,TR
-774223256,774223263,ID
-774223264,774223271,DE
-774223272,774223279,CN
-774223280,774223287,GB
-774223288,774223295,CN
-774223296,774223303,TR
-774223304,774223311,CN
-774223312,774223319,IN
-774223320,774223327,ID
-774223328,774223335,PK
-774223336,774223351,PT
-774223352,774223359,GB
-774223360,774223375,UA
-774223376,774223391,RU
-774223392,774223407,PK
-774223408,774223743,GB
-774223744,774223807,US
-774223808,774223839,CN
-774223840,774223871,US
-774223872,774223951,GB
-774223952,774223959,RU
-774223960,774223967,CN
-774223968,774223975,RU
-774223976,774223983,US
-774223984,774223991,RU
-774223992,774223999,PK
-774224000,774224007,IT
-774224008,774224023,CN
-774224024,774224031,AE
-774224032,774224039,TW
-774224040,774224047,CA
-774224048,774224055,CN
-774224056,774224079,IN
-774224080,774224087,DE
-774224088,774224095,CN
-774224096,774224103,BY
-774224104,774224111,RU
-774224112,774224119,CN
-774224120,774224127,IN
-774224128,774224191,GB
-774224192,774224223,US
-774224224,774224255,LT
-774224256,774224383,GB
-774224384,774224399,UA
-774224400,774224407,LT
-774224408,774224415,GB
-774224416,774224423,TW
-774224424,774224431,GB
-774224432,774224439,CN
-774224440,774224767,GB
-774224768,774224831,CN
-774224832,774224847,UA
-774224848,774224967,GB
-774224968,774224975,UA
-774224976,774224983,RU
-774224984,774224991,CN
-774224992,774224999,LK
-774225000,774225007,CN
-774225008,774225015,PK
-774225016,774225023,CN
-774225024,774225055,US
-774225056,774225151,RU
-774225152,774225343,GB
-774225344,774225351,CN
-774225352,774225359,LT
-774225360,774225375,UA
-774225376,774225391,JO
-774225392,774225415,UA
-774225416,774225423,CN
-774225424,774225431,TR
-774225432,774225439,DE
-774225440,774225447,CN
-774225448,774225455,BY
-774225456,774225463,GB
-774225464,774225471,CN
-774225472,774225479,IT
-774225480,774225487,IN
-774225488,774225495,CN
-774225496,774225503,UA
-774225504,774225511,CN
-774225512,774225519,TR
-774225520,774225527,RU
-774225528,774225535,CA
-774225536,774225567,GB
-774225568,774225599,RU
-774225600,774225615,PK
-774225616,774225647,GB
-774225648,774225663,UA
-774225664,774225671,LK
-774225672,774225687,RU
-774225688,774225695,PK
-774225696,774225703,CN
-774225704,774225727,GB
-774225728,774225743,LT
-774225744,774225823,GB
-774225824,774225855,US
-774225856,774225919,IN
+774217728,774225919,GB
774225920,774234111,UA
774234112,774242303,IT
774242304,774258687,RU
@@ -4204,9 +4036,7 @@
774520832,774537215,BH
774537216,774553599,RU
774553600,774569983,RO
-774569984,774579199,GB
-774579200,774580223,IT
-774580224,774586367,GB
+774569984,774586367,GB
774586368,774602751,PS
774602752,774619135,GB
774619136,774651903,RU
@@ -4320,9 +4150,10 @@
778666016,778666031,FR
778666032,778666047,PL
778666048,778666063,FR
-778666064,778666095,PL
-778666096,778666099,DE
-778666100,778666103,ES
+778666064,778666079,IE
+778666080,778666095,ES
+778666096,778666099,PL
+778666100,778666103,LT
778666104,778666107,GB
778666108,778666111,IE
778666112,778666119,FR
@@ -4332,9 +4163,9 @@
778666144,778666151,FR
778666152,778666155,GB
778666156,778666159,ES
-778666160,778666175,PL
-778666176,778666207,FR
-778666208,778666239,PL
+778666160,778666175,IE
+778666176,778666191,FR
+778666192,778666239,PL
778666240,778666247,GB
778666248,778666259,FR
778666260,778666263,PL
@@ -4430,8 +4261,7 @@
778668576,778668607,FR
778668608,778668615,IE
778668616,778668619,PL
-778668620,778668623,GB
-778668624,778668639,FR
+778668620,778668639,FR
778668640,778668671,PL
778668672,778668703,NL
778668704,778668707,PL
@@ -4439,7 +4269,9 @@
778668712,778668715,FR
778668716,778668719,PL
778668720,778668723,PT
-778668724,778668735,PL
+778668724,778668727,PL
+778668728,778668731,PT
+778668732,778668735,DE
778668736,778668799,IT
778668800,778669103,FR
778669104,778669107,PL
@@ -4472,7 +4304,8 @@
778669568,778669615,FR
778669616,778669623,GB
778669624,778669631,PL
-778669632,778669695,FR
+778669632,778669663,FR
+778669664,778669695,GB
778669696,778669727,PT
778669728,778669759,NL
778669760,778669767,DE
@@ -4494,12 +4327,17 @@
778670000,778670007,PL
778670008,778670011,CZ
778670012,778670015,LT
-778670016,778670143,FR
+778670016,778670019,NL
+778670020,778670035,IT
+778670036,778670039,GB
+778670040,778670043,ES
+778670044,778670079,GB
+778670080,778670143,FR
778670144,778670151,CZ
778670152,778670159,CH
778670160,778670163,FR
-778670164,778670167,GB
-778670168,778670175,FR
+778670164,778670171,GB
+778670172,778670175,FR
778670176,778670207,GB
778670208,778670211,DE
778670212,778670215,IT
@@ -4519,7 +4357,9 @@
778670356,778670359,FR
778670360,778670383,DE
778670384,778670387,PL
-778670388,778670399,GB
+778670388,778670391,NL
+778670392,778670395,CZ
+778670396,778670399,GB
778670400,778670407,PL
778670408,778670411,DE
778670412,778670415,NL
@@ -4551,12 +4391,12 @@
778671212,778671231,FR
778671232,778671239,GB
778671240,778671243,PL
-778671244,778671247,FR
+778671244,778671247,ES
778671248,778671263,PL
778671264,778671279,GB
778671280,778671311,FR
778671312,778671327,PT
-778671328,778671331,FR
+778671328,778671331,ES
778671332,778671335,DE
778671336,778671631,FR
778671632,778671647,PL
@@ -4622,8 +4462,8 @@
778673084,778673087,PT
778673088,778673119,FR
778673120,778673151,ES
-778673152,778673191,FR
-778673192,778673195,ES
+778673152,778673183,FR
+778673184,778673195,ES
778673196,778673199,GB
778673200,778673203,CZ
778673204,778673207,IE
@@ -4694,11 +4534,15 @@
778675004,778675007,GB
778675008,778675039,ES
778675040,778675071,FR
-778675072,778675079,IT
+778675072,778675075,DE
+778675076,778675079,IT
778675080,778675087,ES
-778675088,778675135,FR
-778675136,778675199,ES
-778675200,778675215,DE
+778675088,778675159,FR
+778675160,778675163,PL
+778675164,778675167,DE
+778675168,778675199,FR
+778675200,778675207,ES
+778675208,778675215,PL
778675216,778675219,PT
778675220,778675227,FR
778675228,778675231,NL
@@ -4715,7 +4559,9 @@
778675444,778675447,FR
778675448,778675451,PL
778675452,778675455,DE
-778675456,778675471,NL
+778675456,778675459,PL
+778675460,778675463,FR
+778675464,778675471,ES
778675472,778675475,BE
778675476,778675479,ES
778675480,778675483,CH
@@ -4734,9 +4580,9 @@
778675624,778675631,PL
778675632,778675639,ES
778675640,778675647,DE
-778675648,778675663,GB
-778675664,778675679,FR
-778675680,778675695,DE
+778675648,778675687,FR
+778675688,778675691,ES
+778675692,778675695,FR
778675696,778675711,NL
778675712,778675839,FR
778675840,778675843,FI
@@ -4794,8 +4640,8 @@
778676624,778676631,PL
778676632,778676635,FR
778676636,778676639,DE
-778676640,778676671,GB
-778676672,778676687,FR
+778676640,778676655,ES
+778676656,778676687,FR
778676688,778676691,ES
778676692,778676703,PL
778676704,778676719,FR
@@ -4820,12 +4666,12 @@
778676828,778676847,FR
778676848,778676851,NL
778676852,778676855,LT
-778676856,778676859,FR
+778676856,778676859,IE
778676860,778676863,DE
778676864,778676991,PL
778676992,778676999,FR
-778677000,778677003,PL
-778677004,778677023,FR
+778677000,778677007,PL
+778677008,778677023,FR
778677024,778677055,DE
778677056,778677075,FR
778677076,778677079,DE
@@ -4838,9 +4684,11 @@
778677152,778677167,DE
778677168,778677175,CZ
778677176,778677183,NL
-778677184,778677247,GB
+778677184,778677215,GB
+778677216,778677247,PL
778677248,778677503,FR
-778677504,778677511,DE
+778677504,778677507,IE
+778677508,778677511,FR
778677512,778677515,IT
778677516,778677519,GB
778677520,778677523,FR
@@ -4885,17 +4733,18 @@
778678028,778678031,FR
778678032,778678047,PL
778678048,778678115,FR
-778678116,778678127,ES
+778678116,778678119,ES
+778678120,778678127,IT
778678128,778678143,FR
778678144,778678159,GB
778678160,778678163,PL
778678164,778678167,BE
778678168,778678191,PL
-778678192,778678207,NL
+778678192,778678207,FR
778678208,778678271,PL
778678272,778678783,DE
778678784,778678799,FR
-778678800,778678803,DE
+778678800,778678803,PL
778678804,778678807,GB
778678808,778678815,FR
778678816,778678831,PL
@@ -4920,8 +4769,9 @@
778678968,778678975,GB
778678976,778679007,FR
778679008,778679023,PL
-778679024,778679039,ES
-778679040,778679055,PL
+778679024,778679031,GB
+778679032,778679035,FR
+778679036,778679055,PL
778679056,778679071,BE
778679072,778679103,ES
778679104,778679123,PL
@@ -4946,8 +4796,8 @@
778679552,778679615,FR
778679616,778679679,ES
778679680,778679695,PT
-778679696,778679743,GB
-778679744,778679807,ES
+778679696,778679711,GB
+778679712,778679807,FR
778679808,778679823,IT
778679824,778679843,PL
778679844,778679847,DE
@@ -4979,7 +4829,7 @@
778680256,778680271,IT
778680272,778680279,BE
778680280,778680287,PL
-778680288,778680319,FR
+778680288,778680319,DE
778680320,778680447,GB
778680448,778680451,PT
778680452,778680455,IE
@@ -5003,7 +4853,9 @@
778681152,778681215,PL
778681216,778681235,FR
778681236,778681239,ES
-778681240,778681251,FR
+778681240,778681243,FR
+778681244,778681247,GB
+778681248,778681251,FR
778681252,778681255,DE
778681256,778681279,FR
778681280,778681295,DE
@@ -5012,11 +4864,15 @@
778681316,778681319,FR
778681320,778681327,ES
778681328,778681359,GB
-778681360,778681367,FR
-778681368,778681383,CZ
-778681384,778681399,IT
-778681400,778681415,NL
-778681416,778681419,GB
+778681360,778681367,ES
+778681368,778681371,NL
+778681372,778681375,CH
+778681376,778681383,FR
+778681384,778681391,DE
+778681392,778681399,FR
+778681400,778681403,DE
+778681404,778681407,ES
+778681408,778681419,GB
778681420,778681423,BE
778681424,778681431,FR
778681432,778681435,DE
@@ -5028,11 +4884,13 @@
778681472,778681475,DE
778681476,778681479,PT
778681480,778681503,FR
-778681504,778681519,PL
-778681520,778681523,ES
+778681504,778681507,ES
+778681508,778681511,FR
+778681512,778681515,PL
+778681516,778681523,ES
778681524,778681527,FR
778681528,778681531,PL
-778681532,778681535,CH
+778681532,778681535,IT
778681536,778681543,FR
778681544,778681547,GB
778681548,778681551,PT
@@ -5041,11 +4899,16 @@
778681588,778681591,FR
778681592,778681595,LT
778681596,778681599,GB
-778681600,778681615,ES
-778681616,778681623,DE
-778681624,778681663,FR
-778681664,778681679,DE
-778681680,778681703,FR
+778681600,778681623,DE
+778681624,778681631,FR
+778681632,778681639,IT
+778681640,778681643,PL
+778681644,778681647,DE
+778681648,778681651,FR
+778681652,778681655,ES
+778681656,778681671,DE
+778681672,778681675,GB
+778681676,778681703,FR
778681704,778681707,IE
778681708,778681711,ES
778681712,778681727,FR
@@ -5054,7 +4917,7 @@
778682116,778682119,PL
778682120,778682123,CH
778682124,778682127,FR
-778682128,778682143,GB
+778682128,778682143,IE
778682144,778682175,CH
778682176,778682195,IT
778682196,778682199,NL
@@ -5098,14 +4961,24 @@
778691044,778691047,ES
778691048,778691051,PL
778691052,778691055,PT
-778691056,778691359,FR
+778691056,778691063,NL
+778691064,778691067,LT
+778691068,778691359,FR
778691360,778691583,PT
-778691584,778691743,FR
+778691584,778691615,FR
+778691616,778691619,DE
+778691620,778691627,NL
+778691628,778691631,PL
+778691632,778691743,FR
778691744,778691747,PL
778691748,778691751,ES
778691752,778691755,FI
778691756,778691759,FR
-778691760,778691807,GB
+778691760,778691791,GB
+778691792,778691795,DE
+778691796,778691799,PL
+778691800,778691803,ES
+778691804,778691807,PL
778691808,778691839,ES
778691840,778691855,CH
778691856,778691975,FR
@@ -5121,14 +4994,19 @@
778692096,778692099,PL
778692100,778692103,DE
778692104,778692107,CH
-778692108,778692111,FI
-778692112,778692115,PL
+778692108,778692115,PL
778692116,778692127,FR
778692128,778692143,NL
778692144,778692159,DE
778692160,778692191,FR
-778692192,778692207,GB
-778692208,778692615,FR
+778692192,778692195,ES
+778692196,778692199,CZ
+778692200,778692207,ES
+778692208,778692223,FR
+778692224,778692255,DE
+778692256,778692319,FR
+778692320,778692351,IE
+778692352,778692615,FR
778692616,778692619,PL
778692620,778692623,IE
778692624,778692639,NL
@@ -5148,15 +5026,19 @@
778692784,778692787,GB
778692788,778692791,DE
778692792,778692799,FR
-778692800,778692831,DE
+778692800,778692807,IE
+778692808,778692811,PL
+778692812,778692815,DE
+778692816,778692823,NL
+778692824,778692831,FR
778692832,778692835,BE
778692836,778692839,PT
778692840,778692843,ES
778692844,778692847,PL
778692848,778692863,ES
-778692864,778692879,FR
+778692864,778692879,IE
778692880,778692883,PL
-778692884,778692887,IT
+778692884,778692887,FR
778692888,778692891,PL
778692892,778692895,GB
778692896,778692911,FR
@@ -5168,7 +5050,7 @@
778692976,778692983,DE
778692984,778692991,FR
778692992,778693023,GB
-778693024,778693027,LT
+778693024,778693027,PL
778693028,778693031,ES
778693032,778693035,FR
778693036,778693039,DE
@@ -5182,16 +5064,22 @@
778693080,778693087,FR
778693088,778693091,IE
778693092,778693095,FR
-778693096,778693103,IE
+778693096,778693099,IT
+778693100,778693103,ES
778693104,778693119,FR
-778693120,778693151,BE
-778693152,778693167,GB
+778693120,778693135,GB
+778693136,778693139,FR
+778693140,778693143,PL
+778693144,778693151,FR
+778693152,778693155,GB
+778693156,778693159,FR
+778693160,778693163,BE
+778693164,778693167,DE
778693168,778693171,CZ
-778693172,778693175,NL
-778693176,778693215,FR
-778693216,778693223,PL
+778693172,778693183,FR
+778693184,778693223,PL
778693224,778693227,FR
-778693228,778693231,ES
+778693228,778693231,IT
778693232,778693235,DE
778693236,778693239,PL
778693240,778693243,ES
@@ -5200,25 +5088,29 @@
778693280,778693295,IT
778693296,778693327,FR
778693328,778693391,GB
-778693392,778693407,FR
-778693408,778693439,PT
+778693392,778693423,FR
+778693424,778693439,ES
778693440,778693455,FR
778693456,778693459,DE
778693460,778693511,FR
778693512,778693515,CZ
-778693516,778693535,FR
-778693536,778693567,NL
+778693516,778693567,FR
778693568,778693599,BE
778693600,778693631,NL
778693632,778693663,FR
778693664,778693679,NL
-778693680,778693727,DE
-778693728,778693759,CZ
-778693760,778693775,DE
+778693680,778693695,DE
+778693696,778693759,IE
+778693760,778693763,NL
+778693764,778693767,ES
+778693768,778693771,PL
+778693772,778693775,FR
778693776,778693791,IT
-778693792,778693823,FR
+778693792,778693799,ES
+778693800,778693807,FR
+778693808,778693823,PL
778693824,778693839,PT
-778693840,778693855,ES
+778693840,778693855,FR
778693856,778693887,DE
778693888,778693919,PT
778693920,778693927,CH
@@ -5233,8 +5125,10 @@
778694016,778694143,FR
778694144,778694147,DE
778694148,778694159,PL
-778694160,778694175,FI
-778694176,778694187,GB
+778694160,778694163,GB
+778694164,778694171,PL
+778694172,778694183,FR
+778694184,778694187,PL
778694188,778694191,ES
778694192,778694195,BE
778694196,778694199,PL
@@ -5246,9 +5140,10 @@
778694336,778694351,IT
778694352,778694415,FR
778694416,778694463,IT
-778694464,778694479,GB
+778694464,778694479,FR
778694480,778694511,IT
-778694512,778694527,CZ
+778694512,778694515,LT
+778694516,778694527,ES
778694528,778694543,PL
778694544,778694555,DE
778694556,778694559,FR
@@ -5262,12 +5157,21 @@
778694628,778694639,FR
778694640,778694643,PL
778694644,778694647,PT
-778694648,778694687,FR
+778694648,778694655,FR
+778694656,778694663,DE
+778694664,778694671,PT
+778694672,778694679,FR
+778694680,778694687,PL
778694688,778694703,GB
778694704,778694719,FR
778694720,778694783,IT
778694784,778694815,FR
-778694816,778694847,GB
+778694816,778694823,BE
+778694824,778694827,FI
+778694828,778694831,PT
+778694832,778694839,IT
+778694840,778694843,FI
+778694844,778694847,CZ
778694848,778694911,FR
778694912,778694943,GB
778694944,778694959,FR
@@ -5287,7 +5191,8 @@
778695332,778695335,GB
778695336,778695339,PL
778695340,778695343,FR
-778695344,778695351,LT
+778695344,778695347,PL
+778695348,778695351,ES
778695352,778695383,FR
778695384,778695399,DE
778695400,778695415,GB
@@ -5304,8 +5209,10 @@
778695504,778695519,FR
778695520,778695535,GB
778695536,778695551,FR
-778695552,778695567,GB
-778695568,778695575,PL
+778695552,778695555,BE
+778695556,778695559,CH
+778695560,778695563,DE
+778695564,778695575,PL
778695576,778695579,ES
778695580,778695583,FI
778695584,778695615,PL
@@ -5320,7 +5227,7 @@
778695776,778695795,FR
778695796,778695799,ES
778695800,778695807,FR
-778695808,778695823,ES
+778695808,778695823,DE
778695824,778695839,FR
778695840,778695903,DE
778695904,778695911,FI
@@ -5343,7 +5250,8 @@
778696020,778696023,ES
778696024,778696027,DE
778696028,778696031,GB
-778696032,778696063,PL
+778696032,778696047,FR
+778696048,778696063,ES
778696064,778696099,FR
778696100,778696103,GB
778696104,778696107,FR
@@ -5356,8 +5264,10 @@
778696188,778696199,FR
778696200,778696203,IT
778696204,778696207,ES
-778696208,778696223,FR
-778696224,778696255,IE
+778696208,778696211,IE
+778696212,778696215,DE
+778696216,778696219,IT
+778696220,778696255,GB
778696256,778696263,IT
778696264,778696287,ES
778696288,778696335,DE
@@ -5383,7 +5293,10 @@
778696640,778696643,ES
778696644,778696647,NL
778696648,778696655,FR
-778696656,778696671,NL
+778696656,778696659,NL
+778696660,778696663,CH
+778696664,778696667,FI
+778696668,778696671,IE
778696672,778696687,FR
778696688,778696691,BE
778696692,778696695,FI
@@ -5391,14 +5304,17 @@
778696700,778696703,GB
778696704,778696959,FR
778696960,778696975,IT
-778696976,778696991,GB
+778696976,778696979,GB
+778696980,778696983,FR
+778696984,778696987,ES
+778696988,778696991,FR
778696992,778696995,NL
778696996,778696999,ES
778697000,778697015,FR
778697016,778697019,PL
778697020,778697023,ES
778697024,778697055,DE
-778697056,778697059,PL
+778697056,778697059,GB
778697060,778697063,FR
778697064,778697067,PL
778697068,778697071,FR
@@ -5407,7 +5323,7 @@
778697096,778697099,FR
778697100,778697103,PL
778697104,778697151,IE
-778697152,778697167,GB
+778697152,778697167,ES
778697168,778697171,FR
778697172,778697175,DE
778697176,778697179,PL
@@ -5433,7 +5349,7 @@
778697696,778697727,FR
778697728,778697791,FI
778697792,778697807,ES
-778697808,778697811,GB
+778697808,778697811,DE
778697812,778697815,PL
778697816,778697819,FR
778697820,778697823,IT
@@ -5457,11 +5373,11 @@
778698452,778698455,PL
778698456,778698459,CZ
778698460,778698463,PL
-778698464,778698467,GB
+778698464,778698467,NL
778698468,778698471,PL
778698472,778698479,IT
778698480,778698495,FR
-778698496,778698499,GB
+778698496,778698499,IE
778698500,778698503,FR
778698504,778698511,CH
778698512,778698519,FI
@@ -5469,9 +5385,13 @@
778698528,778698531,IT
778698532,778698535,CH
778698536,778698539,PL
-778698540,778698543,IT
-778698544,778698555,PL
-778698556,778698643,FR
+778698540,778698543,FR
+778698544,778698559,PL
+778698560,778698627,FR
+778698628,778698631,DE
+778698632,778698635,PL
+778698636,778698639,DE
+778698640,778698643,NL
778698644,778698647,PL
778698648,778698655,ES
778698656,778698667,FR
@@ -5481,7 +5401,7 @@
778698696,778698703,FR
778698704,778698707,DE
778698708,778698711,ES
-778698712,778698715,NL
+778698712,778698715,IE
778698716,778698719,ES
778698720,778698751,FR
778698752,778764287,TR
@@ -5846,8 +5766,10 @@
782417920,782434303,AM
782434304,782449151,SI
782449152,782449407,HR
-782449408,782450175,SI
-782450176,782450687,BA
+782449408,782449663,SI
+782449664,782449695,BA
+782449696,782449919,SI
+782449920,782450687,BA
782450688,782467071,DE
782467072,782483455,RU
782483456,782499839,FI
@@ -5868,8 +5790,7 @@
782666752,782667007,US
782667008,782667519,RU
782667520,782667775,LU
-782667776,782668031,GB
-782668032,782668287,FR
+782667776,782668287,FR
782668288,782668799,RU
782668800,782669567,NL
782669568,782669823,GB
@@ -6041,6 +5962,7 @@
785645568,785711103,NO
785711104,785776639,SY
785776640,785842175,RO
+785842176,785907711,PL
785907712,785973247,BY
785973248,786038783,MK
786038784,786104319,FR
@@ -6089,7 +6011,9 @@
786638848,786640895,ES
786640896,786642943,GB
786642944,786644991,GR
-786644992,786649087,SE
+786644992,786645759,SE
+786645760,786646015,MT
+786646016,786649087,SE
786649088,786651135,FR
786651136,786655231,DE
786655232,786657279,PL
@@ -6126,7 +6050,9 @@
786747392,786751487,SK
786751488,786755583,PL
786755584,786759679,IT
-786759680,786771967,DE
+786759680,786771711,DE
+786771712,786771775,AT
+786771776,786771967,DE
786771968,786776063,UA
786776064,786780159,RU
786780160,786784255,IT
@@ -6326,7 +6252,9 @@
787863552,787865599,DE
787865600,787869695,FR
787869696,787873791,GB
-787873792,787906559,SE
+787873792,787894271,SE
+787894272,787896319,US
+787896320,787906559,SE
787906560,787939327,GR
787939328,787972095,GB
787972096,788004863,UA
@@ -6459,14 +6387,14 @@
788502528,788504575,IE
788504576,788506623,FR
788506624,788508671,CH
-788508672,788509207,FR
-788509208,788509231,AT
+788508672,788509215,FR
+788509216,788509231,AT
788509232,788509247,FR
-788509248,788509439,AT
-788509440,788509631,FR
+788509248,788509279,AT
+788509280,788509631,FR
788509632,788509695,AT
-788509696,788509951,FR
-788509952,788510719,AT
+788509696,788509999,FR
+788510000,788510719,AT
788510720,788512767,ES
788512768,788514815,FI
788514816,788516863,FR
@@ -6538,7 +6466,9 @@
831389696,831512575,KR
831512576,831513599,AU
831513600,831514623,NZ
-831514624,831515647,HK
+831514624,831514887,HK
+831514888,831514895,AU
+831514896,831515647,HK
831515648,831516671,AU
831516672,831518719,JP
831518720,831519743,AU
@@ -6670,14 +6600,19 @@
842597640,842597647,GT
842597648,842598703,US
842598704,842598719,CZ
-842598720,843055103,US
+842598720,842601607,US
+842601608,842601615,AR
+842601616,842602423,US
+842602424,842602431,IN
+842602432,843055103,US
843055104,843644927,CA
843644928,844890111,US
844890112,844988415,CA
844988416,845283327,US
845283328,845545471,CA
-845545472,846725119,US
-847249408,855638015,US
+845545472,846442495,US
+846442496,846446591,CA
+846446592,855638015,US
855638016,872415231,GB
872415232,889192447,US
889192448,905969663,DE
@@ -7125,9 +7060,7 @@
1030750208,1031798783,JP
1031798784,1035993087,CN
1035993088,1037565951,JP
-1037565952,1037591499,TW
-1037591500,1037591503,CN
-1037591504,1038614527,TW
+1037565952,1038614527,TW
1038614528,1039007743,CN
1039007744,1039138815,HK
1039138816,1039400959,CN
@@ -7149,12 +7082,10 @@
1040187392,1040252927,IL
1040252928,1040318463,GR
1040318464,1040383999,CH
-1040384000,1040386559,SA
-1040386560,1040391167,A2
-1040391168,1040392191,SA
+1040384000,1040392191,SA
1040392192,1040392447,GB
-1040392448,1040399359,SA
-1040399360,1040400127,GB
+1040392448,1040399615,SA
+1040399616,1040400127,GB
1040400128,1040400383,SA
1040400384,1040416767,GB
1040416768,1040424959,SE
@@ -7247,8 +7178,8 @@
1040984216,1040984219,TZ
1040984220,1040990207,A2
1040990208,1040994303,CY
-1040994304,1040994815,RU
-1040994816,1040998399,CY
+1040994304,1040994559,RU
+1040994560,1040998399,CY
1040998400,1041006591,EG
1041006592,1041039359,CH
1041039360,1041051647,SE
@@ -7315,9 +7246,9 @@
1041699768,1041699807,GB
1041699808,1041700423,FR
1041700424,1041700535,GB
-1041700536,1041700559,FR
-1041700560,1041700607,GB
-1041700608,1041700983,FR
+1041700536,1041700583,FR
+1041700584,1041700591,GB
+1041700592,1041700983,FR
1041700984,1041700991,GB
1041700992,1041701175,FR
1041701176,1041701183,GB
@@ -7333,9 +7264,7 @@
1041701720,1041701727,GB
1041701728,1041701863,FR
1041701864,1041701871,GB
-1041701872,1041701911,FR
-1041701912,1041701919,GB
-1041701920,1041701967,FR
+1041701872,1041701967,FR
1041701968,1041701975,GB
1041701976,1041702167,FR
1041702168,1041702175,GB
@@ -7347,9 +7276,7 @@
1041702352,1041702399,GB
1041702400,1041702751,FR
1041702752,1041702759,GB
-1041702760,1041703575,FR
-1041703576,1041703583,GB
-1041703584,1041703639,FR
+1041702760,1041703639,FR
1041703640,1041703647,GB
1041703648,1041703975,FR
1041703976,1041703983,GB
@@ -7368,14 +7295,10 @@
1041704384,1041704407,FR
1041704408,1041704431,GB
1041704432,1041704439,FR
-1041704440,1041704455,GB
-1041704456,1041704479,FR
-1041704480,1041704487,GB
-1041704488,1041704551,FR
+1041704440,1041704447,GB
+1041704448,1041704551,FR
1041704552,1041704575,GB
-1041704576,1041704751,FR
-1041704752,1041704759,GB
-1041704760,1041704775,FR
+1041704576,1041704775,FR
1041704776,1041704783,GB
1041704784,1041704815,FR
1041704816,1041704823,GB
@@ -7425,9 +7348,7 @@
1041706112,1041706143,GB
1041706144,1041706191,FR
1041706192,1041706239,GB
-1041706240,1041706447,FR
-1041706448,1041706463,GB
-1041706464,1041706479,FR
+1041706240,1041706479,FR
1041706480,1041706487,GB
1041706488,1041706791,FR
1041706792,1041706799,GB
@@ -7561,8 +7482,8 @@
1041714112,1041714175,GB
1041714176,1041714511,FR
1041714512,1041714519,GB
-1041714520,1041714655,FR
-1041714656,1041714687,GB
+1041714520,1041714663,FR
+1041714664,1041714687,GB
1041714688,1041714815,FR
1041714816,1041714847,GB
1041714848,1041714855,FR
@@ -7576,12 +7497,10 @@
1041715088,1041715095,FR
1041715096,1041715103,GB
1041715104,1041715119,FR
-1041715120,1041715143,GB
-1041715144,1041715151,FR
-1041715152,1041715167,GB
-1041715168,1041715183,FR
-1041715184,1041715199,GB
-1041715200,1041715527,FR
+1041715120,1041715135,GB
+1041715136,1041715159,FR
+1041715160,1041715167,GB
+1041715168,1041715527,FR
1041715528,1041715535,GB
1041715536,1041715583,FR
1041715584,1041715615,GB
@@ -7631,7 +7550,9 @@
1041717632,1041717639,GB
1041717640,1041717687,FR
1041717688,1041717695,GB
-1041717696,1041718112,FR
+1041717696,1041717711,FR
+1041717712,1041717719,GB
+1041717720,1041718112,FR
1041718113,1041718119,GB
1041718120,1041718127,FR
1041718128,1041718135,GB
@@ -7675,7 +7596,9 @@
1041719229,1041719231,GB
1041719232,1041719247,FR
1041719248,1041719263,GB
-1041719264,1041719743,FR
+1041719264,1041719567,FR
+1041719568,1041719583,GB
+1041719584,1041719743,FR
1041719744,1041719759,GB
1041719760,1041719887,FR
1041719888,1041719903,GB
@@ -7709,8 +7632,8 @@
1041721776,1041721791,GB
1041721792,1041721815,FR
1041721816,1041721823,GB
-1041721824,1041722167,FR
-1041722168,1041722191,GB
+1041721824,1041722175,FR
+1041722176,1041722191,GB
1041722192,1041722207,FR
1041722208,1041722215,GB
1041722216,1041722223,FR
@@ -7748,8 +7671,8 @@
1041723872,1041723887,FR
1041723888,1041723903,GB
1041723904,1041724455,FR
-1041724456,1041724463,GB
-1041724464,1041724511,FR
+1041724456,1041724471,GB
+1041724472,1041724511,FR
1041724512,1041724519,GB
1041724520,1041724671,FR
1041724672,1041724927,GB
@@ -7783,7 +7706,9 @@
1041726640,1041726655,GB
1041726656,1041726671,FR
1041726672,1041726687,GB
-1041726688,1041726735,FR
+1041726688,1041726719,FR
+1041726720,1041726727,GB
+1041726728,1041726735,FR
1041726736,1041726751,GB
1041726752,1041726847,FR
1041726848,1041726855,GB
@@ -7921,8 +7846,8 @@
1041737128,1041737151,GB
1041737152,1041737167,FR
1041737168,1041737183,GB
-1041737184,1041737247,FR
-1041737248,1041737279,GB
+1041737184,1041737215,FR
+1041737216,1041737279,GB
1041737280,1041737295,FR
1041737296,1041737303,GB
1041737304,1041737375,FR
@@ -7935,7 +7860,9 @@
1041737488,1041737495,GB
1041737496,1041737503,FR
1041737504,1041737511,GB
-1041737512,1041737591,FR
+1041737512,1041737535,FR
+1041737536,1041737567,GB
+1041737568,1041737591,FR
1041737592,1041737599,GB
1041737600,1041737607,FR
1041737608,1041737615,GB
@@ -7984,8 +7911,8 @@
1041739300,1041739303,GB
1041739304,1041739375,FR
1041739376,1041739383,BE
-1041739384,1041739391,FR
-1041739392,1041739423,GB
+1041739384,1041739407,FR
+1041739408,1041739423,GB
1041739424,1041739463,FR
1041739464,1041739471,GB
1041739472,1041739487,FR
@@ -8000,7 +7927,9 @@
1041740104,1041740119,GB
1041740120,1041740135,FR
1041740136,1041740143,GB
-1041740144,1041740263,FR
+1041740144,1041740167,FR
+1041740168,1041740175,GB
+1041740176,1041740263,FR
1041740264,1041740271,GB
1041740272,1041740567,FR
1041740568,1041740575,GB
@@ -8023,8 +7952,8 @@
1041741264,1041741279,FR
1041741280,1041741295,GB
1041741296,1041741567,FR
-1041741568,1041741575,GB
-1041741576,1041741607,FR
+1041741568,1041741583,GB
+1041741584,1041741607,FR
1041741608,1041741615,GB
1041741616,1041741631,FR
1041741632,1041741647,GB
@@ -8094,7 +8023,9 @@
1041744416,1041744447,GB
1041744448,1041744479,FR
1041744480,1041744543,GB
-1041744544,1041744599,FR
+1041744544,1041744575,FR
+1041744576,1041744583,GB
+1041744584,1041744599,FR
1041744600,1041744607,GB
1041744608,1041744623,FR
1041744624,1041744639,GB
@@ -8122,9 +8053,7 @@
1041745360,1041745375,GB
1041745376,1041745399,FR
1041745400,1041745407,GB
-1041745408,1041745415,FR
-1041745416,1041745423,GB
-1041745424,1041745447,FR
+1041745408,1041745447,FR
1041745448,1041745471,GB
1041745472,1041745479,FR
1041745480,1041745487,GB
@@ -8188,7 +8117,9 @@
1041750744,1041750751,GB
1041750752,1041750775,FR
1041750776,1041750783,GB
-1041750784,1041751303,FR
+1041750784,1041750831,FR
+1041750832,1041750839,GB
+1041750840,1041751303,FR
1041751304,1041751311,GB
1041751312,1041751351,FR
1041751352,1041751359,GB
@@ -8196,7 +8127,9 @@
1041751568,1041751575,GB
1041751576,1041751695,FR
1041751696,1041751719,GB
-1041751720,1041751775,FR
+1041751720,1041751759,FR
+1041751760,1041751767,GB
+1041751768,1041751775,FR
1041751776,1041751807,GB
1041751808,1041753319,FR
1041753320,1041753327,GB
@@ -8484,8 +8417,8 @@
1043357696,1043365887,CH
1043365888,1043398655,PT
1043398656,1043464191,GB
-1043464192,1043464255,NL
-1043464256,1043464311,GB
+1043464192,1043464287,NL
+1043464288,1043464311,GB
1043464312,1043464351,NL
1043464352,1043464383,GB
1043464384,1043464799,NL
@@ -8551,8 +8484,8 @@
1043468064,1043468127,NL
1043468128,1043468159,GB
1043468160,1043468191,NL
-1043468192,1043468543,GB
-1043468544,1043468575,NL
+1043468192,1043468415,GB
+1043468416,1043468575,NL
1043468576,1043468655,GB
1043468656,1043468663,NL
1043468664,1043468671,GB
@@ -8610,13 +8543,19 @@
1043472476,1043472487,GB
1043472488,1043472495,DE
1043472496,1043472503,GB
-1043472504,1043472895,DE
+1043472504,1043472743,DE
+1043472744,1043472751,GB
+1043472752,1043472895,DE
1043472896,1043473151,GB
-1043473152,1043473411,DE
+1043473152,1043473247,DE
+1043473248,1043473255,GB
+1043473256,1043473411,DE
1043473412,1043473415,GB
1043473416,1043473579,DE
1043473580,1043473583,GB
-1043473584,1043474031,DE
+1043473584,1043473983,DE
+1043473984,1043474015,GB
+1043474016,1043474031,DE
1043474032,1043474047,GB
1043474048,1043474455,DE
1043474456,1043474463,GB
@@ -8632,7 +8571,11 @@
1043475984,1043475991,GB
1043475992,1043476319,DE
1043476320,1043476351,GB
-1043476352,1043476735,DE
+1043476352,1043476543,DE
+1043476544,1043476559,GB
+1043476560,1043476575,DE
+1043476576,1043476607,GB
+1043476608,1043476735,DE
1043476736,1043476767,GB
1043476768,1043476815,DE
1043476816,1043476991,GB
@@ -8641,15 +8584,7 @@
1043477760,1043478179,DE
1043478180,1043478271,GB
1043478272,1043478287,DE
-1043478288,1043478527,GB
-1043478528,1043478623,DE
-1043478624,1043478639,GB
-1043478640,1043478655,DE
-1043478656,1043478671,GB
-1043478672,1043478735,DE
-1043478736,1043478751,GB
-1043478752,1043478783,DE
-1043478784,1043479295,GB
+1043478288,1043479295,GB
1043479296,1043479551,DE
1043479552,1043480063,GB
1043480064,1043480351,DE
@@ -9193,7 +9128,9 @@
1044455424,1044463615,EE
1044463616,1044479999,SE
1044480000,1044488191,CH
-1044488192,1044496383,SK
+1044488192,1044494911,SK
+1044494912,1044494943,SR
+1044494944,1044496383,SK
1044496384,1044512767,EE
1044512768,1044578303,DK
1044578304,1044580607,DE
@@ -9405,9 +9342,7 @@
1044932728,1044932735,BE
1044932736,1044932799,GB
1044932800,1044932831,BE
-1044932832,1044932839,GB
-1044932840,1044932847,BE
-1044932848,1044932863,GB
+1044932832,1044932863,GB
1044932864,1044932935,BE
1044932936,1044932947,GB
1044932948,1044932951,BE
@@ -9430,8 +9365,8 @@
1044933408,1044933411,GB
1044933412,1044933415,BE
1044933416,1044933439,GB
-1044933440,1044933511,BE
-1044933512,1044933519,GB
+1044933440,1044933503,BE
+1044933504,1044933519,GB
1044933520,1044933551,BE
1044933552,1044933555,GB
1044933556,1044933583,BE
@@ -9466,7 +9401,9 @@
1044934576,1044934583,GB
1044934584,1044934591,BE
1044934592,1044934599,GB
-1044934600,1044934719,BE
+1044934600,1044934607,BE
+1044934608,1044934615,GB
+1044934616,1044934719,BE
1044934720,1044934783,GB
1044934784,1044934815,BE
1044934816,1044934819,GB
@@ -9502,24 +9439,24 @@
1044935852,1044935871,GB
1044935872,1044935879,BE
1044935880,1044935887,GB
-1044935888,1044935903,BE
-1044935904,1044936095,GB
+1044935888,1044935895,BE
+1044935896,1044936095,GB
1044936096,1044936103,BE
1044936104,1044936111,GB
1044936112,1044936123,BE
1044936124,1044936151,GB
1044936152,1044936207,BE
1044936208,1044936215,GB
-1044936216,1044936271,BE
+1044936216,1044936231,BE
+1044936232,1044936239,GB
+1044936240,1044936271,BE
1044936272,1044936287,GB
1044936288,1044936303,BE
1044936304,1044936311,GB
1044936312,1044936335,BE
1044936336,1044936351,GB
1044936352,1044936439,BE
-1044936440,1044936447,GB
-1044936448,1044936455,BE
-1044936456,1044936463,GB
+1044936440,1044936463,GB
1044936464,1044936495,BE
1044936496,1044936503,GB
1044936504,1044936711,BE
@@ -9562,16 +9499,20 @@
1044938104,1044938107,GB
1044938108,1044938111,BE
1044938112,1044938143,GB
-1044938144,1044938235,BE
+1044938144,1044938175,BE
+1044938176,1044938207,GB
+1044938208,1044938235,BE
1044938236,1044938271,GB
-1044938272,1044938367,BE
+1044938272,1044938335,BE
+1044938336,1044938343,GB
+1044938344,1044938367,BE
1044938368,1044938399,GB
1044938400,1044938407,BE
1044938408,1044938415,GB
1044938416,1044938423,BE
1044938424,1044938431,GB
-1044938432,1044938487,BE
-1044938488,1044938511,GB
+1044938432,1044938479,BE
+1044938480,1044938511,GB
1044938512,1044938519,BE
1044938520,1044938523,GB
1044938524,1044938559,BE
@@ -9614,17 +9555,19 @@
1045154560,1045154591,NL
1045154592,1045154623,DE
1045154624,1045154655,GB
-1045154656,1045154687,DE
+1045154656,1045154687,MA
1045154688,1045154719,US
1045154720,1045154751,RU
1045154752,1045154783,SE
-1045154784,1045155071,DE
+1045154784,1045154815,BR
+1045154816,1045155071,DE
1045155072,1045155327,CH
1045155328,1045160959,DE
1045160960,1045160991,TR
1045160992,1045161023,DE
1045161024,1045161055,AT
-1045161056,1045161119,DE
+1045161056,1045161087,DE
+1045161088,1045161119,IN
1045161120,1045161151,SC
1045161152,1045168127,DE
1045168128,1045233663,RU
@@ -9677,9 +9620,7 @@
1045461728,1045461735,ES
1045461736,1045461743,NL
1045461744,1045463039,DE
-1045463040,1045467487,FI
-1045467488,1045467519,AX
-1045467520,1045471231,FI
+1045463040,1045471231,FI
1045471232,1045479423,UA
1045479424,1045487615,SE
1045487616,1045495807,LT
@@ -9718,12 +9659,11 @@
1045742848,1045742983,SE
1045742984,1045742991,GB
1045742992,1045743007,SE
-1045743008,1045743031,GB
+1045743008,1045743015,FI
+1045743016,1045743031,GB
1045743032,1045743039,SE
1045743040,1045743063,GB
-1045743064,1045743071,SE
-1045743072,1045743087,GB
-1045743088,1045743095,SE
+1045743064,1045743095,SE
1045743096,1045743103,GB
1045743104,1045743231,SE
1045743232,1045743251,GB
@@ -9740,11 +9680,10 @@
1045744672,1045745407,GB
1045745408,1045745607,SE
1045745608,1045745615,FI
-1045745616,1045745623,GB
-1045745624,1045745627,SE
+1045745616,1045745627,SE
1045745628,1045745631,GB
1045745632,1045745647,SE
-1045745648,1045745663,GB
+1045745648,1045745663,FI
1045745664,1045745695,SE
1045745696,1045745759,GB
1045745760,1045745768,SE
@@ -9799,7 +9738,9 @@
1046225656,1046229111,NO
1046229112,1046229119,SE
1046229120,1046282239,NO
-1046282240,1046283007,DE
+1046282240,1046282623,DE
+1046282624,1046282751,US
+1046282752,1046283007,DE
1046283008,1046283135,BZ
1046283136,1046283263,DE
1046283264,1046283327,LU
@@ -9876,8 +9817,8 @@
1046338048,1046339839,EU
1046339840,1046340095,FR
1046340096,1046343423,EU
-1046343424,1046343935,NL
-1046343936,1046344959,EU
+1046343424,1046343679,NL
+1046343680,1046344959,EU
1046344960,1046345215,DE
1046345216,1046345327,EU
1046345328,1046345727,DE
@@ -10230,9 +10171,7 @@
1046544384,1046560767,IT
1046560768,1046570591,ES
1046570592,1046570607,CH
-1046570608,1046571815,ES
-1046571816,1046571823,FR
-1046571824,1046572007,ES
+1046570608,1046572007,ES
1046572008,1046572015,DK
1046572016,1046585343,ES
1046585344,1046609919,NO
@@ -10256,9 +10195,7 @@
1046872064,1046872583,BE
1046872584,1046872607,EU
1046872608,1046872615,BE
-1046872616,1046872655,EU
-1046872656,1046872671,BE
-1046872672,1046872975,EU
+1046872616,1046872975,EU
1046872976,1046872999,BE
1046873000,1046873087,EU
1046873088,1046873279,BE
@@ -10330,13 +10267,13 @@
1046882304,1046884383,BE
1046884384,1046885375,EU
1046885376,1046888447,BE
-1046888448,1046895103,GB
-1046895104,1046896383,EU
+1046888448,1046895359,GB
+1046895360,1046896383,EU
1046896384,1046897663,GB
1046897664,1046898431,BE
1046898432,1046898687,EU
-1046898688,1046898975,BE
-1046898976,1046899167,EU
+1046898688,1046898943,BE
+1046898944,1046899167,EU
1046899168,1046904831,BE
1046904832,1046906879,SK
1046906880,1046908927,IR
@@ -10401,7 +10338,9 @@
1047527424,1047535615,BE
1047535616,1047551999,DE
1047552000,1047560191,RU
-1047560192,1047561747,DE
+1047560192,1047561151,DE
+1047561152,1047561159,AT
+1047561160,1047561747,DE
1047561748,1047561751,ES
1047561752,1047561887,DE
1047561888,1047561891,US
@@ -10432,8 +10371,10 @@
1047565132,1047565135,GB
1047565136,1047565343,DE
1047565344,1047565359,CH
-1047565360,1047565855,DE
-1047565856,1047565887,CH
+1047565360,1047565503,DE
+1047565504,1047565507,CZ
+1047565508,1047565839,DE
+1047565840,1047565887,CH
1047565888,1047566363,DE
1047566364,1047566367,CH
1047566368,1047566403,DE
@@ -10491,9 +10432,7 @@
1047567160,1047567163,DE
1047567164,1047567167,AT
1047567168,1047567175,CH
-1047567176,1047567183,DE
-1047567184,1047567191,CH
-1047567192,1047567211,DE
+1047567176,1047567211,DE
1047567212,1047567227,CH
1047567228,1047567239,DE
1047567240,1047567243,CH
@@ -10541,8 +10480,8 @@
1047567872,1047567875,CH
1047567876,1047567879,AT
1047567880,1047567883,CH
-1047567884,1047567935,DE
-1047567936,1047567939,CH
+1047567884,1047567903,DE
+1047567904,1047567939,CH
1047567940,1047568047,DE
1047568048,1047568051,CH
1047568052,1047568055,DE
@@ -10579,15 +10518,15 @@
1047740480,1047740543,EU
1047740544,1047740671,DE
1047740672,1047740927,A2
-1047740928,1047781663,EU
-1047781664,1047781671,GB
-1047781672,1047782695,EU
+1047740928,1047782695,EU
1047782696,1047782703,GB
1047782704,1047782719,EU
1047782720,1047782751,SE
1047782752,1047782783,NO
1047782784,1047782815,FI
-1047782816,1047789375,EU
+1047782816,1047785471,EU
+1047785472,1047788031,DE
+1047788032,1047789375,EU
1047789376,1047789383,GB
1047789384,1047789407,EU
1047789408,1047789423,DE
@@ -10610,7 +10549,9 @@
1047941376,1047986175,RU
1047986176,1047997439,SE
1047997440,1047997503,NO
-1047997504,1048012383,SE
+1047997504,1048003503,SE
+1048003504,1048003511,NO
+1048003512,1048012383,SE
1048012384,1048012391,DE
1048012392,1048051711,SE
1048051712,1048117247,SA
@@ -10664,9 +10605,7 @@
1048605096,1048605103,UA
1048605104,1048605119,LT
1048605120,1048607231,UA
-1048607232,1048607247,EE
-1048607248,1048607487,UA
-1048607488,1048607519,EE
+1048607232,1048607519,EE
1048607520,1048607743,UA
1048607744,1048607759,EE
1048607760,1048607775,UA
@@ -11120,7 +11059,9 @@
1048887040,1048887047,DE
1048887048,1048887935,NL
1048887936,1048887999,DE
-1048888000,1048891391,NL
+1048888000,1048889983,NL
+1048889984,1048890015,DE
+1048890016,1048891391,NL
1048891392,1048891399,DE
1048891400,1048891823,NL
1048891824,1048891831,DE
@@ -11379,9 +11320,7 @@
1049004544,1049006079,DE
1049006080,1049007103,EU
1049007104,1049007111,DE
-1049007112,1049007119,EU
-1049007120,1049007135,DE
-1049007136,1049007359,EU
+1049007112,1049007359,EU
1049007360,1049009535,DE
1049009536,1049009559,EU
1049009560,1049009567,DE
@@ -11550,7 +11489,9 @@
1049759984,1049759999,AE
1049760000,1049760639,DE
1049760640,1049760703,IT
-1049760704,1049760927,DE
+1049760704,1049760767,DE
+1049760768,1049760775,ES
+1049760776,1049760927,DE
1049760928,1049760959,DK
1049760960,1049761023,PL
1049761024,1049761791,DE
@@ -12075,7 +12016,9 @@
1052020736,1052022527,EU
1052022528,1052022783,DE
1052022784,1052024831,EU
-1052024832,1052041279,DE
+1052024832,1052041247,DE
+1052041248,1052041255,EU
+1052041256,1052041279,DE
1052041280,1052041295,EU
1052041296,1052041327,DE
1052041328,1052041335,EU
@@ -12085,9 +12028,7 @@
1052041600,1052041727,EU
1052041728,1052041863,DE
1052041864,1052041983,EU
-1052041984,1052042047,DE
-1052042048,1052042087,NL
-1052042088,1052042095,DE
+1052041984,1052042095,DE
1052042096,1052042143,EU
1052042144,1052042183,DE
1052042184,1052042223,EU
@@ -13024,13 +12965,17 @@
1052876800,1052884991,NG
1052884992,1052901375,FR
1052901376,1053032447,NL
-1053032448,1053097983,IT
+1053032448,1053047367,IT
+1053047368,1053047375,TR
+1053047376,1053097983,IT
1053097984,1053106175,DE
1053106176,1053114367,GB
1053114368,1053130751,BE
1053130752,1053138943,NL
1053138944,1053147135,FI
-1053147136,1053163519,SK
+1053147136,1053155071,SK
+1053155072,1053155327,SR
+1053155328,1053163519,SK
1053163520,1053294591,DK
1053294592,1053294847,EU
1053294848,1053295103,AT
@@ -13121,9 +13066,7 @@
1053312960,1053313023,EU
1053313024,1053313471,GB
1053313472,1053313479,EU
-1053313480,1053313671,GB
-1053313672,1053313679,EU
-1053313680,1053313791,GB
+1053313480,1053313791,GB
1053313792,1053313919,EU
1053313920,1053314047,GB
1053314048,1053314063,EU
@@ -13380,9 +13323,7 @@
1053851904,1053851919,FR
1053851920,1053852031,EU
1053852032,1053852047,IT
-1053852048,1053852095,EU
-1053852096,1053852103,DE
-1053852104,1053852111,EU
+1053852048,1053852111,EU
1053852112,1053852127,GB
1053852128,1053852159,DE
1053852160,1053855743,EU
@@ -13471,7 +13412,9 @@
1053896704,1053900799,DE
1053900800,1053917183,NO
1053917184,1053925375,UZ
-1053925376,1053933567,SE
+1053925376,1053927159,SE
+1053927160,1053927163,FI
+1053927164,1053933567,SE
1053933568,1053949951,CZ
1053949952,1053984415,FR
1053984416,1053984447,US
@@ -13487,11 +13430,17 @@
1054130176,1054138367,LT
1054138368,1054146559,AZ
1054146560,1054179327,RU
-1054179328,1054180095,GB
-1054180096,1054180351,DE
-1054180352,1054181375,GB
-1054181376,1054186495,DE
-1054186496,1054187519,GB
+1054179328,1054180351,GB
+1054180352,1054181120,DE
+1054181121,1054181375,GB
+1054181376,1054183168,DE
+1054183169,1054183423,GB
+1054183424,1054185216,DE
+1054185217,1054185471,GB
+1054185472,1054186240,DE
+1054186241,1054186495,GB
+1054186496,1054187264,DE
+1054187265,1054187519,GB
1054187520,1054195711,BG
1054195712,1054212095,BE
1054212096,1054212519,DE
@@ -13740,9 +13689,7 @@
1055490048,1055522815,PL
1055522816,1055588351,NL
1055588352,1055653887,BE
-1055653888,1055681055,FI
-1055681056,1055681071,SE
-1055681072,1055784959,FI
+1055653888,1055784959,FI
1055784960,1055850495,NL
1055850496,1055916031,GB
1055916032,1055924223,RS
@@ -13998,7 +13945,13 @@
1064973056,1064973183,AU
1064973184,1065049471,US
1065049472,1065049535,CA
-1065049536,1065517087,US
+1065049536,1065389439,US
+1065389440,1065389455,MY
+1065389456,1065390591,US
+1065390592,1065390599,MY
+1065390600,1065390655,US
+1065390656,1065390687,MX
+1065390688,1065517087,US
1065517088,1065517119,A2
1065517120,1065519359,US
1065519360,1065519487,CA
@@ -14021,7 +13974,7 @@
1066311680,1066315775,CA
1066315776,1066332159,US
1066332160,1066336255,CA
-1066336256,1066344447,US
+1066336256,1066352639,US
1066352640,1066369023,JM
1066369024,1066584063,US
1066584064,1066586111,PE
@@ -14208,7 +14161,15 @@
1071477248,1071480831,CA
1071480832,1071488447,US
1071488448,1071488479,HK
-1071488480,1071985631,US
+1071488480,1071599105,US
+1071599106,1071599134,PH
+1071599135,1071599300,US
+1071599301,1071599313,PH
+1071599314,1071599392,US
+1071599393,1071599415,PH
+1071599416,1071599477,US
+1071599478,1071599490,PH
+1071599491,1071985631,US
1071985632,1071985663,ML
1071985664,1072512951,US
1072512952,1072512959,CA
@@ -14348,12 +14309,10 @@
1073045248,1073045503,PR
1073045504,1073047551,CO
1073047552,1073049599,PR
-1073049600,1073053695,BS
-1073053696,1073091397,US
+1073049600,1073052671,BS
+1073052672,1073091397,US
1073091398,1073091407,CH
-1073091408,1073092335,US
-1073092336,1073092351,CA
-1073092352,1073093646,US
+1073091408,1073093646,US
1073093647,1073093654,PE
1073093655,1073094557,US
1073094558,1073094570,IT
@@ -14507,9 +14466,7 @@
1074229248,1074241535,CA
1074241536,1074249791,US
1074249792,1074249807,BB
-1074249808,1074371583,US
-1074371584,1074372095,A1
-1074372096,1074375935,US
+1074249808,1074375935,US
1074375936,1074376191,A1
1074376192,1074397439,US
1074397440,1074399039,CA
@@ -14620,11 +14577,11 @@
1075479104,1075479111,GB
1075479112,1075479135,CA
1075479136,1075479151,US
-1075479152,1075479567,CA
-1075479568,1075479583,US
-1075479584,1075479607,CA
+1075479152,1075479607,CA
1075479608,1075479615,US
-1075479616,1075484263,CA
+1075479616,1075480415,CA
+1075480416,1075480423,US
+1075480424,1075484263,CA
1075484264,1075484271,US
1075484272,1075494911,CA
1075494912,1075513151,US
@@ -14733,7 +14690,8 @@
1075597168,1075597183,CA
1075597184,1075597375,US
1075597376,1075597407,CA
-1075597408,1075597439,IL
+1075597408,1075597423,US
+1075597424,1075597439,IL
1075597440,1075597551,US
1075597552,1075597599,CA
1075597600,1075598367,US
@@ -14750,9 +14708,7 @@
1075601280,1075601295,CA
1075601296,1075609599,US
1075609600,1075613695,TT
-1075613696,1075744511,US
-1075744512,1075744639,NL
-1075744640,1075744767,US
+1075613696,1075744767,US
1075744768,1075748863,A2
1075748864,1075855359,US
1075855360,1075871743,DO
@@ -14762,9 +14718,13 @@
1075972352,1075973887,US
1075973888,1075974143,CA
1075974144,1075975167,US
-1075975168,1075976175,CA
+1075975168,1075975679,CA
+1075975680,1075975815,US
+1075975816,1075976175,CA
1075976176,1075976191,US
-1075976192,1075976511,CA
+1075976192,1075976447,CA
+1075976448,1075976479,US
+1075976480,1075976511,CA
1075976512,1075976543,US
1075976544,1075976647,CA
1075976648,1075976655,US
@@ -14887,8 +14847,8 @@
1076004472,1076004479,CA
1076004480,1076004495,US
1076004496,1076004511,CA
-1076004512,1076004559,US
-1076004560,1076004591,CA
+1076004512,1076004543,US
+1076004544,1076004591,CA
1076004592,1076004607,US
1076004608,1076004639,CA
1076004640,1076004703,US
@@ -14904,8 +14864,8 @@
1076005248,1076005263,US
1076005264,1076005279,CA
1076005280,1076005311,US
-1076005312,1076005319,CA
-1076005320,1076005375,US
+1076005312,1076005343,CA
+1076005344,1076005375,US
1076005376,1076005887,CA
1076005888,1076006015,US
1076006016,1076006047,CA
@@ -14952,8 +14912,8 @@
1076026608,1076026623,SG
1076026624,1076026975,CA
1076026976,1076027031,US
-1076027032,1076027263,CA
-1076027264,1076027295,US
+1076027032,1076027199,CA
+1076027200,1076027295,US
1076027296,1076027407,CA
1076027408,1076027423,US
1076027424,1076027711,CA
@@ -14974,7 +14934,9 @@
1076029224,1076029231,DM
1076029232,1076029239,CA
1076029240,1076029247,US
-1076029248,1076029311,CA
+1076029248,1076029255,CA
+1076029256,1076029263,US
+1076029264,1076029311,CA
1076029312,1076029319,GB
1076029320,1076029415,CA
1076029416,1076029422,US
@@ -15013,7 +14975,9 @@
1076035296,1076035327,EG
1076035328,1076035415,US
1076035416,1076035423,EG
-1076035424,1076036247,US
+1076035424,1076035519,US
+1076035520,1076035583,IN
+1076035584,1076036247,US
1076036248,1076036255,IL
1076036256,1076036351,US
1076036352,1076036605,ES
@@ -15061,9 +15025,13 @@
1076179162,1076179163,IN
1076179164,1076179196,US
1076179197,1076179198,IN
-1076179199,1076180795,US
+1076179199,1076180201,US
+1076180202,1076180222,PK
+1076180223,1076180795,US
1076180796,1076180799,IN
-1076180800,1076183039,US
+1076180800,1076181236,US
+1076181237,1076181237,CA
+1076181238,1076183039,US
1076183040,1076183071,IN
1076183072,1076183231,US
1076183232,1076183295,CA
@@ -15924,24 +15892,19 @@
1077626240,1077626271,WS
1077626272,1077627167,US
1077627168,1077627199,EC
-1077627200,1077628959,US
-1077628960,1077628991,ES
-1077628992,1077629071,US
+1077627200,1077629071,US
1077629072,1077629087,CR
-1077629088,1077629119,US
-1077629120,1077629151,NL
+1077629088,1077629151,US
1077629152,1077629183,CA
1077629184,1077629535,US
1077629536,1077629567,CA
1077629568,1077629903,US
1077629904,1077629919,AN
-1077629920,1077630015,US
-1077630016,1077630047,CA
-1077630048,1077632159,US
+1077629920,1077631167,US
+1077631168,1077631231,NL
+1077631232,1077632159,US
1077632160,1077632191,GB
-1077632192,1077632447,US
-1077632448,1077632479,NL
-1077632480,1077633823,US
+1077632192,1077633823,US
1077633824,1077633855,AN
1077633856,1077640799,US
1077640800,1077640831,EC
@@ -16280,7 +16243,8 @@
1077937827,1077937846,US
1077937847,1077937850,TH
1077937851,1077937854,US
-1077937855,1077937866,TH
+1077937855,1077937862,TH
+1077937863,1077937866,SA
1077937867,1077937870,GB
1077937871,1077937878,US
1077937879,1077937882,GB
@@ -16335,9 +16299,7 @@
1077938206,1077938209,AR
1077938210,1077938221,US
1077938222,1077938225,IN
-1077938226,1077938233,US
-1077938234,1077938237,AR
-1077938238,1077938258,US
+1077938226,1077938258,US
1077938259,1077938262,PE
1077938263,1077938266,CA
1077938267,1077938269,GB
@@ -16527,9 +16489,13 @@
1077939492,1077939495,GB
1077939496,1077939523,US
1077939524,1077939533,CA
-1077939534,1077939569,US
+1077939534,1077939557,US
+1077939558,1077939561,MU
+1077939562,1077939569,US
1077939570,1077939574,OM
-1077939575,1077939625,US
+1077939575,1077939582,US
+1077939583,1077939586,GH
+1077939587,1077939625,US
1077939626,1077939630,UY
1077939631,1077939634,GB
1077939635,1077939644,US
@@ -16553,7 +16519,9 @@
1077939986,1077939997,US
1077939998,1077940001,GB
1077940002,1077940005,EG
-1077940006,1077940072,US
+1077940006,1077940064,US
+1077940065,1077940068,GB
+1077940069,1077940072,US
1077940073,1077940076,BE
1077940077,1077940133,US
1077940134,1077940137,IN
@@ -16938,9 +16906,7 @@
1078287328,1078287343,US
1078287344,1078287759,CA
1078287760,1078287767,US
-1078287768,1078287775,CA
-1078287776,1078287807,US
-1078287808,1078287839,CA
+1078287768,1078287839,CA
1078287840,1078287863,US
1078287864,1078288383,CA
1078288384,1078309695,US
@@ -17078,9 +17044,7 @@
1078621696,1078621951,IN
1078621952,1078651055,US
1078651056,1078651071,CA
-1078651072,1078653695,US
-1078653696,1078653727,CZ
-1078653728,1078654431,US
+1078651072,1078654431,US
1078654432,1078654439,AU
1078654440,1078660799,US
1078660800,1078660831,CN
@@ -17315,9 +17279,7 @@
1079385088,1079385343,US
1079385344,1079385471,CA
1079385472,1079385599,US
-1079385600,1079385855,CA
-1079385856,1079386111,SZ
-1079386112,1079386623,CA
+1079385600,1079386623,CA
1079386624,1079386879,SG
1079386880,1079387135,EG
1079387136,1079387903,US
@@ -17386,7 +17348,7 @@
1079408448,1079408639,CA
1079408640,1079408895,US
1079408896,1079409407,PK
-1079409408,1079409919,LR
+1079409408,1079409919,US
1079409920,1079410687,CA
1079410688,1079410943,US
1079410944,1079411199,CA
@@ -17399,9 +17361,7 @@
1079413344,1079413535,CA
1079413536,1079413567,US
1079413568,1079414271,CA
-1079414272,1079414527,US
-1079414528,1079414783,CA
-1079414784,1079415039,US
+1079414272,1079415039,US
1079415040,1079415295,HN
1079415296,1079415807,CA
1079415808,1079416319,US
@@ -17638,7 +17598,9 @@
1081368744,1081368767,CO
1081368768,1081369119,US
1081369120,1081369151,CO
-1081369152,1081369599,US
+1081369152,1081369183,US
+1081369184,1081369215,CO
+1081369216,1081369599,US
1081369600,1081370111,CO
1081370112,1081377079,US
1081377080,1081377087,VE
@@ -17701,8 +17663,8 @@
1081401568,1081401599,AR
1081401600,1081401615,US
1081401616,1081401735,AR
-1081401736,1081401751,US
-1081401752,1081401775,AR
+1081401736,1081401743,US
+1081401744,1081401775,AR
1081401776,1081401791,US
1081401792,1081401807,AR
1081401808,1081401815,US
@@ -17785,31 +17747,31 @@
1081479168,1081483247,CA
1081483248,1081483255,US
1081483256,1081483263,CA
-1081483264,1081487359,US
-1081487360,1081487375,A2
-1081487376,1081487383,US
-1081487384,1081487391,A2
-1081487392,1081487407,US
-1081487408,1081487567,A2
-1081487568,1081487583,US
-1081487584,1081487919,A2
-1081487920,1081487927,US
-1081487928,1081487959,A2
-1081487960,1081487967,US
-1081487968,1081488055,A2
-1081488056,1081488079,US
-1081488080,1081488087,A2
-1081488088,1081488095,US
-1081488096,1081488135,A2
-1081488136,1081488151,US
-1081488152,1081488199,A2
-1081488200,1081488215,US
-1081488216,1081488223,A2
-1081488224,1081488247,US
-1081488248,1081488255,A2
-1081488256,1081488287,US
-1081488288,1081491455,A2
-1081491456,1081565183,US
+1081483264,1081487367,US
+1081487368,1081487375,A2
+1081487376,1081487407,US
+1081487408,1081487519,A2
+1081487520,1081487583,US
+1081487584,1081487871,A2
+1081487872,1081487979,US
+1081487980,1081487991,A2
+1081487992,1081488111,US
+1081488112,1081488119,A2
+1081488120,1081488123,US
+1081488124,1081488135,A2
+1081488136,1081488159,US
+1081488160,1081488167,A2
+1081488168,1081488295,US
+1081488296,1081488303,A2
+1081488304,1081488335,US
+1081488336,1081488343,A2
+1081488344,1081488351,US
+1081488352,1081488383,A2
+1081488384,1081489671,US
+1081489672,1081489679,A2
+1081489680,1081489687,US
+1081489688,1081489919,A2
+1081489920,1081565183,US
1081565184,1081573375,CA
1081573376,1081581615,US
1081581616,1081581623,JP
@@ -17908,7 +17870,19 @@
1081589112,1081589759,US
1081589760,1081593855,BB
1081593856,1081597951,CA
-1081597952,1081609823,US
+1081597952,1081608191,US
+1081608192,1081608207,CA
+1081608208,1081608223,US
+1081608224,1081608231,CA
+1081608232,1081608319,US
+1081608320,1081608327,CA
+1081608328,1081608335,US
+1081608336,1081608343,CA
+1081608344,1081608503,US
+1081608504,1081608511,CA
+1081608512,1081608575,US
+1081608576,1081608583,CA
+1081608584,1081609823,US
1081609824,1081609831,LK
1081609832,1081609887,US
1081609888,1081609919,IN
@@ -18043,9 +18017,13 @@
1082434240,1082434255,IN
1082434256,1082621987,US
1082621988,1082621991,ME
-1082621992,1082683391,US
+1082621992,1082679807,US
1082683392,1082687487,CA
-1082687488,1082885311,US
+1082687488,1082788447,US
+1082788448,1082788455,SG
+1082788456,1082788767,US
+1082788768,1082788799,SG
+1082788800,1082885311,US
1082885312,1082885343,CA
1082885344,1082885855,US
1082885856,1082885887,CA
@@ -18254,7 +18232,13 @@
1086922752,1086923343,CA
1086923344,1086923351,US
1086923352,1086930943,CA
-1086930944,1086955519,US
+1086930944,1086941831,US
+1086941832,1086941835,CA
+1086941836,1086942079,US
+1086942080,1086942087,CA
+1086942088,1086942975,US
+1086942976,1086943231,CA
+1086943232,1086955519,US
1086955520,1086971903,CA
1086971904,1087008767,US
1087008768,1087009279,CY
@@ -18267,7 +18251,7 @@
1087420160,1087440895,US
1087440896,1087442943,PR
1087442944,1087444223,US
-1087444224,1087444479,CY
+1087444224,1087444479,GB
1087444480,1087495519,US
1087495520,1087495535,TW
1087495536,1087496703,US
@@ -18491,7 +18475,18 @@
1089265664,1089265919,GB
1089265920,1089266431,US
1089266432,1089266943,GB
-1089266944,1089306623,US
+1089266944,1089282059,US
+1089282060,1089282063,CA
+1089282064,1089282075,US
+1089282076,1089282079,CA
+1089282080,1089282095,US
+1089282096,1089282099,CA
+1089282100,1089282687,US
+1089282688,1089282703,A1
+1089282704,1089282711,CA
+1089282712,1089285439,US
+1089285440,1089285455,A1
+1089285456,1089306623,US
1089306624,1089339391,PR
1089339392,1089393295,US
1089393296,1089393407,CA
@@ -18693,9 +18688,7 @@
1091695214,1091695223,CA
1091695224,1091695283,US
1091695284,1091695293,CA
-1091695294,1091797263,US
-1091797264,1091797279,IT
-1091797280,1091797855,US
+1091695294,1091797855,US
1091797856,1091797871,IT
1091797872,1091798639,US
1091798640,1091798647,CN
@@ -19595,9 +19588,7 @@
1096890880,1096891135,GB
1096891136,1096925183,US
1096925184,1096941567,CA
-1096941568,1096942679,US
-1096942680,1096942687,IE
-1096942688,1096947471,US
+1096941568,1096947471,US
1096947472,1096947479,MY
1096947480,1096950551,US
1096950552,1096950559,CA
@@ -19621,13 +19612,19 @@
1096960768,1096960895,GB
1096960896,1096964263,US
1096964264,1096964271,IN
-1096964272,1096968127,US
+1096964272,1096966303,US
+1096966304,1096966311,IN
+1096966312,1096968127,US
1096968128,1096968159,CA
1096968160,1096968191,US
1096968192,1096968319,GB
-1096968320,1096969471,US
+1096968320,1096969071,US
+1096969072,1096969079,CA
+1096969080,1096969471,US
1096969472,1096969479,IN
-1096969480,1097057623,US
+1096969480,1097056559,US
+1097056560,1097056575,SE
+1097056576,1097057623,US
1097057624,1097057631,IT
1097057632,1097057655,US
1097057656,1097057663,NZ
@@ -19665,7 +19662,9 @@
1097731456,1097736191,CA
1097736192,1097768959,US
1097768960,1097777151,CA
-1097777152,1097830399,US
+1097777152,1097797631,US
+1097797632,1097797887,DE
+1097797888,1097830399,US
1097830400,1097834495,CA
1097834496,1097896191,US
1097896192,1097896711,VI
@@ -20076,9 +20075,7 @@
1106605696,1106605703,DE
1106605704,1106685047,US
1106685048,1106685055,CA
-1106685056,1106740991,US
-1106740992,1106741247,CR
-1106741248,1106758655,US
+1106685056,1106758655,US
1106758656,1106759167,EC
1106759168,1106759679,CO
1106759680,1106767871,US
@@ -20101,15 +20098,15 @@
1107288064,1107292159,CA
1107292160,1107701759,US
1107701760,1107705855,CA
-1107705856,1107800063,US
-1107800064,1107800319,CA
-1107800320,1107801367,US
+1107705856,1107801367,US
1107801368,1107801375,CA
1107801376,1107808842,US
1107808843,1107808846,PE
1107808847,1107808877,US
1107808878,1107808881,PE
-1107808882,1107820543,US
+1107808882,1107809850,US
+1107809851,1107809851,CA
+1107809852,1107820543,US
1107820544,1107853311,ZA
1107853312,1107895039,US
1107895040,1107895807,GB
@@ -20483,8 +20480,8 @@
1110700032,1110704127,CA
1110704128,1110863871,US
1110863872,1110865919,JM
-1110865920,1110867200,KY
-1110867201,1110867967,JM
+1110865920,1110867455,KY
+1110867456,1110867967,JM
1110867968,1110870791,US
1110870792,1110870799,HK
1110870800,1110870815,US
@@ -20517,7 +20514,20 @@
1112433152,1112440831,CA
1112440832,1112530943,US
1112530944,1112539135,CA
-1112539136,1113212479,US
+1112539136,1112900711,US
+1112900712,1112900719,MV
+1112900720,1112901623,US
+1112901624,1112901631,EG
+1112901632,1112901759,US
+1112901760,1112901767,EG
+1112901768,1112903711,US
+1112903712,1112903719,TR
+1112903720,1112906431,US
+1112906432,1112906439,GB
+1112906440,1112907919,US
+1112907920,1112907935,EG
+1112907936,1112915967,US
+1112924160,1113212479,US
1113212480,1113212495,CA
1113212496,1113591807,US
1113591808,1113595903,CA
@@ -20624,10 +20634,11 @@
1114875392,1114876159,CA
1114876160,1114876447,US
1114876448,1114876463,CA
-1114876464,1114876479,US
+1114876464,1114876479,AD
1114876480,1114876543,CA
1114876544,1114876575,GB
-1114876576,1114876927,US
+1114876576,1114876911,US
+1114876912,1114876927,AD
1114876928,1114877183,CA
1114877184,1114877439,CY
1114877440,1114877695,US
@@ -20651,7 +20662,9 @@
1114881472,1114881535,CY
1114881536,1114928863,US
1114928864,1114928871,GB
-1114928872,1114930175,US
+1114928872,1114929071,US
+1114929072,1114929087,RU
+1114929088,1114930175,US
1114930176,1114930303,GB
1114930304,1114966815,US
1114966816,1114966831,GB
@@ -21036,13 +21049,7 @@
1117814824,1117814831,CN
1117814832,1117815295,US
1117815296,1117815551,CN
-1117815552,1117816831,US
-1117816832,1117816863,CN
-1117816864,1117816879,US
-1117816880,1117816887,CN
-1117816888,1117816895,US
-1117816896,1117816959,CN
-1117816960,1117817919,US
+1117815552,1117817919,US
1117817920,1117817983,CA
1117817984,1117818495,US
1117818496,1117818623,IT
@@ -21139,8 +21146,8 @@
1118133632,1118133695,US
1118133696,1118133759,IN
1118133760,1118133887,CA
-1118133888,1118134783,US
-1118134784,1118134879,CA
+1118133888,1118134815,US
+1118134816,1118134879,CA
1118134880,1118134911,US
1118134912,1118134975,CA
1118134976,1118135007,US
@@ -21149,9 +21156,7 @@
1118135568,1118135583,CA
1118135584,1118135615,US
1118135616,1118135631,TZ
-1118135632,1118135647,US
-1118135648,1118135663,CA
-1118135664,1118135807,US
+1118135632,1118135807,US
1118135808,1118136191,CA
1118136192,1118136831,US
1118136832,1118136863,IN
@@ -21295,7 +21300,9 @@
1118535680,1118539775,CA
1118539776,1118543871,US
1118543872,1118547967,CA
-1118547968,1118564607,US
+1118547968,1118563839,US
+1118563840,1118564351,BZ
+1118564352,1118564607,US
1118564608,1118564639,NO
1118564640,1118564655,US
1118564656,1118564671,IN
@@ -21520,7 +21527,7 @@
1118973160,1118973167,NI
1118973168,1118973183,A2
1118973184,1118973439,VE
-1118973440,1118973695,HK
+1118973440,1118973695,US
1118973696,1118973951,NG
1118973952,1118974015,GY
1118974016,1118974047,A2
@@ -21674,7 +21681,9 @@
1118983424,1118983679,NI
1118983680,1118983743,TZ
1118983744,1118983759,VE
-1118983760,1118983871,A2
+1118983760,1118983807,A2
+1118983808,1118983839,NG
+1118983840,1118983871,A2
1118983872,1118983879,TZ
1118983880,1118983919,US
1118983920,1118984447,A2
@@ -21940,11 +21949,15 @@
1120315136,1120315391,US
1120315392,1120321535,CA
1120321536,1120346111,US
-1120346112,1120347527,CA
+1120346112,1120347039,CA
+1120347040,1120347055,US
+1120347056,1120347135,CA
+1120347136,1120347391,US
+1120347392,1120347527,CA
1120347528,1120347535,US
1120347536,1120347591,CA
-1120347592,1120347599,US
-1120347600,1120350207,CA
+1120347592,1120347607,US
+1120347608,1120350207,CA
1120350208,1120370687,US
1120370688,1120371199,CA
1120371200,1120371455,US
@@ -21984,8 +21997,8 @@
1120376304,1120376327,CA
1120376328,1120376383,US
1120376384,1120376447,CA
-1120376448,1120376479,US
-1120376480,1120376494,CA
+1120376448,1120376455,US
+1120376456,1120376494,CA
1120376495,1120376559,US
1120376560,1120376647,CA
1120376648,1120376671,US
@@ -22015,7 +22028,9 @@
1120380128,1120380131,CA
1120380132,1120380223,US
1120380224,1120380239,CA
-1120380240,1120380415,US
+1120380240,1120380263,US
+1120380264,1120380271,CA
+1120380272,1120380415,US
1120380416,1120380431,VG
1120380432,1120380447,CA
1120380448,1120380479,US
@@ -22183,35 +22198,46 @@
1120874496,1120874503,A2
1120874504,1120874511,US
1120874512,1120874519,A2
-1120874520,1120874527,US
-1120874528,1120874631,A2
+1120874520,1120874543,US
+1120874544,1120874563,A2
+1120874564,1120874575,US
+1120874576,1120874587,A2
+1120874588,1120874591,US
+1120874592,1120874631,A2
1120874632,1120874639,US
-1120874640,1120874655,A2
-1120874656,1120874703,US
+1120874640,1120874651,A2
+1120874652,1120874703,US
1120874704,1120874719,CA
1120874720,1120874727,A2
-1120874728,1120874751,US
-1120874752,1120874783,A2
-1120874784,1120874815,US
-1120874816,1120874855,A2
-1120874856,1120874871,US
-1120874872,1120874911,A2
+1120874728,1120874763,US
+1120874764,1120874767,A2
+1120874768,1120874775,US
+1120874776,1120874779,A2
+1120874780,1120874815,US
+1120874816,1120874831,A2
+1120874832,1120874839,US
+1120874840,1120874847,A2
+1120874848,1120874879,US
+1120874880,1120874887,A2
+1120874888,1120874895,US
+1120874896,1120874911,A2
1120874912,1120874935,US
1120874936,1120874943,A2
1120874944,1120874959,CA
-1120874960,1120874967,A2
-1120874968,1120874975,US
-1120874976,1120874983,A2
-1120874984,1120875007,US
-1120875008,1120875263,A2
-1120875264,1120876287,US
+1120874960,1120874979,US
+1120874980,1120874983,A2
+1120874984,1120876287,US
1120876288,1120876543,A2
1120876544,1120876567,JO
1120876568,1120876575,A2
1120876576,1120876591,JO
1120876592,1120876599,A2
1120876600,1120876607,JO
-1120876608,1120876799,A2
+1120876608,1120876615,A2
+1120876616,1120876623,US
+1120876624,1120876655,A2
+1120876656,1120876671,US
+1120876672,1120876799,A2
1120876800,1120878359,US
1120878360,1120878591,A2
1120878592,1120886783,US
@@ -22262,7 +22288,7 @@
1121247568,1121247583,MT
1121247584,1121247591,CY
1121247592,1121247615,CA
-1121247616,1121247631,PA
+1121247616,1121247631,BZ
1121247632,1121247639,AW
1121247640,1121247647,VG
1121247648,1121247663,US
@@ -22350,18 +22376,19 @@
1121251048,1121251055,AW
1121251056,1121251071,CA
1121251072,1121251079,GB
-1121251080,1121251095,CY
+1121251080,1121251087,CA
+1121251088,1121251095,CY
1121251096,1121251103,CA
1121251104,1121251119,BZ
1121251120,1121251135,CA
1121251136,1121251167,AG
1121251168,1121251199,VG
1121251200,1121251263,AW
-1121251264,1121251271,CA
-1121251272,1121251279,KN
-1121251280,1121251295,CA
+1121251264,1121251279,CA
+1121251280,1121251287,BZ
+1121251288,1121251295,CA
1121251296,1121251311,IM
-1121251312,1121251327,PA
+1121251312,1121251327,BZ
1121251328,1121251583,CA
1121251584,1121251591,BZ
1121251592,1121251599,MT
@@ -22373,15 +22400,14 @@
1121251664,1121251671,MT
1121251672,1121251679,CA
1121251680,1121251687,AG
-1121251688,1121251775,BZ
-1121251776,1121251791,CA
+1121251688,1121251791,BZ
1121251792,1121251807,VG
1121251808,1121251831,CA
1121251832,1121251839,VG
1121251840,1121251847,BZ
1121251848,1121251855,PA
1121251856,1121251863,AN
-1121251864,1121251871,CA
+1121251864,1121251871,BZ
1121251872,1121251887,VG
1121251888,1121251895,CY
1121251896,1121251903,CA
@@ -22751,7 +22777,9 @@
1122101376,1122101383,CO
1122101384,1122101431,US
1122101432,1122101439,SG
-1122101440,1122103471,US
+1122101440,1122101471,US
+1122101472,1122101479,VE
+1122101480,1122103471,US
1122103472,1122103479,BE
1122103480,1122125996,US
1122125997,1122126004,GB
@@ -22853,19 +22881,24 @@
1123582272,1123582399,US
1123582400,1123582431,DE
1123582432,1123582463,CA
-1123582464,1123583455,US
-1123583456,1123583519,CY
+1123582464,1123583487,US
+1123583488,1123583519,CY
1123583520,1123584351,US
1123584352,1123584383,DE
1123584384,1123588063,US
1123588064,1123588095,CY
-1123588096,1123588351,DE
-1123588352,1123589631,US
+1123588096,1123589631,US
1123589632,1123589887,DE
1123589888,1123590143,US
1123590144,1123598335,VI
1123598336,1123651583,US
-1123651584,1123655679,JM
+1123651584,1123651839,JM
+1123651840,1123652095,BB
+1123652096,1123653119,JM
+1123653120,1123653375,BB
+1123653376,1123653631,JM
+1123653632,1123654655,KY
+1123654656,1123655679,JM
1123655680,1123663871,US
1123663872,1123667967,SV
1123667968,1123670015,PR
@@ -23058,7 +23091,9 @@
1125396484,1125396491,LK
1125396492,1125396999,US
1125397000,1125397007,ES
-1125397008,1125454007,US
+1125397008,1125398466,US
+1125398467,1125398468,LK
+1125398469,1125454007,US
1125454008,1125454015,GB
1125454016,1125454111,US
1125454112,1125454119,ES
@@ -23206,11 +23241,15 @@
1125541544,1125541551,CN
1125541552,1125541807,CA
1125541808,1125541815,US
-1125541816,1125543543,CA
+1125541816,1125541951,CA
+1125541952,1125541959,BM
+1125541960,1125543543,CA
1125543544,1125543551,US
1125543552,1125543687,CA
1125543688,1125543695,US
-1125543696,1125543935,CA
+1125543696,1125543887,CA
+1125543888,1125543903,US
+1125543904,1125543935,CA
1125543936,1125545983,US
1125548032,1125548291,CA
1125548292,1125548351,US
@@ -23231,13 +23270,19 @@
1125623296,1125623551,IN
1125623552,1125628671,US
1125628672,1125628703,NZ
-1125628704,1125642301,US
+1125628704,1125641790,US
+1125641791,1125641792,CA
+1125641793,1125642185,US
+1125642186,1125642189,CA
+1125642190,1125642301,US
1125642302,1125642303,IN
1125642304,1125642674,US
1125642675,1125642694,BO
-1125642695,1126009343,US
-1126009344,1126009599,AR
-1126009600,1126504223,US
+1125642695,1125644770,US
+1125644771,1125644771,PK
+1125644772,1125645449,US
+1125645450,1125645453,CA
+1125645454,1126504223,US
1126504224,1126504231,PR
1126504232,1126551767,US
1126551768,1126551775,PR
@@ -23354,8 +23399,14 @@
1133785504,1133785567,US
1133785568,1133785599,BE
1133785600,1134029055,US
-1134029056,1134029567,A2
-1134029568,1134444543,US
+1134029056,1134029151,A2
+1134029152,1134029159,US
+1134029160,1134029183,A2
+1134029184,1134029215,US
+1134029216,1134029567,A2
+1134029568,1134440447,US
+1134440448,1134443520,CN
+1134443521,1134444543,US
1134444544,1134448639,CA
1134448640,1134545919,US
1134545920,1134545951,BH
@@ -24411,7 +24462,9 @@
1137928064,1137928191,PA
1137928192,1137928255,CA
1137928256,1137928319,BZ
-1137928320,1137930143,CA
+1137928320,1137929727,CA
+1137929728,1137929983,IE
+1137929984,1137930143,CA
1137930144,1137930159,MT
1137930160,1137934335,CA
1137934336,1137946145,US
@@ -24550,9 +24603,13 @@
1138337208,1138417663,US
1138417664,1138417695,CA
1138417696,1138417727,DE
-1138417728,1138421759,US
+1138417728,1138419711,US
+1138419712,1138419967,DE
+1138419968,1138421759,US
1138421760,1138421791,DE
-1138421792,1138425855,US
+1138421792,1138422271,US
+1138422272,1138422527,DE
+1138422528,1138425855,US
1138425856,1138427519,KN
1138427520,1138427647,US
1138427648,1138429951,KN
@@ -24644,9 +24701,11 @@
1138512896,1138512927,ID
1138512928,1138544895,US
1138544896,1138545151,GB
-1138545152,1138548735,US
-1138548736,1138556927,CA
-1138556928,1138593791,US
+1138545152,1138548991,US
+1138548992,1138549247,CA
+1138549248,1138553087,US
+1138553088,1138553343,CA
+1138553344,1138593791,US
1138593792,1138597887,CA
1138597888,1138600447,US
1138600448,1138600703,BE
@@ -24692,12 +24751,14 @@
1138656207,1138656222,US
1138656223,1138656230,EG
1138656231,1138656597,US
-1138656598,1138656605,EG
-1138656606,1138656661,US
+1138656598,1138656613,EG
+1138656614,1138656661,US
1138656662,1138656669,MA
1138656670,1138656745,US
1138656746,1138656753,AE
-1138656754,1138657101,US
+1138656754,1138656909,US
+1138656910,1138656917,IN
+1138656918,1138657101,US
1138657102,1138657109,IN
1138657110,1138657123,US
1138657124,1138657131,EG
@@ -24720,7 +24781,8 @@
1138658058,1138658123,GB
1138658124,1138658131,US
1138658132,1138658163,EG
-1138658164,1138658175,US
+1138658164,1138658167,US
+1138658168,1138658175,EG
1138658176,1138658302,GB
1138658303,1138658431,US
1138658432,1138658496,PK
@@ -24750,7 +24812,8 @@
1138659790,1138659797,ID
1138659798,1138659805,US
1138659806,1138659813,ID
-1138659814,1138659823,US
+1138659814,1138659821,LK
+1138659822,1138659823,US
1138659824,1138659831,ID
1138659832,1138659849,US
1138659850,1138659857,MA
@@ -24761,7 +24824,9 @@
1138659984,1138659999,EG
1138660000,1138660035,US
1138660036,1138660043,IN
-1138660044,1138660105,US
+1138660044,1138660050,US
+1138660051,1138660058,PH
+1138660059,1138660105,US
1138660106,1138660137,GB
1138660138,1138660169,US
1138660170,1138660177,MA
@@ -24792,9 +24857,7 @@
1138660806,1138660821,EG
1138660822,1138660873,US
1138660874,1138660881,EG
-1138660882,1138660889,US
-1138660890,1138660897,EG
-1138660898,1138660921,US
+1138660882,1138660921,US
1138660922,1138660929,EG
1138660930,1138660958,US
1138660959,1138660966,MA
@@ -24818,7 +24881,7 @@
1138661308,1138661417,US
1138661418,1138661425,LK
1138661426,1138661457,US
-1138661458,1138661465,IN
+1138661458,1138661465,EG
1138661466,1138661521,US
1138661522,1138661529,EG
1138661530,1138661553,US
@@ -24840,9 +24903,7 @@
1138661822,1138661829,MA
1138661830,1138661913,US
1138661914,1138661954,EG
-1138661955,1138661977,US
-1138661978,1138661993,EG
-1138661994,1138662057,US
+1138661955,1138662057,US
1138662058,1138662089,EG
1138662090,1138662097,ID
1138662098,1138662105,US
@@ -24910,8 +24971,8 @@
1139146752,1139154943,GT
1139154944,1139167231,JM
1139167232,1139167743,US
-1139167744,1139169023,PR
-1139169024,1139169279,US
+1139167744,1139168895,PR
+1139168896,1139169279,US
1139169280,1139170047,PR
1139170048,1139171327,US
1139171328,1139175423,GT
@@ -24946,9 +25007,7 @@
1142204104,1142204111,PR
1142204112,1142204327,US
1142204328,1142204335,PR
-1142204336,1145053455,US
-1145053456,1145053471,NG
-1145053472,1145056703,US
+1142204336,1145056703,US
1145056704,1145056719,CO
1145056720,1145188351,US
1145188352,1145192447,CA
@@ -24968,9 +25027,7 @@
1145261312,1145261375,IN
1145261376,1145307135,US
1145307136,1145311231,CA
-1145311232,1145331711,US
-1145331712,1145331967,DK
-1145331968,1145333031,US
+1145311232,1145333031,US
1145333032,1145333039,IT
1145333040,1145333191,US
1145333192,1145333199,CN
@@ -25019,7 +25076,9 @@
1145503744,1145520127,CA
1145520128,1145552895,US
1145552896,1145556991,CA
-1145556992,1150043135,US
+1145556992,1145567839,US
+1145567840,1145567871,CN
+1145567872,1150043135,US
1150043136,1150044159,VA
1150044160,1150046207,US
1150046208,1150050303,JP
@@ -25095,8 +25154,8 @@
1156130016,1156130303,CA
1156130304,1156131327,US
1156131328,1156131583,CA
-1156131584,1156259839,US
-1156259840,1156265983,CA
+1156131584,1156263935,US
+1156263936,1156265983,CA
1156265984,1156296703,US
1156296704,1156300799,CA
1156300800,1157670431,US
@@ -25391,7 +25450,9 @@
1158732885,1158736241,US
1158736242,1158736249,IN
1158736250,1158774783,US
-1158774784,1158791167,CA
+1158774784,1158776947,CA
+1158776948,1158776951,US
+1158776952,1158791167,CA
1158791168,1158794239,BM
1158794240,1158794495,US
1158794496,1158799359,BM
@@ -25439,7 +25500,9 @@
1158945096,1158945103,TH
1158945104,1158945111,RU
1158945112,1158945119,CA
-1158945120,1158945271,US
+1158945120,1158945127,US
+1158945128,1158945135,MX
+1158945136,1158945271,US
1158945272,1158945287,CA
1158945288,1158945319,US
1158945320,1158945335,CA
@@ -25511,9 +25574,7 @@
1158949288,1158949295,CA
1158949296,1158949407,US
1158949408,1158949415,ZA
-1158949416,1158949775,US
-1158949776,1158949783,GB
-1158949784,1158950105,US
+1158949416,1158950105,US
1158950106,1158950107,CA
1158950108,1158950319,US
1158950320,1158950327,CA
@@ -25542,7 +25603,9 @@
1158951744,1158951751,IN
1158951752,1158951839,US
1158951840,1158951855,CA
-1158951856,1158952743,US
+1158951856,1158952711,US
+1158952712,1158952719,IN
+1158952720,1158952743,US
1158952744,1158952751,FI
1158952752,1158952815,US
1158952816,1158952823,CA
@@ -25568,22 +25631,23 @@
1158957472,1158957647,US
1158957648,1158957655,AU
1158957656,1158957663,PE
-1158957664,1158957695,US
-1158957696,1158957703,TH
-1158957704,1158958295,US
+1158957664,1158958295,US
1158958296,1158958303,AG
1158958304,1158958311,ES
1158958312,1158958367,US
1158958368,1158958375,CA
1158958376,1158958591,US
1158958592,1158958599,ZA
-1158958600,1158958671,US
+1158958600,1158958607,IL
+1158958608,1158958671,US
1158958672,1158958679,SA
1158958680,1158958719,US
1158958720,1158958751,CA
1158958752,1158959031,US
1158959032,1158959039,CA
-1158959040,1158959135,US
+1158959040,1158959079,US
+1158959080,1158959081,BG
+1158959082,1158959135,US
1158959136,1158959151,BD
1158959152,1158959679,US
1158959680,1158959687,CR
@@ -25605,7 +25669,9 @@
1158961256,1158961263,ES
1158961264,1158961775,US
1158961776,1158961783,CA
-1158961784,1158962175,US
+1158961784,1158962023,US
+1158962024,1158962027,IL
+1158962028,1158962175,US
1158962176,1158962183,GB
1158962184,1158962287,US
1158962288,1158962295,ZA
@@ -25735,9 +25801,12 @@
1159262492,1159262727,US
1159262728,1159262731,DE
1159262732,1159262735,RU
-1159262736,1159262743,US
+1159262736,1159262739,US
+1159262740,1159262743,DE
1159262744,1159262751,RU
-1159262752,1159266935,US
+1159262752,1159262967,US
+1159262968,1159262975,RU
+1159262976,1159266935,US
1159266936,1159266943,PR
1159266944,1159269119,US
1159269120,1159269375,AR
@@ -25745,17 +25814,15 @@
1159274496,1159274751,GB
1159274752,1159276799,US
1159276800,1159277055,A2
-1159277056,1159279359,US
-1159279360,1159279615,PR
-1159279616,1159281151,US
-1159281152,1159281407,HK
-1159281408,1159281679,US
+1159277056,1159281679,US
1159281680,1159281695,HK
1159281696,1159281727,US
1159281728,1159281743,HK
1159281744,1159281919,US
-1159281920,1159282175,HK
-1159282176,1159292807,US
+1159281920,1159282175,GB
+1159282176,1159290655,US
+1159290656,1159290687,CA
+1159290688,1159292807,US
1159292808,1159292815,AU
1159292816,1159293343,US
1159293344,1159293359,KR
@@ -25841,9 +25908,7 @@
1159521824,1159521855,US
1159521856,1159522031,CA
1159522032,1159522047,US
-1159522048,1159522063,CA
-1159522064,1159522071,US
-1159522072,1159522095,CA
+1159522048,1159522095,CA
1159522096,1159522111,US
1159522112,1159522143,CA
1159522144,1159522167,US
@@ -26080,7 +26145,9 @@
1160662488,1160662495,GB
1160662496,1160662743,US
1160662744,1160662751,GB
-1160662752,1160665623,US
+1160662752,1160663679,US
+1160663680,1160663711,HK
+1160663712,1160665623,US
1160665624,1160665631,GB
1160665632,1160665807,US
1160665808,1160665815,GB
@@ -26322,17 +26389,21 @@
1161627704,1161627711,DE
1161627712,1161627727,US
1161627728,1161627743,AR
-1161627744,1161627751,RO
-1161627752,1161627759,US
+1161627744,1161627751,US
+1161627752,1161627759,PL
1161627760,1161627775,GB
-1161627776,1161627807,US
+1161627776,1161627783,US
+1161627784,1161627791,GB
+1161627792,1161627807,US
1161627808,1161627815,SI
1161627816,1161627823,US
1161627824,1161627831,AU
1161627832,1161627839,US
-1161627840,1161627863,AR
+1161627840,1161627847,AR
+1161627848,1161627855,US
+1161627856,1161627863,AR
1161627864,1161627871,CA
-1161627872,1161627879,HR
+1161627872,1161627879,SI
1161627880,1161627895,US
1161627896,1161627903,CA
1161627904,1161628447,US
@@ -26340,7 +26411,9 @@
1161628456,1161628463,GB
1161628464,1161628479,US
1161628480,1161628487,GB
-1161628488,1161628607,US
+1161628488,1161628519,US
+1161628520,1161628527,PL
+1161628528,1161628607,US
1161628608,1161628639,AR
1161628640,1161628647,IN
1161628648,1161628663,US
@@ -26357,7 +26430,7 @@
1161629344,1161629375,FI
1161629376,1161629383,CA
1161629384,1161629391,AR
-1161629392,1161629399,IE
+1161629392,1161629399,GB
1161629400,1161629407,IL
1161629408,1161629415,GB
1161629416,1161629423,SI
@@ -26366,10 +26439,10 @@
1161629440,1161629519,US
1161629520,1161629527,GB
1161629528,1161629535,MY
-1161629536,1161629567,GB
-1161629568,1161629583,US
+1161629536,1161629583,US
1161629584,1161629599,GB
-1161629600,1161629615,US
+1161629600,1161629607,PL
+1161629608,1161629615,US
1161629616,1161629631,GB
1161629632,1161629663,US
1161629664,1161629671,AU
@@ -26377,7 +26450,8 @@
1161629696,1161629951,PL
1161629952,1161630223,US
1161630224,1161630231,NL
-1161630232,1161630255,US
+1161630232,1161630247,US
+1161630248,1161630255,HR
1161630256,1161630263,NL
1161630264,1161630271,AR
1161630272,1161630335,US
@@ -26472,7 +26546,16 @@
1161633024,1161633055,CA
1161633056,1161633215,US
1161633216,1161633231,EE
-1161633232,1161633631,US
+1161633232,1161633239,US
+1161633240,1161633247,AU
+1161633248,1161633263,US
+1161633264,1161633271,PL
+1161633272,1161633543,US
+1161633544,1161633551,AR
+1161633552,1161633559,US
+1161633560,1161633567,IL
+1161633568,1161633583,PL
+1161633584,1161633631,US
1161633632,1161633639,CA
1161633640,1161634055,US
1161634056,1161634063,IN
@@ -26488,29 +26571,26 @@
1161634224,1161634231,VN
1161634232,1161634239,US
1161634240,1161634247,GB
-1161634248,1161634271,US
-1161634272,1161634287,CH
-1161634288,1161634335,US
-1161634336,1161634352,PL
-1161634353,1161634495,US
+1161634248,1161634335,US
+1161634336,1161634351,PL
+1161634352,1161634495,US
1161634496,1161634503,GB
1161634504,1161634519,US
1161634520,1161634527,BG
-1161634528,1161634943,US
+1161634528,1161634815,US
+1161634816,1161634831,PL
+1161634832,1161634943,US
1161634944,1161634959,PL
-1161634960,1161634975,US
-1161634976,1161635007,PL
+1161634960,1161635007,US
1161635008,1161635071,KW
1161635072,1161635855,US
1161635856,1161635871,BE
-1161635872,1161636063,US
-1161636064,1161636095,IL
+1161635872,1161635887,PL
+1161635888,1161636095,US
1161636096,1161636127,GB
1161636128,1161636159,US
1161636160,1161636223,IL
-1161636224,1161636415,US
-1161636416,1161636447,PL
-1161636448,1161636463,US
+1161636224,1161636463,US
1161636464,1161636471,EG
1161636472,1161636495,US
1161636496,1161636503,CA
@@ -26734,14 +26814,18 @@
1161791322,1161791330,CA
1161791331,1161791381,US
1161791382,1161791386,CA
-1161791387,1161795979,US
+1161791387,1161794468,US
+1161794469,1161794472,ZA
+1161794473,1161794649,US
+1161794650,1161794654,ZA
+1161794655,1161795979,US
1161795980,1161795983,CA
1161795984,1161818111,US
1161818112,1161822207,CA
1161822208,1161832767,US
1161832768,1161832831,BR
1161832832,1161833759,US
-1161833760,1161833791,FR
+1161833760,1161833791,TR
1161833792,1161833855,US
1161833856,1161833887,FR
1161833888,1161833919,US
@@ -26846,7 +26930,7 @@
1162383072,1162393759,US
1162393760,1162393767,IN
1162393768,1162394463,US
-1162394464,1162394471,IE
+1162394464,1162394471,GB
1162394472,1162401519,US
1162401520,1162401527,IN
1162401528,1162408455,US
@@ -26998,7 +27082,9 @@
1163398144,1163398239,A2
1163398240,1163398303,BD
1163398304,1163398367,A2
-1163398368,1163399039,BD
+1163398368,1163398399,BD
+1163398400,1163398655,US
+1163398656,1163399039,BD
1163399040,1163399103,A2
1163399104,1163399295,BD
1163399296,1163399679,A2
@@ -27052,17 +27138,15 @@
1163477728,1163478047,US
1163478048,1163478063,JP
1163478064,1163526143,US
-1163526144,1163526463,CA
-1163526464,1163526655,US
+1163526144,1163526471,CA
+1163526472,1163526655,US
1163526656,1163527023,CA
1163527024,1163527039,BV
1163527040,1163527059,CA
1163527060,1163527071,US
1163527072,1163527103,CA
1163527104,1163527135,US
-1163527136,1163527679,CA
-1163527680,1163527743,US
-1163527744,1163527783,CA
+1163527136,1163527783,CA
1163527784,1163527791,US
1163527792,1163529215,CA
1163529216,1163530239,US
@@ -27080,9 +27164,7 @@
1163530960,1163530967,US
1163530968,1163533023,CA
1163533024,1163533055,US
-1163533056,1163533511,CA
-1163533512,1163533519,US
-1163533520,1163533551,CA
+1163533056,1163533551,CA
1163533552,1163533567,PA
1163533568,1163533695,CA
1163533696,1163533727,US
@@ -27176,9 +27258,7 @@
1163547536,1163547539,US
1163547540,1163547567,CA
1163547568,1163547583,VG
-1163547584,1163547647,CA
-1163547648,1163547903,US
-1163547904,1163547951,CA
+1163547584,1163547951,CA
1163547952,1163547983,US
1163547984,1163550335,CA
1163550336,1163550351,US
@@ -27206,7 +27286,9 @@
1163552576,1163552607,PA
1163552608,1163552679,CA
1163552680,1163552687,US
-1163552688,1163553855,CA
+1163552688,1163552695,CA
+1163552696,1163552703,US
+1163552704,1163553855,CA
1163553856,1163553871,US
1163553872,1163553919,CA
1163553920,1163553935,BV
@@ -27248,9 +27330,7 @@
1163570496,1163571199,US
1163571200,1163571983,CA
1163571984,1163571999,US
-1163572000,1163572031,CA
-1163572032,1163572063,BE
-1163572064,1163572175,CA
+1163572000,1163572175,CA
1163572176,1163572183,US
1163572184,1163572687,CA
1163572688,1163572703,US
@@ -27310,12 +27390,12 @@
1163582160,1163582167,FI
1163582168,1163582183,CA
1163582184,1163582191,US
-1163582192,1163583487,CA
-1163583488,1163585199,US
+1163582192,1163583231,CA
+1163583232,1163585199,US
1163585200,1163585215,CA
1163585216,1163585855,US
-1163585856,1163585887,CA
-1163585888,1163585889,US
+1163585856,1163585871,CA
+1163585872,1163585889,US
1163585890,1163585905,GB
1163585906,1163586740,US
1163586741,1163586743,CA
@@ -27331,12 +27411,14 @@
1163588216,1163588223,US
1163588224,1163588607,CA
1163588608,1163588608,US
-1163588609,1163588655,CA
-1163588656,1163588671,US
-1163588672,1163588695,CA
+1163588609,1163588695,CA
1163588696,1163588703,US
1163588704,1163588727,CA
-1163588728,1163588863,US
+1163588728,1163588799,US
+1163588800,1163588815,CA
+1163588816,1163588831,US
+1163588832,1163588847,CA
+1163588848,1163588863,US
1163588864,1163589631,CA
1163589632,1163870575,US
1163870576,1163870583,CN
@@ -27348,7 +27430,13 @@
1167319112,1167319119,ZA
1167319120,1167319255,US
1167319256,1167319263,CA
-1167319264,1167321959,US
+1167319264,1167319359,US
+1167319360,1167319367,CA
+1167319368,1167320071,US
+1167320072,1167320079,CA
+1167320080,1167321447,US
+1167321448,1167321455,CA
+1167321456,1167321959,US
1167321960,1167321967,GB
1167321968,1167322695,US
1167322696,1167322703,IN
@@ -27360,7 +27448,9 @@
1167324048,1167324055,CA
1167324056,1167324287,US
1167324288,1167324295,GB
-1167324296,1167325727,US
+1167324296,1167324311,US
+1167324312,1167324319,CA
+1167324320,1167325727,US
1167325728,1167325735,CA
1167325736,1167325935,US
1167325936,1167325951,CA
@@ -27457,9 +27547,7 @@
1168954076,1168954079,CA
1168954080,1168954623,US
1168954624,1168954687,IN
-1168954688,1168954751,US
-1168954752,1168954879,CA
-1168954880,1168955647,US
+1168954688,1168955647,US
1168955648,1168956159,CA
1168956160,1168957439,US
1168957440,1168958047,CA
@@ -27474,7 +27562,8 @@
1168958212,1168958215,CA
1168958216,1168958223,US
1168958224,1168958231,SG
-1168958232,1168958423,CA
+1168958232,1168958239,US
+1168958240,1168958423,CA
1168958424,1168958463,US
1168958464,1168958479,CA
1168958480,1168958495,US
@@ -27549,8 +27638,7 @@
1170457664,1170458063,US
1170458064,1170458079,DE
1170458080,1170461055,US
-1170461056,1170461439,CO
-1170461440,1170461695,US
+1170461056,1170461695,CO
1170461696,1170462719,IL
1170462720,1170465791,US
1170465792,1170466047,CY
@@ -27561,7 +27649,14 @@
1170467840,1170468351,DO
1170468352,1170469055,US
1170469056,1170469071,VG
-1170469072,1170472959,US
+1170469072,1170470911,US
+1170470912,1170471167,ES
+1170471168,1170471375,US
+1170471376,1170471391,UY
+1170471392,1170471903,US
+1170471904,1170471919,BE
+1170471920,1170472703,US
+1170472704,1170472959,VG
1170472960,1170481151,CA
1170481152,1170489343,US
1170489344,1170497535,CA
@@ -27578,22 +27673,24 @@
1170539461,1170539461,PK
1170539462,1170539522,US
1170539523,1170539523,AU
-1170539524,1170539589,US
+1170539524,1170539586,US
+1170539587,1170539587,SC
+1170539588,1170539589,US
1170539590,1170539590,SA
1170539591,1170539591,CN
1170539592,1170539592,AU
-1170539593,1170539650,US
-1170539651,1170539651,TR
-1170539652,1170539652,US
+1170539593,1170539652,US
1170539653,1170539653,GB
1170539654,1170539712,US
1170539713,1170539713,CN
1170539714,1170539714,US
1170539715,1170539715,PK
-1170539716,1170539777,US
+1170539716,1170539776,US
+1170539777,1170539777,SC
1170539778,1170539778,CN
-1170539779,1170539780,US
-1170539781,1170539781,KR
+1170539779,1170539779,SC
+1170539780,1170539780,US
+1170539781,1170539781,PR
1170539782,1170539841,US
1170539842,1170539842,BD
1170539843,1170539843,MY
@@ -27611,9 +27708,7 @@
1170540106,1170540106,CN
1170540107,1170540163,US
1170540164,1170540164,RO
-1170540165,1170540228,US
-1170540229,1170540229,TR
-1170540230,1170540230,US
+1170540165,1170540230,US
1170540231,1170540231,KR
1170540232,1170540232,CN
1170540233,1170540288,US
@@ -27622,8 +27717,7 @@
1170540292,1170540292,TR
1170540293,1170540294,US
1170540295,1170540295,CN
-1170540296,1170540296,TR
-1170540297,1170540353,US
+1170540296,1170540353,US
1170540354,1170540354,CN
1170540355,1170540359,US
1170540360,1170540360,CN
@@ -27638,17 +27732,21 @@
1170540429,1170540429,TR
1170540430,1170540480,US
1170540481,1170540481,TR
-1170540482,1170540485,US
-1170540486,1170540487,TR
+1170540482,1170540486,US
+1170540487,1170540487,TR
1170540488,1170540491,US
1170540492,1170540494,TR
-1170540495,1170540608,US
+1170540495,1170540496,US
+1170540497,1170540497,CZ
+1170540498,1170540608,US
1170540609,1170540609,CN
1170540610,1170540616,US
1170540617,1170540617,TR
1170540618,1170542863,US
1170542864,1170542871,CN
-1170542872,1170544127,US
+1170542872,1170543747,US
+1170543748,1170543751,PR
+1170543752,1170544127,US
1170544128,1170544191,CN
1170544192,1170544195,US
1170544196,1170544199,BD
@@ -27664,19 +27762,20 @@
1170544396,1170544431,US
1170544432,1170544439,CN
1170544440,1170544443,AU
-1170544444,1170544511,US
-1170544512,1170544543,TR
-1170544544,1170544807,US
+1170544444,1170544807,US
1170544808,1170544815,CN
1170544816,1170544831,US
1170544832,1170544959,CN
1170544960,1170544983,US
1170544984,1170544987,CN
-1170544988,1170545055,US
+1170544988,1170544991,US
+1170544992,1170545023,SC
+1170545024,1170545055,US
1170545056,1170545087,CN
1170545088,1170545407,US
1170545408,1170545439,TR
-1170545440,1170545595,US
+1170545440,1170545471,SC
+1170545472,1170545595,US
1170545596,1170545599,CN
1170545600,1170552607,US
1170552608,1170552611,CN
@@ -27702,16 +27801,15 @@
1170553628,1170553631,TR
1170553632,1170553635,US
1170553636,1170553643,SA
-1170553644,1170553647,TR
-1170553648,1170553651,US
+1170553644,1170553651,US
1170553652,1170553655,TR
1170553656,1170553663,US
1170553664,1170553667,SA
-1170553668,1170553683,US
+1170553668,1170553675,US
+1170553676,1170553679,SC
+1170553680,1170553683,US
1170553684,1170553687,CN
-1170553688,1170553707,US
-1170553708,1170553711,TR
-1170553712,1170553855,US
+1170553688,1170553855,US
1170553856,1170553983,MY
1170553984,1170554047,CN
1170554048,1170554367,US
@@ -27745,7 +27843,9 @@
1176512152,1176512159,GB
1176512160,1176512703,US
1176512704,1176512711,ZA
-1176512712,1176513879,US
+1176512712,1176513479,US
+1176513480,1176513487,CA
+1176513488,1176513879,US
1176513880,1176513887,GB
1176513888,1176514271,US
1176514272,1176514303,IN
@@ -27789,10 +27889,9 @@
1176621888,1176622047,CA
1176622048,1176622079,US
1176622080,1176622335,GB
-1176622336,1176622367,US
-1176622368,1176622431,CA
-1176622432,1176622527,US
-1176622528,1176622559,CA
+1176622336,1176622431,CA
+1176622432,1176622455,US
+1176622456,1176622559,CA
1176622560,1176622591,US
1176622592,1176623359,CA
1176623360,1176623487,US
@@ -28115,7 +28214,9 @@
1177165312,1177165823,CA
1177165824,1177167743,US
1177167744,1177167751,LB
-1177167752,1177168223,US
+1177167752,1177167839,US
+1177167840,1177167847,IL
+1177167848,1177168223,US
1177168224,1177168231,IE
1177168232,1177175199,US
1177175200,1177175231,CZ
@@ -28408,7 +28509,9 @@
1208205984,1208205991,GB
1208205992,1208206439,US
1208206440,1208206463,CA
-1208206464,1208207183,US
+1208206464,1208207095,US
+1208207096,1208207097,IN
+1208207098,1208207183,US
1208207184,1208207191,AU
1208207192,1208207303,US
1208207304,1208207311,ZA
@@ -28542,7 +28645,8 @@
1208338176,1208516607,US
1208516608,1208516623,MX
1208516624,1208516639,US
-1208516640,1208516735,TR
+1208516640,1208516671,TR
+1208516672,1208516735,US
1208516736,1208516799,ID
1208516800,1208516855,US
1208516856,1208516859,CN
@@ -28584,8 +28688,9 @@
1208518400,1208518655,ID
1208518656,1208519167,US
1208519168,1208519423,CN
-1208519424,1208519551,TR
-1208519552,1208521983,US
+1208519424,1208519679,US
+1208519680,1208519935,GB
+1208519936,1208521983,US
1208521984,1208522239,CN
1208522240,1208522271,US
1208522272,1208522303,TR
@@ -28599,8 +28704,7 @@
1208523992,1208523995,TR
1208523996,1208523999,US
1208524000,1208524031,TR
-1208524032,1208524047,US
-1208524048,1208524055,TR
+1208524032,1208524055,US
1208524056,1208524059,CN
1208524060,1208524063,US
1208524064,1208524079,CN
@@ -28625,21 +28729,23 @@
1208526080,1208526335,US
1208526336,1208526591,CN
1208526592,1208526607,TR
-1208526608,1208526623,US
-1208526624,1208526655,TR
-1208526656,1208526815,US
+1208526608,1208526815,US
1208526816,1208526847,CN
1208526848,1208527871,US
1208527872,1208527887,VN
1208527888,1208527903,US
-1208527904,1208528127,VN
+1208527904,1208528015,VN
+1208528016,1208528031,SC
+1208528032,1208528127,VN
1208528128,1208531007,US
1208531008,1208531071,CN
1208531072,1208531455,US
1208531456,1208531583,CN
1208531584,1208531711,US
1208531712,1208531967,PK
-1208531968,1208532287,US
+1208531968,1208531995,US
+1208531996,1208531999,GB
+1208532000,1208532287,US
1208532288,1208532351,PK
1208532352,1208586364,US
1208586365,1208586372,MA
@@ -28651,7 +28757,7 @@
1208586527,1208586536,TR
1208586537,1208586573,US
1208586574,1208586581,MX
-1208586582,1208586589,US
+1208586582,1208586589,LK
1208586590,1208586597,NZ
1208586598,1208586662,US
1208586663,1208586670,GB
@@ -28675,7 +28781,9 @@
1208587026,1208587033,NZ
1208587034,1208587045,US
1208587046,1208587053,IN
-1208587054,1208587169,US
+1208587054,1208587087,US
+1208587088,1208587095,LK
+1208587096,1208587169,US
1208587170,1208587177,MX
1208587178,1208587187,US
1208587188,1208587195,EG
@@ -28751,15 +28859,21 @@
1208588973,1208588985,GB
1208588986,1208588989,US
1208588990,1208589000,GB
-1208589001,1208589065,US
+1208589001,1208589043,US
+1208589044,1208589051,BH
+1208589052,1208589065,US
1208589066,1208589081,CA
1208589082,1208589156,US
1208589157,1208589165,GB
1208589166,1208589174,US
1208589175,1208589186,CA
-1208589187,1208589321,US
+1208589187,1208589299,US
+1208589300,1208589307,LK
+1208589308,1208589321,US
1208589322,1208589329,CA
-1208589330,1208589379,US
+1208589330,1208589341,US
+1208589342,1208589349,ID
+1208589350,1208589379,US
1208589380,1208589387,EG
1208589388,1208589577,US
1208589578,1208589585,GB
@@ -28767,11 +28881,19 @@
1208589640,1208589651,TR
1208589652,1208589857,US
1208589858,1208589865,MA
-1208589866,1208589970,US
+1208589866,1208589901,US
+1208589902,1208589913,EG
+1208589914,1208589915,US
+1208589916,1208589917,EG
+1208589918,1208589970,US
1208589971,1208590002,GB
1208590003,1208590004,US
1208590005,1208590014,GB
-1208590015,1208590061,US
+1208590015,1208590031,US
+1208590032,1208590033,EG
+1208590034,1208590041,US
+1208590042,1208590055,EG
+1208590056,1208590061,US
1208590062,1208590071,CN
1208590072,1208590091,US
1208590092,1208590108,GB
@@ -28956,10 +29078,11 @@
1209271084,1209271087,BR
1209271088,1209271127,US
1209271128,1209271131,SA
-1209271132,1209271187,US
-1209271188,1209271191,TR
+1209271132,1209271191,US
1209271192,1209271195,RO
-1209271196,1209271215,US
+1209271196,1209271207,US
+1209271208,1209271211,SC
+1209271212,1209271215,US
1209271216,1209271219,IN
1209271220,1209271367,US
1209271368,1209271371,TR
@@ -28980,8 +29103,7 @@
1209271544,1209271551,CN
1209271552,1209271567,US
1209271568,1209271571,PL
-1209271572,1209271575,TR
-1209271576,1209271579,US
+1209271572,1209271579,US
1209271580,1209271583,BD
1209271584,1209271607,US
1209271608,1209271611,KH
@@ -29011,7 +29133,9 @@
1209271848,1209271855,IN
1209271856,1209271867,US
1209271868,1209271871,BR
-1209271872,1209271951,US
+1209271872,1209271923,US
+1209271924,1209271927,CA
+1209271928,1209271951,US
1209271952,1209271955,KH
1209271956,1209271963,US
1209271964,1209271967,TR
@@ -29019,20 +29143,15 @@
1209271972,1209271975,TR
1209271976,1209271979,CA
1209271980,1209271983,ZA
-1209271984,1209271999,US
+1209271984,1209271995,US
+1209271996,1209271999,SC
1209272000,1209272007,TR
1209272008,1209272011,PL
-1209272012,1209272043,US
-1209272044,1209272047,TR
-1209272048,1209272079,US
-1209272080,1209272095,TR
-1209272096,1209272127,US
+1209272012,1209272127,US
1209272128,1209272159,CN
1209272160,1209272175,US
1209272176,1209272191,BR
-1209272192,1209272223,TR
-1209272224,1209272239,US
-1209272240,1209272255,TR
+1209272192,1209272255,US
1209272256,1209272287,CN
1209272288,1209272383,US
1209272384,1209272399,CN
@@ -29050,11 +29169,9 @@
1209272624,1209272655,US
1209272656,1209272671,TR
1209272672,1209272719,US
-1209272720,1209272767,CN
-1209272768,1209272783,TR
-1209272784,1209272847,US
-1209272848,1209272863,TR
-1209272864,1209272895,US
+1209272720,1209272735,PR
+1209272736,1209272767,CN
+1209272768,1209272895,US
1209272896,1209272959,CN
1209272960,1209273023,BR
1209273024,1209273055,US
@@ -29068,15 +29185,18 @@
1209273280,1209273311,BR
1209273312,1209273359,US
1209273360,1209273407,TR
-1209273408,1209273555,US
+1209273408,1209273471,CZ
+1209273472,1209273555,US
1209273556,1209273559,CA
1209273560,1209273647,US
1209273648,1209273655,CN
1209273656,1209273663,AU
1209273664,1209273671,BD
-1209273672,1209273999,US
-1209274000,1209274015,TR
-1209274016,1209274023,US
+1209273672,1209273675,US
+1209273676,1209273679,GB
+1209273680,1209273991,US
+1209273992,1209273999,SC
+1209274000,1209274023,US
1209274024,1209274031,RO
1209274032,1209274039,TR
1209274040,1209274047,US
@@ -29084,28 +29204,34 @@
1209274112,1209274115,US
1209274116,1209274119,CZ
1209274120,1209274135,US
-1209274136,1209274151,TR
-1209274152,1209274367,US
-1209274368,1209274495,TR
+1209274136,1209274143,TR
+1209274144,1209274175,US
+1209274176,1209274239,SC
+1209274240,1209274495,US
1209274496,1209274527,CN
1209274528,1209274543,US
1209274544,1209274559,TR
-1209274560,1209274815,US
+1209274560,1209274607,US
+1209274608,1209274623,SC
+1209274624,1209274815,US
1209274816,1209274879,CA
-1209274880,1209274911,CZ
+1209274880,1209274911,CN
1209274912,1209274927,US
1209274928,1209274943,TR
1209274944,1209274959,US
1209274960,1209274967,PH
1209274968,1209275071,US
1209275072,1209275135,GB
-1209275136,1209275679,US
+1209275136,1209275647,US
+1209275648,1209275679,SC
1209275680,1209275695,TR
1209275696,1209275791,US
1209275792,1209275799,TR
1209275800,1209275823,US
1209275824,1209275827,CN
-1209275828,1209275906,US
+1209275828,1209275863,US
+1209275864,1209275871,SC
+1209275872,1209275906,US
1209275907,1209275908,KH
1209275909,1209275913,US
1209275914,1209275914,KH
@@ -29136,7 +29262,9 @@
1209276808,1209276903,US
1209276904,1209276911,CN
1209276912,1209276927,TR
-1209276928,1209277103,US
+1209276928,1209277087,US
+1209277088,1209277095,SC
+1209277096,1209277103,US
1209277104,1209277119,TR
1209277120,1209277135,RO
1209277136,1209277143,US
@@ -29148,7 +29276,10 @@
1209277158,1209277158,IN
1209277159,1209277159,US
1209277160,1209277160,CN
-1209277161,1209277166,US
+1209277161,1209277161,SC
+1209277162,1209277163,US
+1209277164,1209277165,SC
+1209277166,1209277166,GB
1209277167,1209277167,CN
1209277168,1209277168,AU
1209277169,1209277171,US
@@ -29204,8 +29335,7 @@
1209279232,1209279295,BR
1209279296,1209279615,US
1209279616,1209279743,GB
-1209279744,1209279855,US
-1209279856,1209279871,TR
+1209279744,1209279871,US
1209279872,1209279935,MY
1209279936,1209279951,GB
1209279952,1209279967,US
@@ -29216,7 +29346,8 @@
1209280032,1209280047,IN
1209280048,1209280191,US
1209280192,1209280255,ID
-1209280256,1209280419,US
+1209280256,1209280319,SC
+1209280320,1209280419,US
1209280420,1209280423,CN
1209280424,1209280439,US
1209280440,1209280447,CN
@@ -29226,27 +29357,25 @@
1209280512,1209280515,US
1209280516,1209280519,TR
1209280520,1209280527,AU
-1209280528,1209280623,US
-1209280624,1209280639,TR
-1209280640,1209280895,US
+1209280528,1209280575,US
+1209280576,1209280607,SC
+1209280608,1209280895,US
1209280896,1209280959,BR
-1209280960,1209281007,US
-1209281008,1209281023,TR
-1209281024,1209281151,US
+1209280960,1209281151,US
1209281152,1209281231,CN
1209281232,1209281247,US
1209281248,1209281279,CA
1209281280,1209281535,KH
1209281536,1209281791,IN
-1209281792,1209281871,US
-1209281872,1209281887,TR
-1209281888,1209281927,US
+1209281792,1209281863,US
+1209281864,1209281871,SC
+1209281872,1209281927,US
1209281928,1209281935,IN
-1209281936,1209281983,US
-1209281984,1209282047,TR
-1209282048,1209282063,US
+1209281936,1209282063,US
1209282064,1209282067,SA
-1209282068,1209282159,US
+1209282068,1209282111,US
+1209282112,1209282143,SC
+1209282144,1209282159,US
1209282160,1209282175,CN
1209282176,1209282559,US
1209282560,1209282623,CN
@@ -29264,16 +29393,16 @@
1209283752,1209283759,BD
1209283760,1209283775,US
1209283776,1209283807,ZA
-1209283808,1209283839,CA
-1209283840,1209283871,US
-1209283872,1209283875,TR
-1209283876,1209283887,US
+1209283808,1209283839,MY
+1209283840,1209283887,US
1209283888,1209283903,BR
1209283904,1209283915,US
1209283916,1209283919,KR
-1209283920,1209284159,US
+1209283920,1209284095,US
+1209284096,1209284127,CA
+1209284128,1209284159,US
1209284160,1209284223,TR
-1209284224,1209284351,IE
+1209284224,1209284351,CN
1209284352,1209284391,US
1209284392,1209284399,RO
1209284400,1209284415,TR
@@ -29282,18 +29411,15 @@
1209284448,1209284607,US
1209284608,1209284671,TR
1209284672,1209284735,CN
-1209284736,1209284767,US
+1209284736,1209284759,US
+1209284760,1209284767,SC
1209284768,1209284799,MY
1209284800,1209284831,TR
-1209284832,1209284839,US
-1209284840,1209284843,TR
-1209284844,1209284855,US
+1209284832,1209284855,US
1209284856,1209284863,CN
1209284864,1209284993,US
1209284994,1209284994,TR
-1209284995,1209284995,US
-1209284996,1209284996,TR
-1209284997,1209284997,US
+1209284995,1209284997,US
1209284998,1209284998,CN
1209284999,1209284999,US
1209285000,1209285000,CA
@@ -29380,7 +29506,11 @@
1209877935,1209877938,PK
1209877939,1209879554,US
1209879555,1209879558,PE
-1209879559,1209884671,US
+1209879559,1209880125,US
+1209880126,1209880126,CA
+1209880127,1209882516,US
+1209882517,1209882517,CA
+1209882518,1209884671,US
1209884672,1209884679,IT
1209884680,1209884687,ES
1209884688,1209884823,US
@@ -29845,7 +29975,9 @@
1210101280,1210101311,US
1210101312,1210101319,IE
1210101320,1210101327,IL
-1210101328,1210101559,US
+1210101328,1210101519,US
+1210101520,1210101527,IL
+1210101528,1210101559,US
1210101560,1210101567,AU
1210101568,1210101727,US
1210101728,1210101743,GB
@@ -30122,9 +30254,7 @@
1211039088,1211039103,RU
1211039104,1211039503,US
1211039504,1211039519,A2
-1211039520,1211039551,US
-1211039552,1211039567,BM
-1211039568,1211039647,US
+1211039520,1211039647,US
1211039648,1211039663,AR
1211039664,1211039679,US
1211039680,1211039695,BR
@@ -30246,13 +30376,17 @@
1211394064,1211394079,ES
1211394080,1211394751,US
1211394752,1211395071,IT
-1211395072,1211407293,US
+1211395072,1211404421,US
+1211404422,1211404422,CA
+1211404423,1211407293,US
1211407294,1211407333,MX
1211407334,1211413247,US
1211413248,1211413503,CA
1211413504,1211419489,US
1211419490,1211419497,CA
-1211419498,1211432959,US
+1211419498,1211421739,US
+1211421740,1211421740,CA
+1211421741,1211432959,US
1211432960,1211473919,CA
1211473920,1211596799,US
1211596800,1211613183,CA
@@ -30470,13 +30604,25 @@
1247483096,1247483111,US
1247483112,1247483119,CN
1247483120,1247483647,US
-1247483648,1247484671,CN
+1247483648,1247483951,CN
+1247483952,1247483967,US
+1247483968,1247484031,CN
+1247484032,1247484047,US
+1247484048,1247484287,CN
+1247484288,1247484319,US
+1247484320,1247484543,CN
+1247484544,1247484551,US
+1247484552,1247484559,CN
+1247484560,1247484567,US
+1247484568,1247484671,CN
1247484672,1247484927,US
1247484928,1247485191,CN
1247485192,1247485231,US
1247485232,1247485263,CN
1247485264,1247485439,US
-1247485440,1247485543,CN
+1247485440,1247485471,CN
+1247485472,1247485479,US
+1247485480,1247485543,CN
1247485544,1247485615,US
1247485616,1247485623,CN
1247485624,1247485631,US
@@ -30503,7 +30649,9 @@
1248897264,1248897271,FR
1248897272,1248899071,US
1248899072,1248900095,CA
-1248900096,1248903695,US
+1248900096,1248902143,US
+1248902144,1248903167,CA
+1248903168,1248903695,US
1248903696,1248903711,ZA
1248903712,1248903775,US
1248903776,1248903791,FR
@@ -30596,9 +30744,7 @@
1249105120,1249105127,AR
1249105128,1249105135,US
1249105136,1249105143,CH
-1249105144,1249105183,US
-1249105184,1249105191,ZA
-1249105192,1249105279,US
+1249105144,1249105279,US
1249105280,1249105295,CA
1249105296,1249105367,US
1249105368,1249105375,ES
@@ -30656,7 +30802,9 @@
1249229217,1249229217,CA
1249229218,1249229289,US
1249229290,1249229291,CA
-1249229292,1249236991,US
+1249229292,1249229591,US
+1249229592,1249229599,ES
+1249229600,1249236991,US
1249236992,1249239039,KY
1249239040,1249245183,US
1249245184,1249247231,CA
@@ -30724,7 +30872,9 @@
1249440280,1249440287,FR
1249440288,1249452031,US
1249452032,1249453055,CA
-1249453056,1249474559,US
+1249453056,1249460671,US
+1249460672,1249460687,CA
+1249460688,1249474559,US
1249474560,1249475583,CA
1249475584,1249484799,US
1249484800,1249486847,CA
@@ -30749,7 +30899,9 @@
1249572864,1249577087,US
1249577088,1249577232,CA
1249577233,1249577343,US
-1249577344,1249577480,CA
+1249577344,1249577403,CA
+1249577404,1249577468,US
+1249577469,1249577480,CA
1249577481,1249577545,US
1249577546,1249577730,CA
1249577731,1249577794,US
@@ -30837,7 +30989,9 @@
1254704904,1254704911,PH
1254704912,1254713359,US
1254713360,1254713407,CA
-1254713408,1254924687,US
+1254713408,1254752191,US
+1254752192,1254752207,CH
+1254752208,1254924687,US
1254924688,1254924703,RO
1254924704,1254948927,US
1254948928,1254948935,SG
@@ -31125,9 +31279,7 @@
1254966928,1254966943,FR
1254966944,1254966975,US
1254966976,1254966991,IL
-1254966992,1254967007,US
-1254967008,1254967023,AE
-1254967024,1254967079,US
+1254966992,1254967079,US
1254967080,1254967087,PH
1254967088,1254967127,US
1254967128,1254967143,BM
@@ -31217,7 +31369,8 @@
1254970336,1254970343,CH
1254970344,1254970527,US
1254970528,1254970543,GB
-1254970544,1254970607,US
+1254970544,1254970591,US
+1254970592,1254970607,PH
1254970608,1254970623,GH
1254970624,1254970631,MX
1254970632,1254970903,US
@@ -31383,9 +31536,7 @@
1255057888,1255057919,NL
1255057920,1255058671,US
1255058672,1255058687,GB
-1255058688,1255059151,US
-1255059152,1255059167,GB
-1255059168,1255059327,US
+1255058688,1255059327,US
1255059328,1255059343,NL
1255059344,1255059359,US
1255059360,1255059391,CA
@@ -31411,7 +31562,9 @@
1255063552,1255071743,PR
1255071744,1255210495,US
1255210496,1255211007,DE
-1255211008,1255265279,US
+1255211008,1255264511,US
+1255264512,1255264767,SG
+1255264768,1255265279,US
1255265280,1255266303,SG
1255266304,1255274047,US
1255274048,1255274079,GB
@@ -31419,11 +31572,9 @@
1255274496,1255274751,SG
1255274752,1255276543,US
1255276544,1255342079,CA
-1255342080,1255369055,US
-1255369056,1255369087,DE
-1255369088,1255373759,US
-1255373760,1255373791,DE
-1255373792,1255489535,US
+1255342080,1255367167,US
+1255367168,1255367423,DE
+1255367424,1255489535,US
1255489536,1255505919,PR
1255505920,1255514111,US
1255514112,1255522303,CA
@@ -31443,9 +31594,7 @@
1255770368,1255770623,CA
1255770624,1255776431,US
1255776432,1255776439,LB
-1255776440,1255780351,US
-1255780352,1255782399,CA
-1255782400,1255784959,US
+1255776440,1255784959,US
1255784960,1255784967,BE
1255784968,1255788511,US
1255788512,1255788543,BE
@@ -31502,16 +31651,25 @@
1264737280,1264738175,US
1264738176,1264738207,IL
1264738208,1264762879,US
-1264762880,1264766975,CA
-1264766976,1264980735,US
+1264762880,1264763391,CA
+1264763392,1264763647,IE
+1264763648,1264764927,CA
+1264764928,1264764959,US
+1264764960,1264766975,CA
+1264766976,1264978623,US
+1264978624,1264978639,CA
+1264978640,1264980735,US
1264980736,1264980743,CA
-1264980744,1264982895,US
+1264980744,1264982847,US
+1264982848,1264982855,CA
+1264982856,1264982895,US
1264982896,1264982903,AF
1264982904,1264983031,US
1264983032,1264983039,AU
1264983040,1264984703,US
1264984704,1264984711,CA
-1264984712,1264984799,US
+1264984712,1264984791,US
+1264984792,1264984799,CA
1264984800,1264984807,AF
1264984808,1266107759,US
1266107760,1266107775,UM
@@ -31888,7 +32046,9 @@
1279828568,1279828575,CA
1279828576,1279828615,US
1279828616,1279828623,CA
-1279828624,1279848447,US
+1279828624,1279829711,US
+1279829712,1279829759,FR
+1279829760,1279848447,US
1279848448,1279852543,PR
1279852544,1279921919,US
1279921920,1279922047,IE
@@ -31919,13 +32079,15 @@
1279953760,1279953791,GB
1279953792,1279953951,CA
1279953952,1279953967,US
-1279953968,1279954095,CA
+1279953968,1279954015,CA
+1279954016,1279954047,US
+1279954048,1279954095,CA
1279954096,1279954119,US
1279954120,1279954303,CA
1279954304,1279954431,US
1279954432,1279954527,CA
-1279954528,1279954559,US
-1279954560,1279954623,CA
+1279954528,1279954543,US
+1279954544,1279954623,CA
1279954624,1279954655,FI
1279954656,1279954719,CA
1279954720,1279954727,US
@@ -31997,11 +32159,15 @@
1279960528,1279960535,US
1279960536,1279960559,CA
1279960560,1279960567,MX
-1279960568,1279962175,US
+1279960568,1279961087,US
+1279961088,1279961343,IN
+1279961344,1279962175,US
1279962176,1279962207,CA
1279962208,1279962223,US
1279962224,1279962239,CA
-1279962240,1279962895,US
+1279962240,1279962783,US
+1279962784,1279962791,CN
+1279962792,1279962895,US
1279962896,1279962911,CA
1279962912,1279962927,CN
1279962928,1279962943,US
@@ -32347,7 +32513,7 @@
1296250080,1296250111,IL
1296250112,1296250143,IE
1296250144,1296250175,GB
-1296250176,1296250207,BE
+1296250176,1296250207,FR
1296250208,1296250239,ES
1296250240,1296250271,BE
1296250272,1296250303,DE
@@ -32369,7 +32535,7 @@
1296251968,1296252015,NL
1296252016,1296252039,US
1296252040,1296252055,DE
-1296252056,1296252063,BE
+1296252056,1296252063,FR
1296252064,1296252079,IT
1296252080,1296252087,IE
1296252088,1296252095,FR
@@ -32386,7 +32552,8 @@
1296252256,1296252271,GB
1296252272,1296252303,FR
1296252304,1296252319,IL
-1296252320,1296252367,FR
+1296252320,1296252335,GB
+1296252336,1296252367,FR
1296252368,1296252383,DE
1296252384,1296252399,FR
1296252400,1296252415,IE
@@ -32394,8 +32561,7 @@
1296252672,1296252679,GB
1296252680,1296252687,FR
1296252688,1296252695,NL
-1296252696,1296252703,FR
-1296252704,1296252711,DE
+1296252696,1296252711,DE
1296252712,1296252719,FR
1296252720,1296252727,BE
1296252728,1296252735,IL
@@ -32408,8 +32574,8 @@
1296252840,1296252847,DE
1296252848,1296252855,GB
1296252856,1296252871,IE
-1296252872,1296252879,BE
-1296252880,1296252887,FR
+1296252872,1296252879,FR
+1296252880,1296252887,DE
1296252888,1296252895,IE
1296252896,1296252911,BE
1296252912,1296252919,GB
@@ -32429,7 +32595,7 @@
1296260608,1296262143,DE
1296262144,1296262399,FR
1296262400,1296262655,US
-1296262656,1296262911,CA
+1296262656,1296262911,FR
1296262912,1296263935,US
1296263936,1296263943,FR
1296263944,1296263999,US
@@ -32494,12 +32660,10 @@
1296466656,1296466671,BJ
1296466672,1296466687,NO
1296466688,1296466719,BJ
-1296466720,1296466751,NO
-1296466752,1296466759,ML
+1296466720,1296466759,NO
1296466760,1296466767,SL
1296466768,1296466775,BF
-1296466776,1296466783,GN
-1296466784,1296468479,NO
+1296466776,1296468479,NO
1296468480,1296469247,NG
1296469248,1296472383,NO
1296472384,1296472415,BI
@@ -32859,7 +33023,19 @@
1298126848,1298127615,SA
1298127616,1298128127,IR
1298128128,1298128895,SA
-1298128896,1298130943,NL
+1298128896,1298129465,NL
+1298129466,1298129466,IR
+1298129467,1298129738,NL
+1298129739,1298129739,IT
+1298129740,1298129744,NL
+1298129745,1298129745,US
+1298129746,1298129751,NL
+1298129752,1298129755,US
+1298129756,1298129788,NL
+1298129789,1298129792,IT
+1298129793,1298130180,NL
+1298130181,1298130426,TR
+1298130427,1298130943,NL
1298130944,1298132991,BG
1298132992,1298135039,FI
1298135040,1298137087,NL
@@ -32877,7 +33053,9 @@
1298841600,1298857983,RU
1298857984,1298874367,SE
1298874368,1298907135,GB
-1298907136,1298923519,IE
+1298907136,1298915199,IE
+1298915200,1298915215,CA
+1298915216,1298923519,IE
1298923520,1298939903,IT
1298939904,1298956287,RU
1298956288,1298972671,GB
@@ -32946,7 +33124,9 @@
1306238976,1306263551,SE
1306263552,1306271743,KE
1306271744,1306279935,RU
-1306279936,1306286079,IT
+1306279936,1306285775,IT
+1306285776,1306285783,US
+1306285784,1306286079,IT
1306286080,1306287103,CH
1306287104,1306287615,IT
1306287616,1306287903,CH
@@ -33222,9 +33402,9 @@
1307983360,1307983423,ZA
1307983424,1307983487,BW
1307983488,1307983551,ZM
-1307983552,1307983583,MZ
-1307983584,1307983615,ZA
-1307983616,1307983871,GB
+1307983552,1307983615,MZ
+1307983616,1307983743,ZA
+1307983744,1307983871,ZM
1307983872,1307987967,LB
1307987968,1307992063,FR
1307992064,1307996159,RU
@@ -33545,8 +33725,10 @@
1311263616,1311263679,FR
1311263680,1311263871,CH
1311263872,1311263999,FR
-1311264000,1311264111,CH
-1311264112,1311264767,FR
+1311264000,1311264119,CH
+1311264120,1311264127,FR
+1311264128,1311264191,CH
+1311264192,1311264767,FR
1311264768,1311266815,RU
1311266816,1311268863,FR
1311268864,1311270911,BE
@@ -33653,7 +33835,9 @@
1311676024,1311676031,IT
1311676032,1311707655,DE
1311707656,1311707663,NL
-1311707664,1311756823,DE
+1311707664,1311755407,DE
+1311755408,1311755415,IT
+1311755416,1311756823,DE
1311756824,1311756831,ES
1311756832,1311757439,DE
1311757440,1311757447,ES
@@ -33858,7 +34042,9 @@
1315926016,1315930111,CZ
1315930112,1315930623,DE
1315930624,1315930879,LB
-1315930880,1315934207,DE
+1315930880,1315931135,DE
+1315931136,1315931391,LB
+1315931392,1315934207,DE
1315934208,1315938303,RU
1315938304,1315942399,DK
1315942400,1315946495,UA
@@ -33874,9 +34060,7 @@
1317113104,1317113119,IE
1317113120,1317113855,GB
1317113856,1317114111,US
-1317114112,1317115135,GB
-1317115136,1317115391,IE
-1317115392,1317118207,GB
+1317114112,1317118207,GB
1317118208,1317118463,IN
1317118464,1317126399,GB
1317126400,1317126655,US
@@ -33951,7 +34135,7 @@
1317650136,1317650143,GB
1317650144,1317650431,IE
1317650432,1317666815,PT
-1317666816,1317666823,IQ
+1317666816,1317666823,A2
1317666824,1317666831,CD
1317666832,1317666839,A2
1317666840,1317666855,GH
@@ -33978,7 +34162,9 @@
1317667160,1317667167,AO
1317667168,1317667175,NG
1317667176,1317667191,A2
-1317667192,1317667231,NG
+1317667192,1317667207,NG
+1317667208,1317667215,A2
+1317667216,1317667231,NG
1317667232,1317667239,A2
1317667240,1317667247,NG
1317667248,1317667263,A2
@@ -34002,9 +34188,7 @@
1317667496,1317667503,NG
1317667504,1317667551,A2
1317667552,1317667567,NG
-1317667568,1317667711,A2
-1317667712,1317667719,NG
-1317667720,1317667735,A2
+1317667568,1317667735,A2
1317667736,1317667743,NG
1317667744,1317667751,A2
1317667752,1317667759,NG
@@ -34015,7 +34199,8 @@
1317667792,1317667799,NG
1317667800,1317667807,A2
1317667808,1317667815,NG
-1317667816,1317668095,A2
+1317667816,1317667824,UG
+1317667825,1317668095,A2
1317668096,1317668103,GH
1317668104,1317668143,A2
1317668144,1317668151,AO
@@ -34193,7 +34378,9 @@
1317671680,1317671687,LR
1317671688,1317671719,A2
1317671720,1317671727,NG
-1317671728,1317671783,A2
+1317671728,1317671759,A2
+1317671760,1317671767,AO
+1317671768,1317671783,A2
1317671784,1317671807,NG
1317671808,1317671823,CI
1317671824,1317671831,NG
@@ -34214,9 +34401,7 @@
1317672472,1317672479,A2
1317672480,1317672487,ZM
1317672488,1317672503,NG
-1317672504,1317672543,A2
-1317672544,1317672551,CD
-1317672552,1317672583,A2
+1317672504,1317672583,A2
1317672584,1317672591,CD
1317672592,1317672615,A2
1317672616,1317672623,NG
@@ -34240,8 +34425,7 @@
1317672920,1317672927,GH
1317672928,1317672935,A2
1317672936,1317672943,NG
-1317672944,1317672951,UG
-1317672952,1317672959,A2
+1317672944,1317672959,A2
1317672960,1317673231,NG
1317673232,1317673239,A2
1317673240,1317673247,NG
@@ -34326,7 +34510,7 @@
1317674544,1317674567,NG
1317674568,1317674607,A2
1317674608,1317674615,NG
-1317674616,1317674623,IQ
+1317674616,1317674623,A2
1317674624,1317674631,NG
1317674632,1317674639,A2
1317674640,1317674647,NG
@@ -34413,22 +34597,22 @@
1317675800,1317675807,GB
1317675808,1317675815,NG
1317675816,1317675823,A2
-1317675824,1317675847,NG
+1317675824,1317675839,NG
+1317675840,1317675847,A2
1317675848,1317675855,TD
1317675856,1317675863,NG
1317675864,1317675887,A2
1317675888,1317675895,CD
1317675896,1317675903,A2
1317675904,1317675911,UG
-1317675912,1317675919,A2
+1317675912,1317675919,NG
1317675920,1317675927,UG
1317675928,1317675935,LR
1317675936,1317675951,A2
1317675952,1317675959,NG
1317675960,1317675967,A2
1317675968,1317675975,NG
-1317675976,1317675983,A2
-1317675984,1317675991,ML
+1317675976,1317675991,A2
1317675992,1317675999,NG
1317676000,1317676007,A2
1317676008,1317676015,GH
@@ -34471,7 +34655,8 @@
1317676584,1317676591,NG
1317676592,1317676599,AO
1317676600,1317676607,UG
-1317676608,1317676639,A2
+1317676608,1317676631,A2
+1317676632,1317676639,NG
1317676640,1317676647,CD
1317676648,1317676655,A2
1317676656,1317676671,NG
@@ -34479,8 +34664,7 @@
1317676688,1317676695,LR
1317676696,1317676711,A2
1317676712,1317676719,NG
-1317676720,1317676751,A2
-1317676752,1317676759,ML
+1317676720,1317676759,A2
1317676760,1317676767,LR
1317676768,1317676775,A2
1317676776,1317676783,UG
@@ -34502,8 +34686,7 @@
1317676952,1317676983,A2
1317676984,1317676999,NG
1317677000,1317677007,IQ
-1317677008,1317677015,CD
-1317677016,1317677023,A2
+1317677008,1317677023,A2
1317677024,1317677039,NG
1317677040,1317677047,A2
1317677048,1317677055,NG
@@ -34548,7 +34731,8 @@
1317677496,1317677527,NG
1317677528,1317677535,GQ
1317677536,1317677551,CD
-1317677552,1317677567,NG
+1317677552,1317677559,A2
+1317677560,1317677567,NG
1317677568,1317677663,A2
1317677664,1317677671,GB
1317677672,1317677823,A2
@@ -34582,7 +34766,9 @@
1317678224,1317678231,NG
1317678232,1317678239,BF
1317678240,1317678247,CD
-1317678248,1317678271,A2
+1317678248,1317678255,A2
+1317678256,1317678263,CD
+1317678264,1317678271,A2
1317678272,1317678287,NG
1317678288,1317678295,GR
1317678296,1317678311,A2
@@ -34632,17 +34818,22 @@
1317679752,1317679767,NG
1317679768,1317679775,A2
1317679776,1317679799,NG
-1317679800,1317679815,A2
+1317679800,1317679807,A2
+1317679808,1317679815,AO
1317679816,1317679831,NG
1317679832,1317679839,A2
1317679840,1317679847,NG
1317679848,1317679863,A2
1317679864,1317679871,NG
-1317679872,1317681175,A2
+1317679872,1317681159,A2
+1317681160,1317681167,NG
+1317681168,1317681175,A2
1317681176,1317681191,NG
1317681192,1317681279,A2
1317681280,1317681287,NG
-1317681288,1317683199,A2
+1317681288,1317681927,A2
+1317681928,1317681931,NG
+1317681932,1317683199,A2
1317683200,1317683839,DE
1317683840,1317683855,CH
1317683856,1317683863,DE
@@ -34665,7 +34856,7 @@
1317831840,1317831871,CA
1317831872,1317832191,NL
1317832192,1317832447,GB
-1317832448,1317832511,SC
+1317832448,1317832511,CY
1317832512,1317832575,NL
1317832576,1317832703,GI
1317832704,1317832959,NL
@@ -34681,7 +34872,7 @@
1317835712,1317835775,GI
1317835776,1317836031,CY
1317836032,1317836863,NL
-1317836864,1317836927,SC
+1317836864,1317836927,CY
1317836928,1317836991,NL
1317836992,1317837007,GB
1317837008,1317837023,RU
@@ -34699,16 +34890,16 @@
1317841408,1317841439,SC
1317841440,1317841471,MT
1317841472,1317841535,CY
-1317841536,1317841599,NL
+1317841536,1317841567,HK
+1317841568,1317841599,NL
1317841600,1317841663,GI
1317841664,1317841727,HK
-1317841728,1317841791,SC
-1317841792,1317841855,CY
+1317841728,1317841855,CY
1317841856,1317841887,IL
1317841888,1317842943,NL
1317842944,1317843071,CY
1317843072,1317843135,HK
-1317843136,1317843199,SC
+1317843136,1317843199,CY
1317843200,1317843391,US
1317843392,1317843423,NL
1317843424,1317843455,PR
@@ -34731,12 +34922,12 @@
1317977408,1317977415,MT
1317977416,1317978111,AT
1317978112,1317994495,RU
-1317994496,1317995519,NL
-1317995520,1317996095,DE
+1317994496,1317995007,NL
+1317995008,1317996095,DE
1317996096,1317996287,NL
1317996288,1317998207,DE
-1317998208,1317998591,NL
-1317998592,1318000383,DE
+1317998208,1317998335,NL
+1317998336,1318000383,DE
1318000384,1318000447,NL
1318000448,1318002175,DE
1318002176,1318002431,NL
@@ -34822,8 +35013,8 @@
1318871040,1318879231,DK
1318879232,1318887423,CZ
1318887424,1318895615,PL
-1318895616,1318899711,SE
-1318899712,1318903807,DK
+1318895616,1318897663,SE
+1318897664,1318903807,DK
1318903808,1318911999,RU
1318912000,1318920191,MK
1318920192,1318928383,IR
@@ -35014,6 +35205,7 @@
1332477952,1332609023,ES
1332609024,1332613119,PL
1332613120,1332617215,UA
+1332617216,1332621311,CZ
1332621312,1332625407,UA
1332625408,1332629503,RU
1332629504,1332633599,DE
@@ -35146,7 +35338,9 @@
1334651904,1334652159,DE
1334652160,1334652543,GB
1334652544,1334652559,NL
-1334652560,1334652927,GB
+1334652560,1334652863,GB
+1334652864,1334652895,FR
+1334652896,1334652927,GB
1334652928,1334661119,RU
1334661120,1334665215,CH
1334665216,1334669311,NO
@@ -35182,7 +35376,13 @@
1334729984,1334730027,KZ
1334730028,1334730031,RU
1334730032,1334730043,KZ
-1334730044,1334730239,RU
+1334730044,1334730047,RU
+1334730048,1334730055,KZ
+1334730056,1334730063,RU
+1334730064,1334730107,KZ
+1334730108,1334730111,RU
+1334730112,1334730127,KZ
+1334730128,1334730239,RU
1334730240,1334730431,KZ
1334730432,1334730439,RU
1334730440,1334730443,KZ
@@ -35476,17 +35676,23 @@
1346538016,1346538031,CH
1346538032,1346538143,BE
1346538144,1346538175,HR
-1346538176,1346539519,BE
+1346538176,1346538239,BE
+1346538240,1346538303,AT
+1346538304,1346539519,BE
1346539520,1346543615,RU
1346543616,1346547711,FI
1346547712,1346551807,IR
1346551808,1346555903,DE
1346555904,1346559999,IT
-1346560000,1346563071,LI
+1346560000,1346561535,LI
+1346561536,1346561599,CH
+1346561600,1346563071,LI
1346563072,1346563327,CH
1346563328,1346564095,LI
1346564096,1346568191,EE
-1346568192,1346571775,SE
+1346568192,1346571199,SE
+1346571200,1346571207,SK
+1346571208,1346571775,SE
1346571776,1346572287,A1
1346572288,1346576383,DE
1346576384,1346580479,DK
@@ -35631,21 +35837,7 @@
1347010560,1347014655,RU
1347014656,1347018751,GG
1347018752,1347022847,IT
-1347022848,1347024911,AT
-1347024912,1347024927,GB
-1347024928,1347024959,AT
-1347024960,1347025071,GB
-1347025072,1347025079,FR
-1347025080,1347025087,GB
-1347025088,1347025103,AT
-1347025104,1347025111,FR
-1347025112,1347025119,GB
-1347025120,1347025151,AT
-1347025152,1347025215,US
-1347025216,1347025279,GB
-1347025280,1347025343,ES
-1347025344,1347025407,DE
-1347025408,1347026943,AT
+1347022848,1347026943,AT
1347026944,1347035135,GB
1347035136,1347039231,CZ
1347039232,1347043327,RO
@@ -35849,9 +36041,7 @@
1347309840,1347309855,CH
1347309856,1347313663,DE
1347313664,1347321855,RU
-1347321856,1347323775,KW
-1347323776,1347323903,IR
-1347323904,1347325951,KW
+1347321856,1347325951,KW
1347325952,1347327231,CZ
1347327232,1347327487,SK
1347327488,1347327743,CZ
@@ -35994,17 +36184,7 @@
1347694592,1347706879,GB
1347706880,1347710975,IT
1347710976,1347715071,RU
-1347715072,1347715519,ES
-1347715520,1347715527,SA
-1347715528,1347716151,ES
-1347716152,1347716159,LB
-1347716160,1347716207,ES
-1347716208,1347716223,CY
-1347716224,1347719711,ES
-1347719712,1347719719,SO
-1347719720,1347722495,ES
-1347722496,1347722751,LB
-1347722752,1347723263,ES
+1347715072,1347723263,ES
1347723264,1347727359,GB
1347727360,1347731455,UA
1347731456,1347739647,DE
@@ -36062,11 +36242,14 @@
1347837952,1347846143,RO
1347846144,1347850239,NO
1347850240,1347854335,IT
-1347854336,1347854871,DE
+1347854336,1347854847,EU
+1347854848,1347854871,DE
1347854872,1347854879,EU
1347854880,1347854887,DE
1347854888,1347854911,EU
-1347854912,1347855071,DE
+1347854912,1347855023,DE
+1347855024,1347855039,EU
+1347855040,1347855071,DE
1347855072,1347855087,EU
1347855088,1347855103,DE
1347855104,1347855359,CH
@@ -36080,13 +36263,17 @@
1347856064,1347856079,EU
1347856080,1347856087,DE
1347856088,1347856095,EU
-1347856096,1347856239,DE
+1347856096,1347856127,DE
+1347856128,1347856191,EU
+1347856192,1347856239,DE
1347856240,1347856255,EU
1347856256,1347856383,DE
1347856384,1347856399,EU
-1347856400,1347856431,DE
-1347856432,1347856447,EU
-1347856448,1347856639,DE
+1347856400,1347856423,DE
+1347856424,1347856447,EU
+1347856448,1347856591,DE
+1347856592,1347856607,EU
+1347856608,1347856639,DE
1347856640,1347856895,AT
1347856896,1347858495,DE
1347858496,1347858503,EU
@@ -36101,8 +36288,8 @@
1347859344,1347859351,DE
1347859352,1347859359,EU
1347859360,1347859383,DE
-1347859384,1347859407,EU
-1347859408,1347859423,DE
+1347859384,1347859391,EU
+1347859392,1347859423,DE
1347859424,1347859455,EU
1347859456,1347860863,DE
1347860864,1347860879,EU
@@ -36460,7 +36647,9 @@
1352058432,1352058495,US
1352058496,1352139671,DE
1352139672,1352139679,IT
-1352139680,1352144519,DE
+1352139680,1352141311,DE
+1352141312,1352141567,NL
+1352141568,1352144519,DE
1352144520,1352144527,IT
1352144528,1352144535,US
1352144536,1352147007,DE
@@ -36495,7 +36684,9 @@
1352149856,1352149871,SE
1352149872,1352277535,DE
1352277536,1352277567,IT
-1352277568,1352402791,DE
+1352277568,1352304639,DE
+1352304640,1352304895,CH
+1352304896,1352402791,DE
1352402792,1352402799,BE
1352402800,1352404599,DE
1352404600,1352404607,NL
@@ -36546,24 +36737,29 @@
1353265952,1353266959,GB
1353266960,1353266975,IE
1353266976,1353267455,GB
-1353267456,1353268223,IE
+1353267456,1353267711,IE
+1353267712,1353267719,GB
+1353267720,1353268223,IE
1353268224,1353268479,GB
1353268480,1353268599,BE
1353268600,1353268607,GB
-1353268608,1353269215,BE
-1353269216,1353270527,GB
+1353268608,1353269007,BE
+1353269008,1353269015,GB
+1353269016,1353269223,BE
+1353269224,1353269231,FR
+1353269232,1353269247,BE
+1353269248,1353270527,GB
1353270528,1353270783,IE
1353270784,1353271295,GB
1353271296,1353271423,IE
1353271424,1353271815,GB
1353271816,1353271831,ES
1353271832,1353271839,GB
-1353271840,1353272031,ES
-1353272032,1353272039,FR
+1353271840,1353272039,ES
1353272040,1353272047,GB
1353272048,1353272055,ES
-1353272056,1353272063,GB
-1353272064,1353272199,ES
+1353272056,1353272071,GB
+1353272072,1353272199,ES
1353272200,1353272207,GB
1353272208,1353272245,ES
1353272246,1353272247,GB
@@ -36580,37 +36776,33 @@
1353274368,1353274759,ES
1353274760,1353274767,GB
1353274768,1353274791,ES
-1353274792,1353274799,GB
-1353274800,1353274895,ES
+1353274792,1353274807,GB
+1353274808,1353274895,ES
1353274896,1353274911,GB
1353274912,1353275007,ES
1353275008,1353275015,GB
1353275016,1353275391,ES
1353275392,1353277439,GB
1353277440,1353279487,CH
-1353279488,1353279575,IT
-1353279576,1353279591,GB
-1353279592,1353279615,IT
+1353279488,1353279615,IT
1353279616,1353279623,GB
1353279624,1353279743,IT
1353279744,1353279751,GB
1353279752,1353279759,IT
1353279760,1353279763,GB
-1353279764,1353280039,IT
-1353280040,1353280047,GB
-1353280048,1353280119,IT
+1353279764,1353280119,IT
1353280120,1353280127,GB
1353280128,1353280143,IT
1353280144,1353280151,GB
-1353280152,1353280159,IT
-1353280160,1353280167,GB
-1353280168,1353280191,IT
+1353280152,1353280191,IT
1353280192,1353280199,GB
1353280200,1353280287,IT
1353280288,1353280295,GB
1353280296,1353280463,IT
1353280464,1353280479,GB
-1353280480,1353281023,IT
+1353280480,1353280567,IT
+1353280568,1353280575,GB
+1353280576,1353281023,IT
1353281024,1353281535,BE
1353281536,1353282047,GB
1353282048,1353282103,IT
@@ -36622,9 +36814,7 @@
1353282224,1353282559,IT
1353282560,1353283071,GB
1353283072,1353283327,IT
-1353283328,1353287327,GB
-1353287328,1353287359,IE
-1353287360,1353287679,GB
+1353283328,1353287679,GB
1353287680,1353288031,IE
1353288032,1353288063,GB
1353288064,1353288151,IE
@@ -36659,9 +36849,7 @@
1353289084,1353289087,GB
1353289088,1353289247,IE
1353289248,1353289255,GB
-1353289256,1353289279,IE
-1353289280,1353289295,GB
-1353289296,1353289359,IE
+1353289256,1353289359,IE
1353289360,1353289367,GB
1353289368,1353289391,IE
1353289392,1353289407,GB
@@ -36691,8 +36879,8 @@
1353298832,1353298839,SE
1353298840,1353298847,IE
1353298848,1353298863,SE
-1353298864,1353298879,GB
-1353298880,1353298881,SE
+1353298864,1353298871,GB
+1353298872,1353298881,SE
1353298882,1353298887,GB
1353298888,1353299503,SE
1353299504,1353299511,GB
@@ -36704,11 +36892,12 @@
1353299920,1353299927,GB
1353299928,1353299951,SE
1353299952,1353299967,GB
-1353299968,1353300079,SE
-1353300080,1353300095,PT
-1353300096,1353300103,GB
+1353299968,1353300095,SE
+1353300096,1353300103,CH
1353300104,1353300111,SE
-1353300112,1353300175,GB
+1353300112,1353300119,FI
+1353300120,1353300127,SE
+1353300128,1353300175,GB
1353300176,1353300191,SE
1353300192,1353300239,GB
1353300240,1353300247,SE
@@ -36716,7 +36905,9 @@
1353300280,1353300735,SE
1353300736,1353301095,GB
1353301096,1353301103,US
-1353301104,1353306111,GB
+1353301104,1353304335,GB
+1353304336,1353304351,DE
+1353304352,1353306111,GB
1353306112,1353306623,ES
1353306624,1353306687,GB
1353306688,1353306735,BE
@@ -36733,12 +36924,14 @@
1353310488,1353310599,ES
1353310600,1353310607,DE
1353310608,1353310719,ES
-1353310720,1353311135,IT
+1353310720,1353311071,IT
+1353311072,1353311079,GB
+1353311080,1353311135,IT
1353311136,1353311143,GB
1353311144,1353311175,IT
1353311176,1353311183,ES
-1353311184,1353311214,IT
-1353311215,1353312255,GB
+1353311184,1353311231,IT
+1353311232,1353312255,GB
1353312256,1353312767,CH
1353312768,1353312815,IT
1353312816,1353312823,GB
@@ -36932,7 +37125,8 @@
1357250560,1357316095,IL
1357316096,1357316607,ES
1357316608,1357317119,LU
-1357317120,1357317631,EU
+1357317120,1357317375,GB
+1357317376,1357317631,EU
1357317632,1357318143,LY
1357318144,1357320191,QA
1357320192,1357320703,FR
@@ -36945,10 +37139,9 @@
1357321024,1357321087,KE
1357321088,1357321215,HK
1357321216,1357321471,GB
-1357321472,1357321503,ES
-1357321504,1357321727,EU
+1357321472,1357321727,ES
1357321728,1357321983,CY
-1357321984,1357322239,EU
+1357321984,1357322239,GB
1357322240,1357322751,DE
1357322752,1357323263,BH
1357323264,1357323519,ES
@@ -37106,7 +37299,9 @@
1357875216,1357875247,DE
1357875248,1357875263,US
1357875264,1357875279,AT
-1357875280,1357875423,DE
+1357875280,1357875295,DE
+1357875296,1357875327,EU
+1357875328,1357875423,DE
1357875424,1357875439,GB
1357875440,1357875711,DE
1357875712,1357875967,PL
@@ -37156,8 +37351,8 @@
1357881088,1357881343,DE
1357881344,1357883391,FR
1357883392,1357883407,ES
-1357883408,1357883423,EU
-1357883424,1357883519,FR
+1357883408,1357883455,EU
+1357883456,1357883519,FR
1357883520,1357883535,EU
1357883536,1357883543,FR
1357883544,1357883583,EU
@@ -37228,7 +37423,7 @@
1357892200,1357892207,NL
1357892208,1357892215,SE
1357892216,1357892223,US
-1357892224,1357892351,EU
+1357892224,1357892351,FR
1357892352,1357893119,NL
1357893120,1357893375,SE
1357893376,1357893407,EU
@@ -37236,9 +37431,18 @@
1357893440,1357893471,IT
1357893472,1357893503,PL
1357893504,1357893631,DE
-1357893632,1357897343,EU
+1357893632,1357894911,EU
+1357894912,1357895423,FR
+1357895424,1357897215,EU
+1357897216,1357897279,SE
+1357897280,1357897343,EU
1357897344,1357897375,HU
-1357897376,1357897855,EU
+1357897376,1357897471,EU
+1357897472,1357897487,DE
+1357897488,1357897535,EU
+1357897536,1357897543,CZ
+1357897544,1357897551,SE
+1357897552,1357897855,EU
1357897856,1357898495,DE
1357898496,1357898751,EU
1357898752,1357899015,DE
@@ -37256,7 +37460,8 @@
1357899280,1357899287,RU
1357899288,1357899527,EU
1357899528,1357899535,BR
-1357899536,1357899551,EU
+1357899536,1357899543,CZ
+1357899544,1357899551,EU
1357899552,1357899567,AT
1357899568,1357899647,EU
1357899648,1357899775,GB
@@ -37433,8 +37638,8 @@
1358225128,1358225135,DE
1358225136,1358225183,IT
1358225184,1358225191,DE
-1358225192,1358225199,IT
-1358225200,1358225407,DE
+1358225192,1358225207,IT
+1358225208,1358225407,DE
1358225408,1358229503,RU
1358229504,1358230111,DE
1358230112,1358230115,AT
@@ -37680,7 +37885,9 @@
1358669464,1358669471,GB
1358669472,1358669543,PT
1358669544,1358669551,GB
-1358669552,1358669975,PT
+1358669552,1358669823,PT
+1358669824,1358669855,GB
+1358669856,1358669975,PT
1358669976,1358669983,GB
1358669984,1358670015,PT
1358670016,1358670023,GB
@@ -37690,8 +37897,8 @@
1358670944,1358670951,FR
1358670952,1358671047,PT
1358671048,1358671055,ES
-1358671056,1358671071,PT
-1358671072,1358671103,GB
+1358671056,1358671095,PT
+1358671096,1358671103,GB
1358671104,1358671415,PT
1358671416,1358671423,GB
1358671424,1358671431,PT
@@ -37784,9 +37991,7 @@
1358740884,1358740887,NL
1358740888,1358740927,SE
1358740928,1358740943,DK
-1358740944,1358741055,SE
-1358741056,1358741071,GB
-1358741072,1358741503,SE
+1358740944,1358741503,SE
1358741504,1358745599,IT
1358745600,1358749695,SE
1358749696,1358753791,IT
@@ -37829,7 +38034,8 @@
1358862336,1358862847,US
1358862848,1358863103,DK
1358863104,1358863359,CH
-1358863360,1358864383,US
+1358863360,1358863871,US
+1358863872,1358864383,GB
1358864384,1358864399,CH
1358864400,1358864407,IN
1358864408,1358864535,CH
@@ -37841,7 +38047,12 @@
1358884864,1358888959,SE
1358888960,1358889599,DE
1358889600,1358889631,IN
-1358889632,1358893055,DE
+1358889632,1358890943,DE
+1358890944,1358890975,GB
+1358890976,1358891007,IT
+1358891008,1358891647,DE
+1358891648,1358891679,IT
+1358891680,1358893055,DE
1358893056,1358897151,RU
1358897152,1358898175,A2
1358898176,1358898239,CA
@@ -38055,8 +38266,8 @@
1359467488,1359467495,DE
1359467496,1359467647,US
1359467648,1359467775,DE
-1359467776,1359467839,US
-1359467840,1359467903,DE
+1359467776,1359467855,US
+1359467856,1359467903,DE
1359467904,1359468063,US
1359468064,1359468575,DE
1359468576,1359468583,SG
@@ -38304,14 +38515,15 @@
1360621568,1360625663,ES
1360625664,1360626687,DE
1360626688,1360627199,LB
-1360627200,1360627455,DE
+1360627200,1360627455,A2
1360627456,1360627520,IQ
1360627521,1360627711,DE
1360627712,1360627743,LB
1360627744,1360627967,DE
1360627968,1360628095,IQ
1360628096,1360628223,LU
-1360628224,1360628735,LB
+1360628224,1360628479,A2
+1360628480,1360628735,LB
1360628736,1360628991,IQ
1360628992,1360629055,TR
1360629056,1360629247,DE
@@ -39091,17 +39303,15 @@
1365103744,1365103775,ES
1365103776,1365103791,GB
1365103792,1365103871,ES
-1365103872,1365104135,GB
-1365104136,1365104199,ES
+1365103872,1365104127,GB
+1365104128,1365104199,ES
1365104200,1365104207,GB
1365104208,1365106687,ES
1365106688,1365110783,GB
1365110784,1365114879,FR
1365114880,1365118975,BA
1365118976,1365127167,RU
-1365127168,1365127427,AT
-1365127428,1365127431,TR
-1365127432,1365130271,AT
+1365127168,1365130271,AT
1365130272,1365130303,IT
1365130304,1365130495,AT
1365130496,1365131007,IT
@@ -39359,6 +39569,7 @@
1369677824,1369686015,RU
1369686016,1369690111,PL
1369690112,1369694207,UA
+1369694208,1369702399,RU
1369702400,1369833471,BE
1369833472,1369964543,NO
1369964544,1369997311,GB
@@ -39553,8 +39764,8 @@
1372589824,1372618751,IT
1372618752,1372651519,GB
1372651520,1372684287,FI
-1372684288,1372685599,DE
-1372685600,1372685655,EU
+1372684288,1372685631,DE
+1372685632,1372685655,EU
1372685656,1372685663,DE
1372685664,1372685695,EU
1372685696,1372685823,DE
@@ -39593,8 +39804,8 @@
1372694784,1372694815,DE
1372694816,1372694831,EU
1372694832,1372695039,DE
-1372695040,1372695167,EU
-1372695168,1372695423,DE
+1372695040,1372695295,EU
+1372695296,1372695423,DE
1372695424,1372695551,EU
1372695552,1372695807,CZ
1372695808,1372696007,DK
@@ -39607,7 +39818,9 @@
1372697280,1372697343,EU
1372697344,1372698471,DE
1372698472,1372698559,EU
-1372698560,1372700159,DE
+1372698560,1372699135,DE
+1372699136,1372699391,EU
+1372699392,1372700159,DE
1372700160,1372700415,SE
1372700416,1372700671,EU
1372700672,1372702463,DE
@@ -39621,14 +39834,8 @@
1372703328,1372703391,DE
1372703392,1372703423,EU
1372703424,1372703487,DE
-1372703488,1372703743,EU
-1372703744,1372713327,DE
-1372713328,1372713343,EU
-1372713344,1372713375,DE
-1372713376,1372713471,EU
-1372713472,1372714239,DE
-1372714240,1372714495,EU
-1372714496,1372717055,DE
+1372703488,1372704767,EU
+1372704768,1372717055,DE
1372717056,1372749823,PL
1372749824,1372782591,DE
1372782592,1372815359,RU
@@ -39837,7 +40044,15 @@
1383098112,1383098367,DE
1383098368,1383098879,GB
1383098880,1383099159,DE
-1383099160,1383099391,GB
+1383099160,1383099163,BE
+1383099164,1383099167,NL
+1383099168,1383099171,IT
+1383099172,1383099175,RU
+1383099176,1383099179,GB
+1383099180,1383099183,DE
+1383099184,1383099199,GB
+1383099200,1383099263,DE
+1383099264,1383099391,GB
1383099392,1383099679,DE
1383099680,1383099687,GB
1383099688,1383099695,DE
@@ -40260,8 +40475,7 @@
1385568768,1385569279,EU
1385569280,1385569407,FR
1385569408,1385569487,CZ
-1385569488,1385569503,FR
-1385569504,1385569791,EU
+1385569488,1385569791,EU
1385569792,1385570303,FR
1385570304,1385578495,HU
1385578496,1385586687,TR
@@ -40347,15 +40561,11 @@
1388388944,1388388951,NG
1388388952,1388388959,IT
1388388960,1388388967,NG
-1388388968,1388389119,IT
-1388389120,1388389135,NG
-1388389136,1388389151,IT
+1388388968,1388389151,IT
1388389152,1388389167,NG
1388389168,1388389567,IT
1388389568,1388389631,NG
-1388389632,1388389927,IT
-1388389928,1388389935,NG
-1388389936,1388389943,IT
+1388389632,1388389943,IT
1388389944,1388390015,NG
1388390016,1388390143,IT
1388390144,1388394495,NG
@@ -40453,9 +40663,7 @@
1388679168,1388679423,FR
1388679424,1388679455,DE
1388679456,1388679679,EU
-1388679680,1388680703,DE
-1388680704,1388680959,EU
-1388680960,1388682239,DE
+1388679680,1388682239,DE
1388682240,1388682751,EU
1388682752,1388683263,DE
1388683264,1388689639,CH
@@ -40463,13 +40671,12 @@
1388689648,1388691455,CH
1388691456,1388699647,NL
1388699648,1388707839,SE
-1388707840,1388708607,RU
+1388707840,1388708095,RU
+1388708096,1388708607,LB
1388708608,1388709119,LT
1388709120,1388709375,IQ
1388709376,1388709887,RU
-1388709888,1388710143,LB
-1388710144,1388710399,RU
-1388710400,1388710911,LB
+1388709888,1388710911,LB
1388710912,1388711167,IQ
1388711168,1388711679,RU
1388711680,1388711935,IQ
@@ -40487,30 +40694,16 @@
1388716032,1388724223,ES
1388724224,1388728600,DE
1388728601,1388728608,CZ
-1388728609,1388728640,DE
-1388728641,1388728673,AT
-1388728674,1388728734,DE
-1388728735,1388728762,AT
-1388728763,1388728783,DE
-1388728784,1388728799,AT
-1388728800,1388728815,DE
-1388728816,1388728820,AT
-1388728821,1388729208,DE
-1388729209,1388729240,AT
-1388729241,1388729280,DE
-1388729281,1388729296,AT
-1388729297,1388729304,DE
-1388729305,1388729320,AT
-1388729321,1388729856,DE
-1388729857,1388729888,AT
-1388729889,1388731136,DE
-1388731137,1388731391,AT
-1388731392,1388732415,DE
+1388728609,1388732415,DE
1388732416,1388740607,ES
1388740608,1388740623,GB
-1388740624,1388740719,IE
+1388740624,1388740703,IE
+1388740704,1388740707,GB
+1388740708,1388740719,IE
1388740720,1388740735,GB
-1388740736,1388741375,IE
+1388740736,1388740847,IE
+1388740848,1388740863,GB
+1388740864,1388741375,IE
1388741376,1388741443,GB
1388741444,1388741535,IE
1388741536,1388741551,GB
@@ -40524,9 +40717,9 @@
1388741746,1388741747,GB
1388741748,1388741751,IE
1388741752,1388741759,GB
-1388741760,1388741775,IE
-1388741776,1388741787,GB
-1388741788,1388741799,IE
+1388741760,1388741787,IE
+1388741788,1388741791,GB
+1388741792,1388741799,IE
1388741800,1388741800,GB
1388741801,1388741807,IE
1388741808,1388741815,GB
@@ -40538,7 +40731,9 @@
1388742020,1388742023,GB
1388742024,1388742024,IE
1388742025,1388742031,GB
-1388742032,1388742655,IE
+1388742032,1388742067,IE
+1388742068,1388742079,GB
+1388742080,1388742655,IE
1388742656,1388742719,GB
1388742720,1388742731,IE
1388742732,1388742735,IR
@@ -40559,10 +40754,12 @@
1388743452,1388743555,IE
1388743556,1388743559,GB
1388743560,1388743571,IE
-1388743572,1388743583,GB
-1388743584,1388743919,IE
+1388743572,1388743582,GB
+1388743583,1388743919,IE
1388743920,1388743935,GB
-1388743936,1388744087,IE
+1388743936,1388744047,IE
+1388744048,1388744055,GB
+1388744056,1388744087,IE
1388744088,1388744095,GB
1388744096,1388744117,IE
1388744118,1388744127,GB
@@ -40576,51 +40773,47 @@
1388745500,1388745503,GB
1388745504,1388745559,IE
1388745560,1388745563,GB
-1388745564,1388745651,IE
-1388745652,1388745663,GB
-1388745664,1388745683,IE
-1388745684,1388745727,GB
+1388745564,1388745671,IE
+1388745672,1388745687,GB
+1388745688,1388745726,IE
+1388745727,1388745727,GB
1388745728,1388745911,IE
-1388745912,1388745919,GB
-1388745920,1388745927,IE
+1388745912,1388745915,GB
+1388745916,1388745927,IE
1388745928,1388745931,GB
1388745932,1388746155,IE
1388746156,1388746159,GB
-1388746160,1388746175,IE
-1388746176,1388746239,GB
-1388746240,1388746659,IE
+1388746160,1388746187,IE
+1388746188,1388746191,GB
+1388746192,1388746659,IE
1388746660,1388746671,GB
1388746672,1388746675,IE
1388746676,1388746695,GB
1388746696,1388746703,IE
-1388746704,1388746719,GB
-1388746720,1388746895,IE
-1388746896,1388746903,GB
-1388746904,1388746959,IE
-1388746960,1388746975,GB
-1388746976,1388747083,IE
-1388747084,1388747087,GB
-1388747088,1388747543,IE
-1388747544,1388747555,GB
-1388747556,1388747575,IE
-1388747576,1388747647,GB
-1388747648,1388747671,IE
-1388747672,1388747675,GB
-1388747676,1388747783,IE
+1388746704,1388746711,GB
+1388746712,1388746851,IE
+1388746852,1388746863,GB
+1388746864,1388746967,IE
+1388746968,1388746975,GB
+1388746976,1388747543,IE
+1388747544,1388747547,GB
+1388747548,1388747575,IE
+1388747576,1388747599,GB
+1388747600,1388747627,IE
+1388747628,1388747647,GB
+1388747648,1388747783,IE
1388747784,1388747791,GB
-1388747792,1388747835,IE
-1388747836,1388747839,GB
-1388747840,1388747859,IE
+1388747792,1388747859,IE
1388747860,1388747875,GB
1388747876,1388747983,IE
1388747984,1388747987,GB
-1388747988,1388747999,IE
-1388748000,1388748031,GB
+1388747988,1388748030,IE
+1388748031,1388748031,GB
1388748032,1388748223,IE
1388748224,1388748255,GB
1388748256,1388748287,IE
-1388748288,1388748295,GB
-1388748296,1388748349,IE
+1388748288,1388748319,GB
+1388748320,1388748349,IE
1388748350,1388748351,GB
1388748352,1388748799,IE
1388748800,1388756991,RU
@@ -40643,8 +40836,8 @@
1388806144,1388807679,DE
1388807680,1388807711,BZ
1388807712,1388808255,DE
-1388808256,1388808283,BZ
-1388808284,1388814335,DE
+1388808256,1388808287,BZ
+1388808288,1388814335,DE
1388814336,1388815103,AX
1388815104,1388815231,FI
1388815232,1388818687,AX
@@ -40933,7 +41126,8 @@
1389293056,1389293311,US
1389293312,1389293567,KE
1389293568,1389294335,A2
-1389294336,1389294719,US
+1389294336,1389294591,US
+1389294592,1389294719,A2
1389294720,1389294847,IQ
1389294848,1389295615,US
1389295616,1389295871,ZA
@@ -40980,9 +41174,7 @@
1389555264,1389555327,AT
1389555328,1389556751,DE
1389556752,1389556759,CH
-1389556760,1389559039,DE
-1389559040,1389559103,CH
-1389559104,1389559743,DE
+1389556760,1389559743,DE
1389559744,1389559807,CH
1389559808,1389561343,DE
1389561344,1389561407,IT
@@ -41138,17 +41330,17 @@
1400111104,1400373247,NL
1400373248,1400705279,DE
1400705280,1400705791,EU
-1400705792,1400708607,DE
-1400708608,1400709120,EU
+1400705792,1400707071,DE
+1400707072,1400708095,EU
+1400708096,1400708863,DE
+1400708864,1400709120,EU
1400709121,1400710142,DE
1400710143,1400710399,EU
1400710400,1400712191,DE
1400712192,1400712447,EU
1400712448,1400712703,DE
1400712704,1400712959,EU
-1400712960,1400716287,DE
-1400716288,1400717311,EU
-1400717312,1400718335,DE
+1400712960,1400718335,DE
1400718336,1400718847,EU
1400718848,1400721407,DE
1400721408,1400721919,EU
@@ -41555,6 +41747,7 @@
1401927680,1401929727,NL
1401929728,1401931775,RU
1401931776,1401933823,UA
+1401933824,1401935871,DE
1401935872,1401937919,FI
1401937920,1401939967,GB
1401939968,1401942015,UA
@@ -41643,7 +41836,9 @@
1403445248,1403461631,RU
1403461632,1403464663,FR
1403464664,1403464671,BE
-1403464672,1403469423,FR
+1403464672,1403465727,FR
+1403465728,1403465743,GB
+1403465744,1403469423,FR
1403469424,1403469431,US
1403469432,1403469823,FR
1403469824,1403486207,RU
@@ -41768,7 +41963,7 @@
1404010496,1404026879,PL
1404026880,1404043263,ES
1404043264,1404051455,EE
-1404051456,1404059647,KZ
+1404051456,1404059647,HR
1404059648,1404076031,NO
1404076032,1404084223,DE
1404084224,1404092415,NO
@@ -41791,9 +41986,7 @@
1404197888,1404198911,LT
1404198912,1404200959,SE
1404200960,1404203007,NL
-1404203008,1404204800,HR
-1404204801,1404205055,SE
-1404205056,1404207103,HR
+1404203008,1404207103,HR
1404207104,1404210175,NO
1404210176,1404212223,LV
1404212224,1404215295,SE
@@ -41855,7 +42048,10 @@
1404928000,1404944383,SE
1404944384,1404952575,DE
1404952576,1404960767,NL
-1404960768,1405050879,SE
+1404960768,1405026303,SE
+1405026304,1405042687,NO
+1405042688,1405048831,SE
+1405048832,1405050879,HR
1405050880,1405059071,AT
1405059072,1405063167,SE
1405063168,1405067263,NO
@@ -41937,7 +42133,31 @@
1406763008,1406771199,BE
1406771200,1406779391,GB
1406779392,1406787583,RU
-1406787584,1406795775,ES
+1406787584,1406787679,GB
+1406787680,1406787695,ES
+1406787696,1406787927,GB
+1406787928,1406787967,ES
+1406787968,1406788055,GB
+1406788056,1406788351,ES
+1406788352,1406788479,BG
+1406788480,1406788607,ES
+1406788608,1406788711,GB
+1406788712,1406789119,ES
+1406789120,1406789135,GB
+1406789136,1406789183,ES
+1406789184,1406789247,GB
+1406789248,1406789375,ES
+1406789376,1406789503,RO
+1406789504,1406789631,ES
+1406789632,1406789887,FR
+1406789888,1406790015,HU
+1406790016,1406790143,ES
+1406790144,1406790399,GB
+1406790400,1406790655,ES
+1406790656,1406790927,GB
+1406790928,1406790943,ES
+1406790944,1406790959,GB
+1406790960,1406795775,ES
1406795776,1406803967,GB
1406803968,1406812159,DE
1406812160,1406820351,SE
@@ -42051,7 +42271,9 @@
1407517032,1407517039,NG
1407517040,1407517047,A2
1407517048,1407517055,GQ
-1407517056,1407517151,A2
+1407517056,1407517135,A2
+1407517136,1407517143,NG
+1407517144,1407517151,A2
1407517152,1407517159,CD
1407517160,1407517167,ML
1407517168,1407517175,A2
@@ -42179,7 +42401,9 @@
1407520208,1407520215,NG
1407520216,1407520223,CD
1407520224,1407520231,SD
-1407520232,1407520271,A2
+1407520232,1407520239,A2
+1407520240,1407520247,NE
+1407520248,1407520271,A2
1407520272,1407520279,NG
1407520280,1407520311,A2
1407520312,1407520327,NG
@@ -42219,7 +42443,7 @@
1407520752,1407520759,BF
1407520760,1407520767,CD
1407520768,1407520775,TZ
-1407520776,1407520783,CD
+1407520776,1407520783,A2
1407520784,1407520791,SD
1407520792,1407520799,ZA
1407520800,1407520807,A2
@@ -42306,8 +42530,7 @@
1407522488,1407522495,ZW
1407522496,1407522503,LR
1407522504,1407522511,ZW
-1407522512,1407522519,UG
-1407522520,1407522527,A2
+1407522512,1407522527,A2
1407522528,1407522535,ZM
1407522536,1407522543,NG
1407522544,1407522559,UG
@@ -42361,11 +42584,11 @@
1407522976,1407522983,CD
1407522984,1407522991,A2
1407522992,1407522999,CD
-1407523000,1407523007,A2
-1407523008,1407523015,NG
+1407523000,1407523015,A2
1407523016,1407523023,KE
1407523024,1407523031,MU
-1407523032,1407523055,A2
+1407523032,1407523047,A2
+1407523048,1407523055,NG
1407523056,1407523063,MU
1407523064,1407523071,A2
1407523072,1407523079,CD
@@ -42399,9 +42622,12 @@
1407523336,1407523351,A2
1407523352,1407523359,LU
1407523360,1407523455,A2
-1407523456,1407523519,MW
+1407523456,1407523487,MW
+1407523488,1407523495,LR
+1407523496,1407523519,MW
1407523520,1407523535,A2
-1407523536,1407523551,NG
+1407523536,1407523543,SO
+1407523544,1407523551,NG
1407523552,1407523559,CM
1407523560,1407523567,KE
1407523568,1407523583,A2
@@ -42416,9 +42642,10 @@
1407523744,1407523751,IQ
1407523752,1407523791,A2
1407523792,1407523799,IQ
-1407523800,1407523831,A2
+1407523800,1407523807,SY
+1407523808,1407523831,A2
1407523832,1407523839,IQ
-1407523840,1407524351,MW
+1407523840,1407524351,A2
1407524352,1407524607,GB
1407524608,1407524615,ZW
1407524616,1407524623,CD
@@ -42472,7 +42699,8 @@
1407525048,1407525055,NG
1407525056,1407525063,ZA
1407525064,1407525071,SO
-1407525072,1407525087,A2
+1407525072,1407525079,CD
+1407525080,1407525087,A2
1407525088,1407525095,MW
1407525096,1407525103,ZW
1407525104,1407525111,NG
@@ -42535,10 +42763,8 @@
1407529024,1407529087,NG
1407529088,1407529095,SO
1407529096,1407529103,A2
-1407529104,1407529111,NG
-1407529112,1407529119,A2
-1407529120,1407529127,SD
-1407529128,1407529175,A2
+1407529104,1407529111,SO
+1407529112,1407529175,A2
1407529176,1407529183,SO
1407529184,1407529191,NG
1407529192,1407529207,A2
@@ -42549,7 +42775,7 @@
1407531552,1407531559,SD
1407531560,1407531567,A2
1407531568,1407531575,CD
-1407531576,1407531583,A2
+1407531576,1407531583,GQ
1407531584,1407531591,CD
1407531592,1407531599,A2
1407531600,1407531607,LY
@@ -42562,7 +42788,7 @@
1407531664,1407531671,MZ
1407531672,1407531687,CD
1407531688,1407531703,A2
-1407531704,1407531711,IQ
+1407531704,1407531711,SD
1407531712,1407531735,CD
1407531736,1407531743,ZW
1407531744,1407531751,A2
@@ -42591,7 +42817,8 @@
1407533408,1407533423,A2
1407533424,1407533567,GH
1407533568,1407533583,NG
-1407533584,1407533607,A2
+1407533584,1407533591,NE
+1407533592,1407533607,A2
1407533608,1407533631,NG
1407533632,1407533679,A2
1407533680,1407533695,NG
@@ -42812,15 +43039,16 @@
1407539720,1407539727,A2
1407539728,1407539735,GR
1407539736,1407539743,NG
-1407539744,1407539767,A2
+1407539744,1407539751,A2
+1407539752,1407539759,NG
+1407539760,1407539767,A2
1407539768,1407539775,GR
1407539776,1407539783,A2
1407539784,1407539791,GR
1407539792,1407539799,NG
1407539800,1407539823,A2
1407539824,1407539831,NG
-1407539832,1407539847,A2
-1407539848,1407539855,NG
+1407539832,1407539855,A2
1407539856,1407539863,CD
1407539864,1407539879,NG
1407539880,1407539887,A2
@@ -42828,7 +43056,8 @@
1407539896,1407539903,CD
1407539904,1407539911,A2
1407539912,1407539927,NG
-1407539928,1407539943,A2
+1407539928,1407539935,A2
+1407539936,1407539943,GN
1407539944,1407539951,CD
1407539952,1407539959,LR
1407539960,1407539967,A2
@@ -42871,7 +43100,9 @@
1407540432,1407540439,CI
1407540440,1407540447,A2
1407540448,1407540455,LR
-1407540456,1407540479,A2
+1407540456,1407540463,A2
+1407540464,1407540471,MU
+1407540472,1407540479,A2
1407540480,1407540487,CM
1407540488,1407540495,A2
1407540496,1407540503,NG
@@ -42896,7 +43127,9 @@
1407541032,1407541039,NG
1407541040,1407541047,A2
1407541048,1407541055,NG
-1407541056,1407541095,A2
+1407541056,1407541063,A2
+1407541064,1407541071,NG
+1407541072,1407541095,A2
1407541096,1407541103,GQ
1407541104,1407541175,A2
1407541176,1407541183,NG
@@ -42956,7 +43189,8 @@
1407545856,1407545863,CI
1407545864,1407545871,A2
1407545872,1407545879,CD
-1407545880,1407545895,A2
+1407545880,1407545887,A2
+1407545888,1407545895,NG
1407545896,1407545903,CD
1407545904,1407545911,A2
1407545912,1407545927,NG
@@ -42966,8 +43200,7 @@
1407545952,1407545959,BJ
1407545960,1407545967,A2
1407545968,1407545975,GQ
-1407545976,1407545983,A2
-1407545984,1407545991,MU
+1407545976,1407545991,A2
1407545992,1407545999,GN
1407546000,1407546007,CF
1407546008,1407546023,A2
@@ -43015,15 +43248,15 @@
1407548128,1407548143,CM
1407548144,1407548151,A2
1407548152,1407548415,NG
-1407548416,1407548543,GE
+1407548416,1407548443,GE
+1407548444,1407548447,NE
+1407548448,1407548543,GE
1407548544,1407548711,A2
1407548712,1407548719,CD
1407548720,1407548767,A2
1407548768,1407548775,CD
1407548776,1407548927,A2
-1407548928,1407548943,NG
-1407548944,1407548951,A2
-1407548952,1407548959,NG
+1407548928,1407548959,NG
1407548960,1407548967,A2
1407548968,1407548975,CM
1407548976,1407548983,A2
@@ -43066,7 +43299,9 @@
1407693160,1407693167,ES
1407693168,1407695215,GB
1407695216,1407695223,ES
-1407695224,1407700271,GB
+1407695224,1407696487,GB
+1407696488,1407696495,AU
+1407696496,1407700271,GB
1407700272,1407700287,DE
1407700288,1407702015,GB
1407702016,1407702271,FR
@@ -43086,9 +43321,7 @@
1407704384,1407704447,FR
1407704448,1407705207,GB
1407705208,1407705215,ES
-1407705216,1407705247,GB
-1407705248,1407705279,ES
-1407705280,1407705599,GB
+1407705216,1407705599,GB
1407705600,1407705727,FR
1407705728,1407705759,GB
1407705760,1407705791,FR
@@ -43214,8 +43447,7 @@
1410009344,1410009479,US
1410009480,1410009487,A2
1410009488,1410009535,GI
-1410009536,1410010367,A2
-1410010368,1410010399,IR
+1410009536,1410010399,A2
1410010400,1410010431,LY
1410010432,1410010543,A2
1410010544,1410010575,LY
@@ -43232,10 +43464,7 @@
1410010832,1410010879,A2
1410010880,1410011135,IR
1410011136,1410011647,DE
-1410011648,1410012159,A2
-1410012160,1410012415,IQ
-1410012416,1410012447,AF
-1410012448,1410012671,A2
+1410011648,1410012671,A2
1410012672,1410013183,DE
1410013184,1410013439,ES
1410013440,1410013471,IR
@@ -43312,15 +43541,9 @@
1410018560,1410018591,A2
1410018592,1410018607,IR
1410018608,1410018623,LY
-1410018624,1410018815,A2
-1410018816,1410018831,DE
-1410018832,1410018847,A2
-1410018848,1410018863,DE
-1410018864,1410020103,A2
+1410018624,1410020103,A2
1410020104,1410020111,US
-1410020112,1410020351,A2
-1410020352,1410020863,US
-1410020864,1410021375,A2
+1410020112,1410021375,A2
1410021376,1410021407,IR
1410021408,1410021631,A2
1410021632,1410021663,IR
@@ -43394,8 +43617,7 @@
1410037760,1410038015,US
1410038016,1410042815,A2
1410042816,1410042831,US
-1410042832,1410044927,A2
-1410044928,1410045183,VG
+1410042832,1410045183,A2
1410045184,1410045439,IQ
1410045440,1410045695,LB
1410045696,1410071815,A2
@@ -43488,7 +43710,7 @@
1410573440,1410573695,DE
1410573696,1410573711,RU
1410573712,1410573759,DE
-1410573760,1410573775,BA
+1410573760,1410573775,RU
1410573776,1410573799,DE
1410573800,1410573815,IT
1410573816,1410573823,RU
@@ -43502,7 +43724,9 @@
1410574584,1410574591,RU
1410574592,1410574719,DE
1410574720,1410574727,RU
-1410574728,1410575103,DE
+1410574728,1410574847,DE
+1410574848,1410574975,BR
+1410574976,1410575103,DE
1410575104,1410575111,US
1410575112,1410575119,IT
1410575120,1410575135,DE
@@ -43524,7 +43748,9 @@
1410575856,1410575871,DE
1410575872,1410575999,DK
1410576000,1410576255,DE
-1410576256,1410576383,IT
+1410576256,1410576319,IT
+1410576320,1410576351,DE
+1410576352,1410576383,IT
1410576384,1410588671,DE
1410588672,1410596863,GB
1410596864,1410605055,ES
@@ -43546,7 +43772,166 @@
1410711552,1410719743,BG
1410719744,1410727935,RU
1410727936,1410736127,BG
-1410736128,1410744319,RS
+1410736128,1410736128,RS
+1410736129,1410736382,AL
+1410736383,1410736384,RS
+1410736385,1410736638,AL
+1410736639,1410736640,RS
+1410736641,1410736894,AL
+1410736895,1410736896,RS
+1410736897,1410736911,AL
+1410736912,1410736928,RS
+1410736929,1410736991,AL
+1410736992,1410737415,RS
+1410737416,1410737423,AL
+1410737424,1410737431,RS
+1410737432,1410737439,AL
+1410737440,1410737664,RS
+1410737665,1410737918,AL
+1410737919,1410737920,RS
+1410737921,1410738174,AL
+1410738175,1410738175,RS
+1410738176,1410738215,AL
+1410738216,1410738223,RS
+1410738224,1410738247,AL
+1410738248,1410738263,RS
+1410738264,1410738271,AL
+1410738272,1410738279,RS
+1410738280,1410738295,AL
+1410738296,1410738304,RS
+1410738305,1410738310,AL
+1410738311,1410738320,RS
+1410738321,1410738326,AL
+1410738327,1410738328,RS
+1410738329,1410738334,AL
+1410738335,1410738351,RS
+1410738352,1410738359,AL
+1410738360,1410738384,RS
+1410738385,1410738390,AL
+1410738391,1410738439,RS
+1410738440,1410738447,AL
+1410738448,1410738703,RS
+1410738704,1410738718,AL
+1410738719,1410738720,RS
+1410738721,1410738734,AL
+1410738735,1410738752,RS
+1410738753,1410738766,AL
+1410738767,1410738768,RS
+1410738769,1410738782,AL
+1410738783,1410738800,RS
+1410738801,1410738814,AL
+1410738815,1410738816,RS
+1410738817,1410738830,AL
+1410738831,1410738832,RS
+1410738833,1410738846,AL
+1410738847,1410738864,RS
+1410738865,1410738878,AL
+1410738879,1410738896,RS
+1410738897,1410738902,AL
+1410738903,1410738912,RS
+1410738913,1410738927,AL
+1410738928,1410739200,RS
+1410739201,1410739326,AL
+1410739327,1410739328,RS
+1410739329,1410739390,AL
+1410739391,1410739472,RS
+1410739473,1410739486,AL
+1410739487,1410739520,RS
+1410739521,1410739534,AL
+1410739535,1410739543,RS
+1410739544,1410739550,AL
+1410739551,1410739568,RS
+1410739569,1410739582,AL
+1410739583,1410739616,RS
+1410739617,1410739630,AL
+1410739631,1410739696,RS
+1410739697,1410739710,AL
+1410739711,1410739712,RS
+1410739713,1410739719,AL
+1410739720,1410739720,RS
+1410739721,1410739727,AL
+1410739728,1410739728,RS
+1410739729,1410739734,AL
+1410739735,1410739736,RS
+1410739737,1410739742,AL
+1410739743,1410739744,RS
+1410739745,1410739750,AL
+1410739751,1410739752,RS
+1410739753,1410739759,AL
+1410739760,1410739776,RS
+1410739777,1410739783,AL
+1410739784,1410739791,RS
+1410739792,1410739799,AL
+1410739800,1410739807,RS
+1410739808,1410739879,AL
+1410739880,1410739887,RS
+1410739888,1410739919,AL
+1410739920,1410739927,RS
+1410739928,1410739951,AL
+1410739952,1410739967,RS
+1410739968,1410740003,AL
+1410740004,1410740007,RS
+1410740008,1410740043,AL
+1410740044,1410740047,RS
+1410740048,1410740122,AL
+1410740123,1410740123,RS
+1410740124,1410740135,AL
+1410740136,1410740139,RS
+1410740140,1410740335,AL
+1410740336,1410740343,RS
+1410740344,1410740383,AL
+1410740384,1410740391,RS
+1410740392,1410740415,AL
+1410740416,1410740423,RS
+1410740424,1410740471,AL
+1410740472,1410740479,RS
+1410740480,1410740507,AL
+1410740508,1410740511,RS
+1410740512,1410740515,AL
+1410740516,1410740519,RS
+1410740520,1410740643,AL
+1410740644,1410740647,RS
+1410740648,1410740675,AL
+1410740676,1410740679,RS
+1410740680,1410740734,AL
+1410740735,1410740735,RS
+1410740736,1410740751,AL
+1410740752,1410740767,RS
+1410740768,1410740823,AL
+1410740824,1410740831,RS
+1410740832,1410740871,AL
+1410740872,1410740879,RS
+1410740880,1410740911,AL
+1410740912,1410740919,RS
+1410740920,1410740931,AL
+1410740932,1410740935,RS
+1410740936,1410740943,AL
+1410740944,1410740991,RS
+1410740992,1410741303,AL
+1410741304,1410741327,RS
+1410741328,1410741335,AL
+1410741336,1410741351,RS
+1410741352,1410741427,AL
+1410741428,1410741431,RS
+1410741432,1410741443,AL
+1410741444,1410741447,RS
+1410741448,1410741479,AL
+1410741480,1410741483,RS
+1410741484,1410741567,AL
+1410741568,1410741583,RS
+1410741584,1410742279,AL
+1410742280,1410742319,RS
+1410742320,1410742351,AL
+1410742352,1410742359,RS
+1410742360,1410742415,AL
+1410742416,1410742527,RS
+1410742528,1410742907,AL
+1410742908,1410742911,RS
+1410742912,1410742923,AL
+1410742924,1410743039,RS
+1410743040,1410743935,AL
+1410743936,1410743999,RS
+1410744000,1410744319,AL
1410744320,1410744575,FR
1410744576,1410744831,A2
1410744832,1410745223,FR
@@ -43596,7 +43981,8 @@
1410755584,1410760191,AQ
1410760192,1410760447,DE
1410760448,1410760455,CN
-1410760456,1410760471,AQ
+1410760456,1410760463,BS
+1410760464,1410760471,AQ
1410760472,1410760487,DE
1410760488,1410760503,AQ
1410760504,1410760703,DE
@@ -43721,19 +44107,23 @@
1411999904,1411999911,BA
1411999912,1411999919,SI
1411999920,1411999927,BA
-1411999928,1411999951,SI
+1411999928,1411999935,SI
+1411999936,1411999943,BA
+1411999944,1411999951,SI
1411999952,1411999959,BA
-1411999960,1411999983,SI
-1411999984,1412000767,BA
+1411999960,1411999967,SI
+1411999968,1412000767,BA
1412000768,1412000783,SI
1412000784,1412000791,BA
1412000792,1412000863,SI
1412000864,1412000879,BA
-1412000880,1412000903,SI
-1412000904,1412000911,BA
+1412000880,1412000895,SI
+1412000896,1412000911,BA
1412000912,1412000943,SI
-1412000944,1412000991,BA
-1412000992,1412001007,SI
+1412000944,1412000959,BA
+1412000960,1412000967,SI
+1412000968,1412000999,BA
+1412001000,1412001007,SI
1412001008,1412001015,BA
1412001016,1412001311,SI
1412001312,1412001319,DE
@@ -43746,7 +44136,9 @@
1412002784,1412002815,SI
1412002816,1412002847,BA
1412002848,1412002863,SI
-1412002864,1412002911,BA
+1412002864,1412002895,BA
+1412002896,1412002903,SI
+1412002904,1412002911,BA
1412002912,1412002919,SI
1412002920,1412003015,BA
1412003016,1412003023,SI
@@ -43764,7 +44156,9 @@
1412003264,1412003271,SI
1412003272,1412003303,BA
1412003304,1412003327,SI
-1412003328,1412003351,BA
+1412003328,1412003335,BA
+1412003336,1412003343,SI
+1412003344,1412003351,BA
1412003352,1412003375,SI
1412003376,1412003383,BA
1412003384,1412003391,SI
@@ -43777,11 +44171,7 @@
1412003624,1412003631,BA
1412003632,1412003639,SI
1412003640,1412003647,BA
-1412003648,1412003727,SI
-1412003728,1412003783,BA
-1412003784,1412003791,SI
-1412003792,1412003823,BA
-1412003824,1412003855,SI
+1412003648,1412003855,SI
1412003856,1412003903,BG
1412003904,1412003935,SI
1412003936,1412004351,BG
@@ -43878,7 +44268,9 @@
1422403840,1422403903,IT
1422403904,1422406399,DE
1422406400,1422406463,GB
-1422406464,1422468207,DE
+1422406464,1422410367,DE
+1422410368,1422410495,IT
+1422410496,1422468207,DE
1422468208,1422468223,IT
1422468224,1422468671,DE
1422468672,1422468735,IT
@@ -43934,7 +44326,7 @@
1424588800,1424588839,DE
1424588840,1424588847,GB
1424588848,1424588863,DE
-1424588864,1424588927,GB
+1424588864,1424588927,US
1424588928,1424588951,DE
1424588952,1424588959,GB
1424588960,1424588963,IT
@@ -43964,12 +44356,16 @@
1424593968,1424593983,GB
1424593984,1424594055,FR
1424594056,1424594063,IT
-1424594064,1424594103,FR
+1424594064,1424594087,FR
+1424594088,1424594095,GB
+1424594096,1424594103,FR
1424594104,1424594111,GB
1424594112,1424594175,FR
1424594176,1424594431,GB
1424594432,1424594519,IE
-1424594520,1424595455,GB
+1424594520,1424594527,GB
+1424594528,1424594535,IE
+1424594536,1424595455,GB
1424595456,1424595527,IT
1424595528,1424595535,GB
1424595536,1424595575,IT
@@ -43986,8 +44382,8 @@
1424597352,1424597375,GB
1424597376,1424597391,CZ
1424597392,1424597407,GB
-1424597408,1424597423,CZ
-1424597424,1424597503,GB
+1424597408,1424597431,CZ
+1424597432,1424597503,GB
1424597504,1424597759,FR
1424597760,1424598015,IT
1424598016,1424599039,GB
@@ -44011,7 +44407,8 @@
1424600576,1424600831,FR
1424600832,1424601087,BE
1424601088,1424601343,GB
-1424601344,1424601599,ES
+1424601344,1424601351,ES
+1424601352,1424601599,GB
1424601600,1424601855,CH
1424601856,1424602111,GB
1424602112,1424602623,DE
@@ -44020,7 +44417,8 @@
1424602744,1424602879,GB
1424602880,1424602911,US
1424602912,1424602927,FR
-1424602928,1424603007,US
+1424602928,1424602935,GB
+1424602936,1424603007,US
1424603008,1424603023,GB
1424603024,1424603087,US
1424603088,1424603095,GB
@@ -44028,8 +44426,8 @@
1424603136,1424603391,SK
1424603392,1424603647,DE
1424603648,1424603903,GB
-1424603904,1424604031,ES
-1424604032,1424604047,GB
+1424603904,1424604039,ES
+1424604040,1424604047,GB
1424604048,1424604159,ES
1424604160,1424604543,NL
1424604544,1424604671,GB
@@ -44072,8 +44470,8 @@
1424608328,1424608383,FR
1424608384,1424608399,ES
1424608400,1424608511,FR
-1424608512,1424608543,ES
-1424608544,1424608567,GB
+1424608512,1424608559,ES
+1424608560,1424608567,GB
1424608568,1424608687,ES
1424608688,1424608691,GB
1424608692,1424609023,ES
@@ -44084,7 +44482,9 @@
1424609396,1424609399,GB
1424609400,1424609535,CH
1424609536,1424609543,GB
-1424609544,1424609791,CH
+1424609544,1424609743,CH
+1424609744,1424609759,GB
+1424609760,1424609791,CH
1424609792,1424610303,GB
1424610304,1424610559,TZ
1424610560,1424610815,PL
@@ -44092,8 +44492,8 @@
1424611072,1424611135,BE
1424611136,1424611151,GB
1424611152,1424611271,BE
-1424611272,1424611295,GB
-1424611296,1424611327,BE
+1424611272,1424611279,LU
+1424611280,1424611327,BE
1424611328,1424611583,PL
1424611584,1424612095,GB
1424612096,1424612231,CZ
@@ -44112,11 +44512,9 @@
1424614136,1424614143,IT
1424614144,1424614399,GB
1424614400,1424614415,FR
-1424614416,1424614431,IT
-1424614432,1424614439,GB
-1424614440,1424614495,IT
-1424614496,1424614527,GB
-1424614528,1424614655,IT
+1424614416,1424614503,IT
+1424614504,1424614511,GB
+1424614512,1424614655,IT
1424614656,1424614911,FR
1424614912,1424615167,RO
1424615168,1424615679,GB
@@ -44125,7 +44523,8 @@
1424615808,1424615935,IT
1424615936,1424616191,FR
1424616192,1424616447,IT
-1424616448,1424616483,ES
+1424616448,1424616479,GB
+1424616480,1424616483,ES
1424616484,1424616487,GB
1424616488,1424616503,ES
1424616504,1424616511,GB
@@ -44145,8 +44544,7 @@
1424617396,1424617399,GB
1424617400,1424617407,IT
1424617408,1424617423,ES
-1424617424,1424617431,GB
-1424617432,1424617439,ES
+1424617424,1424617439,GB
1424617440,1424617447,IT
1424617448,1424617455,GB
1424617456,1424617463,IT
@@ -44621,33 +45019,18 @@
1426800640,1426817023,PL
1426817024,1426833407,BG
1426833408,1426849791,SE
-1426849792,1426850303,NL
-1426850304,1426850335,SE
-1426850336,1426850367,GB
-1426850368,1426850463,NL
-1426850464,1426850495,GB
-1426850496,1426851519,NL
+1426849792,1426851519,NL
1426851520,1426851583,PA
-1426851584,1426851839,NL
-1426851840,1426852095,SE
-1426852096,1426852352,NL
+1426851584,1426852352,NL
1426852353,1426852359,RU
1426852360,1426852367,SE
1426852368,1426852375,NL
1426852376,1426852383,US
-1426852384,1426852543,GB
-1426852544,1426856447,NL
-1426856448,1426856703,ES
-1426856704,1426857472,NL
+1426852384,1426857472,NL
1426857473,1426857500,ES
-1426857501,1426859263,NL
-1426859264,1426859519,RU
-1426859520,1426864511,NL
+1426857501,1426864511,NL
1426864512,1426864639,PA
-1426864640,1426864895,FR
-1426864896,1426865663,NL
-1426865664,1426865919,BE
-1426865920,1426866175,ES
+1426864640,1426866175,NL
1426866176,1426882559,GB
1426882560,1426898943,FR
1426898944,1426915327,RU
@@ -44670,7 +45053,9 @@
1426968792,1426968800,ES
1426968801,1426969135,GB
1426969136,1426969151,ES
-1426969152,1426972319,GB
+1426969152,1426971855,GB
+1426971856,1426971863,ES
+1426971864,1426972319,GB
1426972320,1426972326,FR
1426972327,1426973335,GB
1426973336,1426973343,ES
@@ -44732,8 +45117,7 @@
1427728480,1427728511,CY
1427728512,1427728543,BR
1427728544,1427728575,DE
-1427728576,1427728607,BR
-1427728608,1427728639,TW
+1427728576,1427728639,BR
1427728640,1427728671,DE
1427728672,1427728703,TR
1427728704,1427728735,RU
@@ -44748,52 +45132,62 @@
1427729056,1427729087,CA
1427729088,1427729119,DE
1427729120,1427729151,BR
-1427729152,1427729311,DE
+1427729152,1427729215,DE
+1427729216,1427729279,IN
+1427729280,1427729311,DE
1427729312,1427729343,GR
1427729344,1427742719,DE
1427742720,1427742751,IO
-1427742752,1427742975,DE
+1427742752,1427742911,DE
+1427742912,1427742943,US
+1427742944,1427742975,DE
1427742976,1427743007,RU
1427743008,1427743039,US
1427743040,1427743071,BR
1427743072,1427743103,CY
1427743104,1427743135,BR
-1427743136,1427743199,DE
+1427743136,1427743167,IN
+1427743168,1427743199,DE
1427743200,1427743231,TR
1427743232,1427743263,GR
1427743264,1427743327,DE
1427743328,1427743359,NL
-1427743360,1427743391,DE
-1427743392,1427743423,BR
-1427743424,1427743455,DE
+1427743360,1427743423,BR
+1427743424,1427743455,TR
1427743456,1427743487,CY
1427743488,1427743583,DE
1427743584,1427743615,LV
1427743616,1427743647,DK
-1427743648,1427743775,DE
+1427743648,1427743679,DE
+1427743680,1427743711,RU
+1427743712,1427743775,DE
1427743776,1427743807,ZA
1427743808,1427743839,DE
1427743840,1427743871,RU
-1427743872,1427743935,DE
+1427743872,1427743903,DE
+1427743904,1427743935,US
1427743936,1427743967,RU
1427743968,1427743999,US
-1427744000,1427744031,TW
-1427744032,1427744127,DE
+1427744000,1427744031,DE
+1427744032,1427744063,RU
+1427744064,1427744127,DE
1427744128,1427744159,PL
1427744160,1427744191,RU
1427744192,1427744255,DE
1427744256,1427744287,US
1427744288,1427744319,TR
-1427744320,1427744351,DE
+1427744320,1427744351,IN
1427744352,1427744383,UA
1427744384,1427744415,PL
1427744416,1427744447,UA
1427744448,1427744479,US
-1427744480,1427744639,DE
+1427744480,1427744575,DE
+1427744576,1427744607,PL
+1427744608,1427744639,DE
1427744640,1427744671,TR
-1427744672,1427744735,DE
-1427744736,1427744767,DK
-1427744768,1427744863,DE
+1427744672,1427744767,DE
+1427744768,1427744799,BR
+1427744800,1427744863,DE
1427744864,1427744927,TR
1427744928,1427744959,HU
1427744960,1427744991,RU
@@ -44803,11 +45197,12 @@
1427745088,1427745151,DE
1427745152,1427745183,RO
1427745184,1427745215,CH
-1427745216,1427745279,DE
+1427745216,1427745247,TR
+1427745248,1427745279,DE
1427745280,1427745311,MA
1427745312,1427745343,TH
1427745344,1427745375,DE
-1427745376,1427745407,TW
+1427745376,1427745407,BR
1427745408,1427745471,US
1427745472,1427745503,RO
1427745504,1427745535,RU
@@ -44822,9 +45217,11 @@
1427745792,1427745823,GB
1427745824,1427745855,US
1427745856,1427745887,BR
-1427745888,1427745919,DE
+1427745888,1427745919,IN
1427745920,1427745951,ES
-1427745952,1427746047,DE
+1427745952,1427745983,IN
+1427745984,1427746015,DE
+1427746016,1427746047,TR
1427746048,1427746079,SE
1427746080,1427746111,GB
1427746112,1427746143,DE
@@ -44845,18 +45242,25 @@
1427748160,1427748191,GB
1427748192,1427748255,DE
1427748256,1427748287,US
-1427748288,1427748447,DE
+1427748288,1427748351,DE
+1427748352,1427748383,BR
+1427748384,1427748447,DE
1427748448,1427748479,RU
1427748480,1427748511,MA
-1427748512,1427748607,DE
+1427748512,1427748575,DE
+1427748576,1427748607,BR
1427748608,1427748639,HU
-1427748640,1427748767,DE
-1427748768,1427748799,BR
-1427748800,1427749567,DE
+1427748640,1427748735,DE
+1427748736,1427748799,BR
+1427748800,1427748831,MA
+1427748832,1427749535,DE
+1427749536,1427749567,MA
1427749568,1427749599,CY
1427749600,1427749695,DE
1427749696,1427749727,BR
-1427749728,1427749855,DE
+1427749728,1427749759,DE
+1427749760,1427749791,BR
+1427749792,1427749855,DE
1427749856,1427749887,RU
1427749888,1427749919,BR
1427749920,1427749951,US
@@ -44875,18 +45279,22 @@
1427751424,1427759903,DE
1427759904,1427759935,MA
1427759936,1427759967,HR
-1427759968,1427760031,DE
+1427759968,1427759999,DE
+1427760000,1427760031,BR
1427760032,1427760095,US
-1427760096,1427760191,DE
+1427760096,1427760159,DE
+1427760160,1427760191,PL
1427760192,1427760255,US
1427760256,1427760319,BR
1427760320,1427760351,TR
1427760352,1427760383,RU
-1427760384,1427760415,TR
-1427760416,1427760447,BR
+1427760384,1427760415,IN
+1427760416,1427760447,TR
1427760448,1427760575,DE
1427760576,1427760607,CH
-1427760608,1427760799,DE
+1427760608,1427760671,DE
+1427760672,1427760703,BR
+1427760704,1427760799,DE
1427760800,1427760831,US
1427760832,1427760863,DE
1427760864,1427760895,US
@@ -44904,7 +45312,9 @@
1427761312,1427761343,UA
1427761344,1427761375,CY
1427761376,1427761407,TW
-1427761408,1427761503,DE
+1427761408,1427761439,RU
+1427761440,1427761471,US
+1427761472,1427761503,IN
1427761504,1427761535,PL
1427761536,1427761567,US
1427761568,1427761599,RU
@@ -45163,7 +45573,8 @@
1433602320,1433608191,DE
1433608192,1433608959,GB
1433608960,1433609215,DE
-1433609216,1433609727,GB
+1433609216,1433609471,ZA
+1433609472,1433609727,GB
1433609728,1433610239,CH
1433610240,1433612287,US
1433612288,1433614335,GB
@@ -45198,7 +45609,8 @@
1433806656,1433806687,IT
1433806688,1433806719,NL
1433806720,1433806751,DE
-1433806752,1433812991,FR
+1433806752,1433806783,ES
+1433806784,1433812991,FR
1433812992,1433821183,BG
1433821184,1433829375,GE
1433829376,1433833471,RU
@@ -45223,7 +45635,9 @@
1433860096,1433862143,DE
1433862144,1433862467,CH
1433862468,1433862471,US
-1433862472,1433862559,CH
+1433862472,1433862519,CH
+1433862520,1433862527,NL
+1433862528,1433862559,CH
1433862560,1433862575,GB
1433862576,1433862751,CH
1433862752,1433862783,MC
@@ -45301,8 +45715,8 @@
1434683328,1434683391,MY
1434683392,1434685759,DE
1434685760,1434685951,NL
-1434685952,1434686719,DE
-1434686720,1434687231,NL
+1434685952,1434686975,DE
+1434686976,1434687231,NL
1434687232,1434687359,DE
1434687360,1434687487,NL
1434687488,1434687647,DE
@@ -45321,9 +45735,7 @@
1434689952,1434690015,NL
1434690016,1434692607,DE
1434692608,1434692671,NL
-1434692672,1434693119,DE
-1434693120,1434693375,NL
-1434693376,1434694655,DE
+1434692672,1434694655,DE
1434694656,1434694719,NL
1434694720,1434696447,DE
1434696448,1434696703,NL
@@ -45334,17 +45746,18 @@
1434702592,1434702655,DE
1434702656,1434702671,NL
1434702672,1434702783,DE
-1434702784,1434702847,NL
-1434702848,1434702975,DE
+1434702784,1434702911,NL
+1434702912,1434702975,DE
1434702976,1434703039,NL
1434703040,1434705727,DE
1434705728,1434705919,NL
-1434705920,1434712063,DE
+1434705920,1434710015,DE
+1434710016,1434710527,NL
+1434710528,1434712063,DE
1434712064,1434712319,NL
1434712320,1434712959,DE
1434712960,1434712975,NL
-1434712976,1434713855,DE
-1434713856,1434714111,NL
+1434712976,1434714111,DE
1434714112,1434746879,AZ
1434746880,1434779647,CZ
1434779648,1434812415,GB
@@ -45488,13 +45901,21 @@
1438860288,1438860415,US
1438860416,1438861823,DE
1438861824,1438862079,CH
-1438862080,1438869591,DE
+1438862080,1438864827,DE
+1438864828,1438864831,PA
+1438864832,1438864927,DE
+1438864928,1438864959,PA
+1438864960,1438868295,DE
+1438868296,1438868303,LT
+1438868304,1438869591,DE
1438869592,1438869595,RU
1438869596,1438869647,DE
1438869648,1438869651,LV
1438869652,1438869655,US
1438869656,1438869663,UA
-1438869664,1438873119,DE
+1438869664,1438870783,DE
+1438870784,1438871039,GB
+1438871040,1438873119,DE
1438873120,1438873127,PA
1438873128,1438873671,DE
1438873672,1438873679,PA
@@ -45631,23 +46052,27 @@
1439467008,1439482367,RO
1439482368,1439482879,GB
1439482880,1439498239,RO
-1439498240,1439503103,DE
-1439503104,1439503359,PT
-1439503360,1439514111,DE
-1439514112,1439514367,GB
-1439514368,1439514623,DE
+1439498240,1439507199,DE
+1439507200,1439507455,GB
+1439507456,1439513599,DE
+1439513600,1439514623,GB
1439514624,1439516671,IT
1439516672,1439518207,DE
1439518208,1439518719,IT
-1439518720,1439529599,DE
-1439529600,1439529727,GB
-1439529728,1439529983,DE
+1439518720,1439527935,DE
+1439527936,1439528959,GB
+1439528960,1439529983,DE
1439529984,1439530239,EG
-1439530240,1439535103,DE
-1439535104,1439538175,IT
-1439538176,1439538687,DE
+1439530240,1439530495,GB
+1439530496,1439534079,DE
+1439534080,1439535103,GB
+1439535104,1439536127,IT
+1439536128,1439537151,GB
+1439537152,1439538175,IT
+1439538176,1439538687,GB
1439538688,1439539199,IT
-1439539200,1439549439,DE
+1439539200,1439543295,DE
+1439543296,1439549439,GB
1439549440,1439551487,IT
1439551488,1439556095,DE
1439556096,1439556607,IT
@@ -45660,8 +46085,8 @@
1439561216,1439561727,DE
1439561728,1439562239,GB
1439562240,1439562751,IE
-1439562752,1439562879,DE
-1439562880,1439563263,GB
+1439562752,1439563007,DE
+1439563008,1439563263,GB
1439563264,1439563775,DE
1439563776,1439629311,LT
1439629312,1439694847,CZ
@@ -45718,7 +46143,9 @@
1441389568,1441389599,LU
1441389600,1441389967,FR
1441389968,1441389983,CA
-1441389984,1441390591,FR
+1441389984,1441390383,FR
+1441390384,1441390399,CA
+1441390400,1441390591,FR
1441390592,1441398783,DK
1441398784,1441415167,RU
1441415168,1441423359,GB
@@ -45754,7 +46181,11 @@
1441546240,1441554431,DK
1441554432,1441554687,GB
1441554688,1441554943,NL
-1441554944,1441557759,GB
+1441554944,1441555199,GB
+1441555200,1441555327,DE
+1441555328,1441556735,GB
+1441556736,1441556991,DE
+1441556992,1441557759,GB
1441557760,1441558015,NL
1441558016,1441562623,GB
1441562624,1441564671,IQ
@@ -45832,6 +46263,8 @@
1442807808,1442811903,BG
1442811904,1442815999,AT
1442816000,1442820095,BG
+1442820096,1442822143,UA
+1442822144,1442824191,RU
1442824192,1442828287,BE
1442828288,1442832383,NL
1442832384,1442836479,GB
@@ -45904,7 +46337,9 @@
1446576128,1446608895,IR
1446608896,1446641663,BY
1446641664,1446674431,SI
-1446674432,1446694543,DK
+1446674432,1446678407,DK
+1446678408,1446678411,US
+1446678412,1446694543,DK
1446694544,1446694559,SE
1446694560,1446694591,DK
1446694592,1446694607,NO
@@ -45919,7 +46354,9 @@
1446710800,1446710815,MT
1446710816,1446710887,AT
1446710888,1446710895,MT
-1446710896,1446712783,AT
+1446710896,1446710903,AT
+1446710904,1446710911,MT
+1446710912,1446712783,AT
1446712784,1446712791,DE
1446712792,1446716399,AT
1446716400,1446716407,MT
@@ -45942,11 +46379,10 @@
1446904104,1446904111,IQ
1446904112,1446904119,GN
1446904120,1446904127,IQ
-1446904128,1446904135,AF
+1446904128,1446904135,A2
1446904136,1446904143,LY
1446904144,1446904151,ER
-1446904152,1446904159,AF
-1446904160,1446904231,A2
+1446904152,1446904231,A2
1446904232,1446904239,IQ
1446904240,1446904247,A2
1446904248,1446904255,AF
@@ -45960,7 +46396,8 @@
1446904400,1446904415,IQ
1446904416,1446904575,A2
1446904576,1446904591,SD
-1446904592,1446904607,A2
+1446904592,1446904599,AF
+1446904600,1446904607,A2
1446904608,1446904623,SD
1446904624,1446904639,A2
1446904640,1446904679,IQ
@@ -45997,17 +46434,19 @@
1446904956,1446904959,A2
1446904960,1446904963,IQ
1446904964,1446904967,TD
-1446904968,1446904971,IQ
+1446904968,1446904971,A2
1446904972,1446904975,LY
1446904976,1446904979,CG
1446904980,1446904983,TG
1446904984,1446904991,LY
1446904992,1446904995,IQ
-1446904996,1446905007,A2
-1446905008,1446905011,CG
+1446904996,1446905003,A2
+1446905004,1446905007,NG
+1446905008,1446905011,A2
1446905012,1446905015,AF
1446905016,1446905019,NG
-1446905020,1446905027,A2
+1446905020,1446905023,LY
+1446905024,1446905027,A2
1446905028,1446905031,IQ
1446905032,1446905035,LY
1446905036,1446905039,IQ
@@ -46015,8 +46454,7 @@
1446905044,1446905047,IQ
1446905048,1446905051,LY
1446905052,1446905059,IQ
-1446905060,1446905063,A2
-1446905064,1446905067,NG
+1446905060,1446905067,NG
1446905068,1446905083,A2
1446905084,1446905095,AF
1446905096,1446905099,LY
@@ -46029,8 +46467,8 @@
1446905128,1446905131,IQ
1446905132,1446905139,LY
1446905140,1446905147,IQ
-1446905148,1446905155,A2
-1446905156,1446905159,IQ
+1446905148,1446905151,A2
+1446905152,1446905159,IQ
1446905160,1446905163,A2
1446905164,1446905171,LY
1446905172,1446905175,A2
@@ -46052,7 +46490,9 @@
1446905244,1446905247,AF
1446905248,1446905251,A2
1446905252,1446905255,LY
-1446905256,1446905271,A2
+1446905256,1446905259,A2
+1446905260,1446905263,IQ
+1446905264,1446905271,A2
1446905272,1446905287,IQ
1446905288,1446905295,LY
1446905296,1446905303,IQ
@@ -46061,16 +46501,20 @@
1446905312,1446905315,EG
1446905316,1446905319,NG
1446905320,1446905331,IQ
-1446905332,1446905335,A2
+1446905332,1446905335,NG
1446905336,1446905343,IQ
1446905344,1446905351,NG
1446905352,1446905383,A2
1446905384,1446905391,SD
1446905392,1446905583,A2
1446905584,1446905591,AF
-1446905592,1446905619,A2
+1446905592,1446905611,A2
+1446905612,1446905615,IQ
+1446905616,1446905619,A2
1446905620,1446905623,TD
-1446905624,1446905635,A2
+1446905624,1446905627,A2
+1446905628,1446905631,IQ
+1446905632,1446905635,A2
1446905636,1446905639,IQ
1446905640,1446905643,A2
1446905644,1446905647,IQ
@@ -46080,7 +46524,8 @@
1446905660,1446905663,ER
1446905664,1446905667,A2
1446905668,1446905675,AF
-1446905676,1446905703,A2
+1446905676,1446905683,LY
+1446905684,1446905703,A2
1446905704,1446905707,IQ
1446905708,1446905715,A2
1446905716,1446905719,IQ
@@ -46090,8 +46535,7 @@
1446905732,1446905735,AF
1446905736,1446905739,IQ
1446905740,1446905743,A2
-1446905744,1446905747,LY
-1446905748,1446905759,A2
+1446905744,1446905759,LY
1446905760,1446905763,ML
1446905764,1446905767,A2
1446905768,1446905775,IQ
@@ -46121,7 +46565,7 @@
1446906072,1446906079,CY
1446906080,1446906111,A2
1446906112,1446906119,IQ
-1446906120,1446906123,BG
+1446906120,1446906123,A2
1446906124,1446906131,IQ
1446906132,1446906135,SD
1446906136,1446906151,A2
@@ -46154,7 +46598,8 @@
1446906392,1446906399,CY
1446906400,1446906883,A2
1446906884,1446906887,AF
-1446906888,1446906895,A2
+1446906888,1446906891,LY
+1446906892,1446906895,A2
1446906896,1446906899,GN
1446906900,1446906915,A2
1446906916,1446906919,AF
@@ -46320,8 +46765,7 @@
1446908232,1446908235,LY
1446908236,1446908247,A2
1446908248,1446908251,AF
-1446908252,1446908255,A2
-1446908256,1446908259,SZ
+1446908252,1446908259,A2
1446908260,1446908263,IQ
1446908264,1446908267,A2
1446908268,1446908271,AF
@@ -46433,7 +46877,9 @@
1446909808,1446909815,A2
1446909816,1446909819,AF
1446909820,1446909827,IQ
-1446909828,1446909999,A2
+1446909828,1446909967,A2
+1446909968,1446909971,LY
+1446909972,1446909999,A2
1446910000,1446910003,AF
1446910004,1446910019,A2
1446910020,1446910023,IQ
@@ -46489,8 +46935,8 @@
1446910728,1446910731,AF
1446910732,1446910739,A2
1446910740,1446910747,AF
-1446910748,1446910771,A2
-1446910772,1446910775,AF
+1446910748,1446910767,A2
+1446910768,1446910775,AF
1446910776,1446910791,A2
1446910792,1446910795,LY
1446910796,1446910799,A2
@@ -46539,9 +46985,7 @@
1446911144,1446911147,TD
1446911148,1446911163,A2
1446911164,1446911171,IQ
-1446911172,1446911183,A2
-1446911184,1446911187,AF
-1446911188,1446911207,A2
+1446911172,1446911207,A2
1446911208,1446911215,IQ
1446911216,1446911223,A2
1446911224,1446911227,AF
@@ -46799,7 +47243,10 @@
1450090496,1450106879,RU
1450106880,1450115071,SK
1450115072,1450123263,RU
-1450123264,1450131455,AT
+1450123264,1450125231,AT
+1450125232,1450125239,DE
+1450125240,1450125247,US
+1450125248,1450131455,AT
1450131456,1450139647,UA
1450139648,1450147839,PL
1450147840,1450151935,CH
@@ -46880,8 +47327,7 @@
1466592256,1466592511,FR
1466592512,1466592767,GB
1466592768,1466592895,FR
-1466592896,1466593023,DE
-1466593024,1466593279,GB
+1466592896,1466593279,GB
1466593280,1466604799,DE
1466604800,1466605055,ES
1466605056,1466606847,DE
@@ -46921,8 +47367,7 @@
1467367616,1467367647,SE
1467367648,1467367679,DE
1467367680,1467367695,IT
-1467367696,1467367807,DE
-1467367808,1467367871,CZ
+1467367696,1467367871,DE
1467367872,1467367903,SE
1467367904,1467367935,DE
1467367936,1467368191,SI
@@ -46931,9 +47376,7 @@
1467368448,1467368703,DK
1467368704,1467369519,DE
1467369520,1467369535,RU
-1467369536,1467369599,DE
-1467369600,1467369663,IT
-1467369664,1467369759,DE
+1467369536,1467369759,DE
1467369760,1467369791,HR
1467369792,1467369855,SE
1467369856,1467369871,RU
@@ -47056,7 +47499,7 @@
1475131392,1475133439,RU
1475133440,1475135487,CZ
1475135488,1475137535,CH
-1475137536,1475139583,IR
+1475137536,1475139583,GB
1475139584,1475141631,ES
1475141632,1475143679,FI
1475143680,1475145727,JO
@@ -47136,9 +47579,7 @@
1475223552,1475229695,NO
1475229696,1475229759,SE
1475229760,1475229951,NO
-1475229952,1475230175,SE
-1475230176,1475230191,NO
-1475230192,1475230207,SE
+1475229952,1475230207,SE
1475230208,1475233791,NO
1475233792,1475234303,GB
1475234304,1475234559,IE
@@ -47150,9 +47591,7 @@
1475242240,1475243775,FR
1475243776,1475244031,MC
1475244032,1475244287,DE
-1475244288,1475244311,SD
-1475244312,1475244319,DE
-1475244320,1475244543,SD
+1475244288,1475244543,SD
1475244544,1475245183,DE
1475245184,1475245311,SD
1475245312,1475246079,DE
@@ -47249,8 +47688,8 @@
1475592192,1475608575,GB
1475608576,1475624959,RU
1475624960,1475627519,JE
-1475627520,1475627662,GB
-1475627663,1475627663,JE
+1475627520,1475627655,GB
+1475627656,1475627663,JE
1475627664,1475627688,GB
1475627689,1475627695,JE
1475627696,1475627775,GB
@@ -47271,13 +47710,9 @@
1475636432,1475636447,JE
1475636448,1475636479,GB
1475636480,1475636735,JE
-1475636736,1475637479,GB
-1475637480,1475637487,JE
-1475637488,1475637503,GB
+1475636736,1475637503,GB
1475637504,1475638783,JE
-1475638784,1475639039,GB
-1475639040,1475639047,JE
-1475639048,1475639182,GB
+1475638784,1475639182,GB
1475639183,1475639183,JE
1475639184,1475639216,GB
1475639217,1475639223,JE
@@ -47292,9 +47727,7 @@
1475639528,1475639543,JE
1475639544,1475639595,GB
1475639596,1475639599,JE
-1475639600,1475639775,GB
-1475639776,1475639783,JE
-1475639784,1475639807,GB
+1475639600,1475639807,GB
1475639808,1475641343,JE
1475641344,1475657727,UA
1475657728,1475674111,SK
@@ -47303,11 +47736,13 @@
1475706880,1475723263,RU
1475723264,1475725311,CY
1475725312,1475725951,RU
-1475725952,1475726463,GB
+1475725952,1475726207,GB
+1475726208,1475726335,RU
+1475726336,1475726463,GB
1475726464,1475726527,RU
1475726528,1475726591,GB
-1475726592,1475726719,RU
-1475726720,1475727103,GB
+1475726592,1475726847,RU
+1475726848,1475727103,GB
1475727104,1475727167,RU
1475727168,1475727343,GB
1475727344,1475727359,RU
@@ -47324,7 +47759,33 @@
1475729152,1475729215,AT
1475729216,1475729407,GB
1475729408,1475731455,UA
-1475731456,1475739647,GB
+1475731456,1475732479,GB
+1475732480,1475732991,RU
+1475732992,1475734783,GB
+1475734784,1475734911,UA
+1475734912,1475735295,GB
+1475735296,1475735551,UA
+1475735552,1475735807,US
+1475735808,1475735999,RU
+1475736000,1475736063,GB
+1475736064,1475736127,LV
+1475736128,1475736191,EE
+1475736192,1475736255,GB
+1475736256,1475736319,HU
+1475736320,1475736447,RU
+1475736448,1475736575,UA
+1475736576,1475736831,RU
+1475736832,1475736959,GB
+1475736960,1475737023,FR
+1475737024,1475737087,PL
+1475737088,1475737151,NL
+1475737152,1475737215,CZ
+1475737216,1475737279,DE
+1475737280,1475737343,AT
+1475737344,1475737599,UA
+1475737600,1475737855,FI
+1475737856,1475738111,SE
+1475738112,1475739647,RU
1475739648,1475756031,BG
1475756032,1475772415,GB
1475772416,1475788799,LV
@@ -47498,7 +47959,7 @@
1481984128,1481984255,PA
1481984256,1481984383,NL
1481984384,1481984511,GI
-1481984512,1481984639,SC
+1481984512,1481984639,CY
1481984640,1481985023,NL
1481985024,1481985279,MT
1481985280,1481987327,NL
@@ -47610,11 +48071,9 @@
1486317568,1486320383,RU
1486320384,1486320639,US
1486320640,1486321663,RU
-1486321664,1486323711,EU
1486323712,1486325759,GB
1486325760,1486327807,PL
1486327808,1486329855,CH
-1486329856,1486331903,FR
1486331904,1486333951,NO
1486333952,1486335999,SE
1486336000,1486338047,KZ
@@ -47808,10 +48267,10 @@
1489731584,1489764351,BG
1489764352,1489797119,RU
1489797120,1489829887,KZ
-1489829888,1489855503,DE
+1489829888,1489855495,DE
+1489855496,1489855503,CH
1489855504,1489855519,RU
-1489855520,1489855535,PL
-1489855536,1489855543,DE
+1489855520,1489855543,DE
1489855544,1489855551,PL
1489855552,1489855583,DE
1489855584,1489855615,RU
@@ -47825,9 +48284,9 @@
1489993728,1490026495,LU
1490026496,1490028543,US
1490028544,1490029055,UA
-1490029056,1490041087,NL
-1490041088,1490041343,UA
-1490041344,1490042879,NL
+1490029056,1490040855,NL
+1490040856,1490040863,UA
+1490040864,1490042879,NL
1490042880,1490049879,CZ
1490049880,1490049887,AT
1490049888,1490049919,CZ
@@ -48095,12 +48554,16 @@
1495236608,1495237247,AT
1495237248,1495237255,EU
1495237256,1495237271,AT
-1495237272,1495237375,EU
+1495237272,1495237311,EU
+1495237312,1495237319,AT
+1495237320,1495237375,EU
1495237376,1495237711,AT
1495237712,1495237727,NL
1495237728,1495237731,AT
-1495237732,1495237759,EU
-1495237760,1495237775,AT
+1495237732,1495237739,EU
+1495237740,1495237743,AT
+1495237744,1495237751,EU
+1495237752,1495237775,AT
1495237776,1495237887,EU
1495237888,1495238207,AT
1495238208,1495238223,EU
@@ -48121,7 +48584,25 @@
1495242144,1495242151,ES
1495242152,1495242159,IT
1495242160,1495242167,PL
-1495242168,1495242751,FR
+1495242168,1495242175,FR
+1495242176,1495242183,GB
+1495242184,1495242191,IE
+1495242192,1495242199,DK
+1495242200,1495242207,CZ
+1495242208,1495242215,GR
+1495242216,1495242223,PT
+1495242224,1495242231,RO
+1495242232,1495242367,FR
+1495242368,1495242375,HU
+1495242376,1495242383,BG
+1495242384,1495242391,SK
+1495242392,1495242399,LT
+1495242400,1495242407,LV
+1495242408,1495242415,SI
+1495242416,1495242423,EE
+1495242424,1495242431,FI
+1495242432,1495242439,SE
+1495242440,1495242751,FR
1495242752,1495244799,MK
1495244800,1495246847,CZ
1495246848,1495248895,IE
@@ -48162,7 +48643,7 @@
1495891968,1495927295,RO
1495927296,1495927551,AE
1495927552,1495937023,RO
-1495937024,1495937535,ES
+1495937024,1495937535,SE
1495937536,1495990271,RO
1495990272,1495994367,GB
1495994368,1496078335,RO
@@ -48195,9 +48676,7 @@
1500078080,1500086271,GB
1500086272,1500094463,RU
1500094464,1500102655,AT
-1500102656,1500104063,NL
-1500104064,1500104071,DE
-1500104072,1500106527,NL
+1500102656,1500106527,NL
1500106528,1500106559,DE
1500106560,1500107415,NL
1500107416,1500107423,DE
@@ -48209,8 +48688,8 @@
1500107944,1500107951,DE
1500107952,1500107999,NL
1500108000,1500108007,BE
-1500108008,1500108095,NL
-1500108096,1500108287,DE
+1500108008,1500108159,NL
+1500108160,1500108287,DE
1500108288,1500108319,NL
1500108320,1500108351,DE
1500108352,1500108367,NL
@@ -48350,9 +48829,15 @@
1502691680,1502691711,SE
1502691712,1502702835,GB
1502702836,1502702839,IE
-1502702840,1502706623,GB
+1502702840,1502703103,GB
+1502703104,1502703615,SE
+1502703616,1502706623,GB
1502706624,1502706687,CY
1502706688,1502707711,GB
+1502707712,1502715903,RU
+1502715904,1502717951,IT
+1502717952,1502719999,GB
+1502720000,1502722047,CH
1502724096,1502740479,GB
1502740480,1502756863,NL
1502756864,1502773247,UZ
@@ -48519,8 +49004,7 @@
1503898352,1503898359,CH
1503898360,1503898415,DE
1503898416,1503898423,BE
-1503898424,1503898431,CH
-1503898432,1503898503,DE
+1503898424,1503898503,DE
1503898504,1503898511,GR
1503898512,1503898567,DE
1503898568,1503898575,NL
@@ -48529,9 +49013,7 @@
1503898608,1503898615,GR
1503898616,1503898631,DE
1503898632,1503898647,GR
-1503898648,1503898679,DE
-1503898680,1503898687,IT
-1503898688,1503898791,DE
+1503898648,1503898791,DE
1503898792,1503898799,US
1503898800,1503898815,DE
1503898816,1503898831,GB
@@ -48571,7 +49053,14 @@
1503899352,1503899367,GR
1503899368,1503899399,DE
1503899400,1503899407,CH
-1503899408,1503908351,DE
+1503899408,1503899423,DE
+1503899424,1503899431,IT
+1503899432,1503899439,GR
+1503899440,1503899463,DE
+1503899464,1503899479,BR
+1503899480,1503899495,DE
+1503899496,1503899503,IT
+1503899504,1503908351,DE
1503908352,1503909375,IT
1503909376,1503920127,DE
1503920128,1503985663,HR
@@ -48654,8 +49143,8 @@
1505321664,1505321823,DE
1505321824,1505321831,AT
1505321832,1505321983,DE
-1505321984,1505322287,AT
-1505322288,1505322415,DE
+1505321984,1505322303,AT
+1505322304,1505322415,DE
1505322416,1505322895,AT
1505322896,1505324335,DE
1505324336,1505324367,AT
@@ -48676,11 +49165,15 @@
1505333624,1505333631,GB
1505333632,1505333887,IE
1505333888,1505333951,GB
-1505333952,1505336063,IE
+1505333952,1505335871,IE
+1505335872,1505335911,GB
+1505335912,1505336063,IE
1505336064,1505336071,GB
1505336072,1505336576,IE
1505336577,1505336639,GB
-1505336640,1505336823,IE
+1505336640,1505336655,IE
+1505336656,1505336663,GB
+1505336664,1505336823,IE
1505336824,1505336863,GB
1505336864,1505336864,IE
1505336865,1505336879,GB
@@ -48841,19 +49334,26 @@
1506418704,1506418719,CA
1506418720,1506418975,DE
1506418976,1506418983,CA
-1506418984,1506422655,DE
+1506418984,1506422079,DE
+1506422080,1506422111,CY
+1506422112,1506422142,CA
+1506422143,1506422655,DE
1506422656,1506422687,CY
1506422688,1506422703,CA
-1506422704,1506422711,GB
-1506422712,1506422719,DE
+1506422704,1506422719,GB
1506422720,1506422751,US
-1506422752,1506427663,DE
+1506422752,1506427183,DE
+1506427184,1506427199,CA
+1506427200,1506427663,DE
1506427664,1506427679,GB
-1506427680,1506428223,DE
+1506427680,1506427743,DE
+1506427744,1506427759,CA
+1506427760,1506428223,DE
1506428224,1506428239,US
1506428240,1506436863,DE
1506436864,1506436879,FR
-1506436880,1506437119,DE
+1506436880,1506436883,GB
+1506436884,1506437119,DE
1506437120,1506437503,US
1506437504,1506437551,DE
1506437552,1506437567,BG
@@ -48975,14 +49475,12 @@
1506445824,1506446143,FR
1506446144,1506446151,GB
1506446152,1506446335,FR
-1506446336,1506446599,NL
-1506446600,1506446623,GB
-1506446624,1506446719,NL
+1506446336,1506446719,NL
1506446720,1506446735,GB
1506446736,1506447359,NL
1506447360,1506447423,IT
-1506447424,1506447455,GB
-1506447456,1506448255,IT
+1506447424,1506447463,GB
+1506447464,1506448255,IT
1506448256,1506448319,GB
1506448320,1506448383,IT
1506448384,1506448639,AT
@@ -49092,8 +49590,7 @@
1506462528,1506462583,GB
1506462584,1506462599,FR
1506462600,1506462607,GB
-1506462608,1506462623,A2
-1506462624,1506462719,FR
+1506462608,1506462719,FR
1506462720,1506463231,IT
1506463232,1506463487,SE
1506463488,1506463671,DE
@@ -49110,7 +49607,11 @@
1506466632,1506467071,GB
1506467072,1506467327,DE
1506467328,1506467583,GB
-1506467584,1506468351,IT
+1506467584,1506467591,IT
+1506467592,1506467615,GB
+1506467616,1506467647,IT
+1506467648,1506467839,GB
+1506467840,1506468351,IT
1506468352,1506468607,GB
1506468608,1506468863,TZ
1506468864,1506470143,IT
@@ -49134,8 +49635,8 @@
1506474256,1506474495,IT
1506474496,1506474751,FR
1506474752,1506475519,IT
-1506475520,1506475559,AT
-1506475560,1506475775,GB
+1506475520,1506475567,AT
+1506475568,1506475775,GB
1506475776,1506476031,DE
1506476032,1506508799,KW
1506508800,1506541567,CZ
@@ -49152,8 +49653,7 @@
1506743168,1506743183,DE
1506743184,1506743199,FR
1506743200,1506743215,IE
-1506743216,1506743232,GB
-1506743233,1506744319,SE
+1506743216,1506744319,SE
1506744320,1506744383,NL
1506744384,1506744391,GB
1506744392,1506746367,NL
@@ -49183,8 +49683,7 @@
1506772148,1506772176,TR
1506772177,1506772323,NL
1506772324,1506772325,IR
-1506772326,1506772326,RO
-1506772327,1506772361,NL
+1506772326,1506772361,NL
1506772362,1506772364,IR
1506772365,1506772938,NL
1506772939,1506772939,IR
@@ -49256,7 +49755,9 @@
1507713024,1507717119,RU
1507717120,1507717631,SE
1507717632,1507718911,NO
-1507718912,1507721215,SE
+1507718912,1507720191,SE
+1507720192,1507720447,NO
+1507720448,1507721215,SE
1507721216,1507753983,GB
1507753984,1507819519,RU
1507819520,1507852287,HU
@@ -49321,9 +49822,7 @@
1508787200,1508787455,ES
1508787456,1508788031,DE
1508788032,1508788063,BE
-1508788064,1508792063,DE
-1508792064,1508792318,GB
-1508792319,1508802559,DE
+1508788064,1508802559,DE
1508802560,1508804783,GB
1508804784,1508804791,DE
1508804792,1508805119,GB
@@ -49364,9 +49863,7 @@
1509467840,1509467871,PL
1509467872,1509469055,NL
1509469056,1509469183,PL
-1509469184,1509469439,NL
-1509469440,1509469567,SE
-1509469568,1509469887,NL
+1509469184,1509469887,NL
1509469888,1509469919,MY
1509469920,1509470207,NL
1509470208,1509478399,RU
@@ -49400,9 +49897,7 @@
1509580800,1509584895,CZ
1509584896,1509588479,NO
1509588480,1509588607,GB
-1509588608,1509588751,NO
-1509588752,1509588767,GB
-1509588768,1509588991,NO
+1509588608,1509588991,NO
1509588992,1509593087,DE
1509593088,1509601279,RU
1509601280,1509605375,NL
@@ -49466,7 +49961,9 @@
1518370816,1518403583,NL
1518403584,1518452735,SE
1518452736,1518460927,AT
-1518460928,1518501887,SE
+1518460928,1518479359,SE
+1518479360,1518481407,EE
+1518481408,1518501887,SE
1518501888,1518503935,EE
1518503936,1518508799,LT
1518508800,1518510079,SE
@@ -49723,7 +50220,6 @@
1533431808,1533433855,IE
1533433856,1533435903,DK
1533435904,1533437951,CZ
-1533437952,1533439999,RU
1533440000,1533441519,PL
1533441520,1533441535,CH
1533441536,1533442047,PL
@@ -49788,9 +50284,7 @@
1533542400,1534066687,GB
1534066688,1534129151,AT
1534129152,1534129407,A2
-1534129408,1534202591,AT
-1534202592,1534202595,ES
-1534202596,1534328831,AT
+1534129408,1534328831,AT
1534328832,1534459903,ES
1534459904,1534482091,AT
1534482092,1534482095,GB
@@ -49909,7 +50403,8 @@
1534715368,1534715371,FR
1534715372,1534715375,CH
1534715376,1534715391,ES
-1534715392,1534715407,PL
+1534715392,1534715399,PL
+1534715400,1534715407,FR
1534715408,1534715411,GB
1534715412,1534715415,FI
1534715416,1534715419,DE
@@ -49944,7 +50439,7 @@
1534715784,1534715791,BE
1534715792,1534715807,ES
1534715808,1534715875,FR
-1534715876,1534715879,NL
+1534715876,1534715879,GB
1534715880,1534715883,PT
1534715884,1534715887,PL
1534715888,1534715919,FR
@@ -49965,8 +50460,10 @@
1534716224,1534716239,FR
1534716240,1534716255,GB
1534716256,1534716319,FR
-1534716320,1534716359,PL
-1534716360,1534716363,CZ
+1534716320,1534716351,PL
+1534716352,1534716355,FR
+1534716356,1534716359,PL
+1534716360,1534716363,FR
1534716364,1534716367,GB
1534716368,1534716375,BE
1534716376,1534716379,CH
@@ -49979,8 +50476,8 @@
1534716448,1534716479,FR
1534716480,1534716495,ES
1534716496,1534716575,FR
-1534716576,1534716607,PL
-1534716608,1534716639,FR
+1534716576,1534716591,PL
+1534716592,1534716639,FR
1534716640,1534716647,BE
1534716648,1534716655,FR
1534716656,1534716663,IE
@@ -50010,7 +50507,9 @@
1534717008,1534717011,PL
1534717012,1534717019,FR
1534717020,1534717023,DE
-1534717024,1534717055,PL
+1534717024,1534717039,GB
+1534717040,1534717047,PL
+1534717048,1534717055,FR
1534717056,1534717071,GB
1534717072,1534717103,FR
1534717104,1534717119,PL
@@ -50019,7 +50518,9 @@
1534717140,1534717143,BE
1534717144,1534717147,FR
1534717148,1534717151,IT
-1534717152,1534717247,FR
+1534717152,1534717215,FR
+1534717216,1534717219,ES
+1534717220,1534717247,FR
1534717248,1534717251,CZ
1534717252,1534717255,NL
1534717256,1534717263,FR
@@ -50074,10 +50575,9 @@
1534717920,1534717923,PL
1534717924,1534717927,ES
1534717928,1534717931,DE
-1534717932,1534717935,FR
-1534717936,1534717951,IT
+1534717932,1534717951,FR
1534717952,1534717955,DE
-1534717956,1534717959,BE
+1534717956,1534717959,FR
1534717960,1534717963,PT
1534717964,1534717967,CH
1534717968,1534717983,IT
@@ -50106,12 +50606,13 @@
1534718416,1534718419,CZ
1534718420,1534718423,GB
1534718424,1534718431,ES
-1534718432,1534718447,PL
+1534718432,1534718435,GB
+1534718436,1534718439,DE
+1534718440,1534718447,ES
1534718448,1534718463,FR
1534718464,1534718467,DE
1534718468,1534718471,PT
-1534718472,1534718479,FR
-1534718480,1534718487,PL
+1534718472,1534718487,PL
1534718488,1534718495,DE
1534718496,1534718531,FR
1534718532,1534718535,PL
@@ -50120,15 +50621,19 @@
1534718544,1534718559,FR
1534718560,1534718575,BE
1534718576,1534718591,GB
-1534718592,1534718687,FR
+1534718592,1534718623,FR
+1534718624,1534718631,PL
+1534718632,1534718687,FR
1534718688,1534718703,PL
1534718704,1534718711,FR
1534718712,1534718719,ES
1534718720,1534718735,GB
-1534718736,1534718751,FR
-1534718752,1534718767,PL
-1534718768,1534718799,FR
-1534718800,1534718815,ES
+1534718736,1534718739,NL
+1534718740,1534718759,FR
+1534718760,1534718763,PL
+1534718764,1534718767,IE
+1534718768,1534718783,FR
+1534718784,1534718815,ES
1534718816,1534718831,GB
1534718832,1534718847,FR
1534718848,1534718911,BE
@@ -50149,8 +50654,7 @@
1534719392,1534719395,CH
1534719396,1534719399,PT
1534719400,1534719403,IT
-1534719404,1534719423,FR
-1534719424,1534719439,DE
+1534719404,1534719439,FR
1534719440,1534719459,PL
1534719460,1534719463,FR
1534719464,1534719471,PL
@@ -50165,7 +50669,9 @@
1534719696,1534719699,IT
1534719700,1534719703,DE
1534719704,1534719711,GB
-1534719712,1534719759,FR
+1534719712,1534719747,FR
+1534719748,1534719751,PL
+1534719752,1534719759,FR
1534719760,1534719775,IT
1534719776,1534719783,PL
1534719784,1534719787,FR
@@ -50211,7 +50717,9 @@
1534720400,1534720403,LT
1534720404,1534720411,GB
1534720412,1534720415,IE
-1534720416,1534720431,FR
+1534720416,1534720419,ES
+1534720420,1534720423,DE
+1534720424,1534720431,ES
1534720432,1534720435,DE
1534720436,1534720439,FR
1534720440,1534720443,GB
@@ -50267,7 +50775,8 @@
1534721000,1534721003,FI
1534721004,1534721007,GB
1534721008,1534721023,ES
-1534721024,1534721055,FR
+1534721024,1534721031,DE
+1534721032,1534721055,FR
1534721056,1534721063,ES
1534721064,1534721071,FR
1534721072,1534721087,GB
@@ -50308,14 +50817,18 @@
1534721528,1534721531,ES
1534721532,1534721567,FR
1534721568,1534721583,GB
-1534721584,1534721599,FR
-1534721600,1534721619,ES
+1534721584,1534721587,IE
+1534721588,1534721595,FR
+1534721596,1534721619,ES
1534721620,1534721627,PL
1534721628,1534721631,NL
1534721632,1534721647,ES
1534721648,1534721663,FR
1534721664,1534721679,ES
-1534721680,1534721743,FR
+1534721680,1534721695,FR
+1534721696,1534721703,PL
+1534721704,1534721711,DE
+1534721712,1534721743,FR
1534721744,1534721747,PL
1534721748,1534721751,GB
1534721752,1534721755,DE
@@ -50338,7 +50851,9 @@
1534721968,1534721971,DE
1534721972,1534721975,PL
1534721976,1534721979,ES
-1534721980,1534722007,PL
+1534721980,1534721983,PL
+1534721984,1534721999,FR
+1534722000,1534722007,PL
1534722008,1534722011,PT
1534722012,1534722015,ES
1534722016,1534722039,FR
@@ -50399,7 +50914,9 @@
1535635456,1535639551,AZ
1535639552,1535672319,GB
1535672320,1535705087,DE
-1535705088,1535720447,CH
+1535705088,1535708671,CH
+1535708672,1535709694,DE
+1535709695,1535720447,CH
1535720448,1535720575,DE
1535720576,1535720703,CH
1535720704,1535720831,DE
@@ -50490,6 +51007,10 @@
1536262144,1536278527,PL
1536278528,1536294911,UA
1536294912,1536311295,RU
+1536311296,1536319487,EE
+1536319488,1536321535,ES
+1536321536,1536325631,GB
+1536325632,1536327679,CZ
1536327680,1536344063,HU
1536344064,1536360447,PL
1536360448,1536376831,RU
@@ -50705,7 +51226,9 @@
1539227648,1539229695,FI
1539229696,1539231743,DE
1539231744,1539233791,BE
-1539233792,1539235839,LU
+1539233792,1539234303,LU
+1539234304,1539234559,IE
+1539234560,1539235839,LU
1539235840,1539237887,DE
1539237888,1539239935,RU
1539239936,1539244031,DE
@@ -51086,6 +51609,7 @@
1539593216,1539594239,RU
1539594240,1539598335,UA
1539598336,1539599359,NL
+1539599360,1539600383,PL
1539600384,1539601407,HU
1539601408,1539602431,GB
1539602432,1539603455,UA
@@ -51186,7 +51710,6 @@
1539706624,1539707135,PL
1539707136,1539707391,LT
1539707392,1539707647,GB
-1539707648,1539707903,RO
1539707904,1539708159,UA
1539708160,1539708415,DE
1539708416,1539708671,GB
@@ -51346,6 +51869,7 @@
1539750400,1539750655,PL
1539750656,1539750911,DE
1539750912,1539751167,UA
+1539751168,1539751423,AT
1539751424,1539751679,SI
1539751680,1539751935,FR
1539751936,1539752191,DE
@@ -51572,6 +52096,7 @@
1539812096,1539812351,RU
1539812352,1539812607,CH
1539812608,1539812863,IT
+1539812864,1539813119,RU
1539813120,1539813375,AT
1539813376,1539813631,PL
1539813632,1539813887,NL
@@ -51666,7 +52191,6 @@
1539857408,1539858431,PL
1539858432,1539859455,RO
1539859456,1539860479,DE
-1539860480,1539861503,UA
1539861504,1539862527,DE
1539862528,1539863551,UA
1539863552,1539864575,ES
@@ -51743,7 +52267,6 @@
1539947520,1539948543,UA
1539948544,1539949567,RO
1539949568,1539950591,MD
-1539950592,1539951103,KZ
1539951104,1539951615,UA
1539951616,1539953663,RU
1539953664,1539954687,UA
@@ -51998,6 +52521,8 @@
1540248576,1540249087,GB
1540249088,1540249599,PL
1540249600,1540250111,KZ
+1540250112,1540250367,PL
+1540250368,1540250623,CZ
1540250624,1540251135,RU
1540251136,1540251647,GB
1540251648,1540252159,PL
@@ -52195,6 +52720,7 @@
1540361472,1540361727,DE
1540361728,1540361983,IT
1540361984,1540362239,EE
+1540362240,1540362495,RU
1540362496,1540363007,DE
1540363008,1540363263,FR
1540363264,1540363519,RU
@@ -52476,7 +53002,7 @@
1540440064,1540440319,UA
1540440320,1540440575,RU
1540440576,1540440831,MD
-1540440832,1540441087,FR
+1540440832,1540441087,GB
1540441088,1540441343,PL
1540441344,1540441855,RU
1540441856,1540442111,GB
@@ -52554,13 +53080,14 @@
1540462592,1540463103,PL
1540463104,1540463359,FR
1540463360,1540463615,PL
+1540463616,1540463871,DK
1540463872,1540464127,UA
1540464128,1540464383,CH
1540464384,1540464895,DE
1540464896,1540465407,GB
1540465408,1540465663,ES
1540465664,1540465919,NL
-1540465920,1540466175,UA
+1540465920,1540466175,RU
1540466176,1540466431,DK
1540466432,1540466687,RU
1540466688,1540466943,NL
@@ -52637,7 +53164,7 @@
1540487168,1540487423,PS
1540487424,1540487679,UA
1540487680,1540487935,DE
-1540487936,1540488447,GB
+1540488192,1540488447,GB
1540488448,1540488703,SA
1540488704,1540488959,DE
1540488960,1540489215,RO
@@ -52860,12 +53387,10 @@
1540651776,1540652031,RU
1540652032,1540652543,UA
1540652544,1540652799,TR
-1540652800,1540653055,EU
1540653056,1540653311,FR
1540653312,1540653567,DK
1540653568,1540653823,DE
1540653824,1540654079,GB
-1540654080,1540654335,RS
1540654336,1540654591,RU
1540654592,1540654847,SI
1540654848,1540655103,RU
@@ -52885,7 +53410,6 @@
1540659456,1540659967,UA
1540659968,1540660223,PL
1540660480,1540660735,FR
-1540660736,1540660991,UA
1540660992,1540661247,RO
1540661248,1540661503,GB
1540661504,1540662015,RO
@@ -52930,7 +53454,7 @@
1540673280,1540673535,SE
1540673536,1540673791,SI
1540673792,1540674047,SE
-1540674048,1540674303,GB
+1540674048,1540674303,NL
1540674304,1540674559,FR
1540674560,1540674815,GB
1540674816,1540675071,GE
@@ -53516,7 +54040,7 @@
1540940800,1540941055,FR
1540941056,1540941311,CH
1540941312,1540941567,AT
-1540941568,1540941823,UA
+1540941568,1540942079,UA
1540942080,1540942335,RO
1540942336,1540942591,FR
1540942592,1540942847,DE
@@ -53575,7 +54099,7 @@
1540966912,1540967935,RU
1540967936,1540968447,UA
1540968448,1540969471,RO
-1540969472,1540969983,GB
+1540969472,1540969983,NL
1540969984,1540970495,DE
1540970496,1540971007,IE
1540971008,1540971519,UA
@@ -54395,6 +54919,7 @@
1541384704,1541384959,RU
1541384960,1541385215,PL
1541385216,1541385471,NL
+1541385472,1541385727,SK
1541385728,1541385983,SI
1541385984,1541386239,PL
1541386240,1541386495,RU
@@ -54440,7 +54965,6 @@
1541396480,1541396735,UA
1541396736,1541396991,RU
1541396992,1541397247,GB
-1541397248,1541397503,FR
1541397504,1541397759,NL
1541397760,1541398015,PL
1541398016,1541398271,HU
@@ -54770,7 +55294,7 @@
1541622528,1541622783,NL
1541622784,1541623295,PL
1541623296,1541623551,GB
-1541623552,1541623679,RU
+1541623552,1541623807,RU
1541623808,1541624831,PL
1541624832,1541625855,RU
1541625856,1541626367,PL
@@ -54943,6 +55467,7 @@
1541728000,1541728255,UA
1541728256,1541729023,GB
1541729024,1541729279,DE
+1541729280,1541729535,UA
1541729536,1541729791,PL
1541729792,1541730303,RU
1541730304,1541730815,ES
@@ -55039,7 +55564,7 @@
1541779968,1541780479,DE
1541780480,1541780735,ES
1541780736,1541780991,GB
-1541780992,1541781247,RO
+1541780992,1541781503,RO
1541781504,1541781759,TR
1541781760,1541782015,RU
1541782016,1541782271,RO
@@ -55055,6 +55580,7 @@
1541787648,1541788159,RU
1541788160,1541788415,UA
1541788416,1541788671,RU
+1541788672,1541789183,PL
1541789184,1541789695,IR
1541789696,1541790719,UA
1541790720,1541790975,SA
@@ -55074,8 +55600,9 @@
1541795584,1541795839,ES
1541795840,1541796863,UA
1541796864,1541797375,RU
-1541797376,1541797887,GB
+1541797376,1541797887,NL
1541797888,1541798143,UA
+1541798144,1541798399,PL
1541798400,1541798911,RO
1541798912,1541799935,CZ
1541799936,1541800447,FR
@@ -55239,6 +55766,105 @@
1541879808,1541880831,UZ
1541880832,1541881343,PL
1541881344,1541881599,IT
+1541881600,1541881855,SE
+1541881856,1541882879,RU
+1541882880,1541883135,LV
+1541883136,1541883391,UA
+1541883392,1541884927,PL
+1541884928,1541885951,LT
+1541885952,1541886975,PL
+1541886976,1541887999,UA
+1541888000,1541888255,RS
+1541888256,1541888511,RU
+1541888512,1541889023,GB
+1541889024,1541889535,PL
+1541889536,1541890303,RU
+1541890304,1541890559,DE
+1541890560,1541891071,UA
+1541891072,1541893119,PL
+1541893120,1541893631,BE
+1541893632,1541894143,PL
+1541894144,1541895167,RU
+1541895168,1541897727,PL
+1541897728,1541897983,RU
+1541897984,1541898239,UA
+1541898240,1541900799,RU
+1541900800,1541901055,RO
+1541901056,1541901311,FR
+1541901312,1541901567,PL
+1541901568,1541901823,RU
+1541901824,1541902335,UA
+1541902336,1541902847,GB
+1541902848,1541903103,RU
+1541903104,1541903359,DK
+1541903360,1541904383,UA
+1541904384,1541904639,PL
+1541904640,1541904895,SE
+1541904896,1541905407,GB
+1541905408,1541905663,RU
+1541905664,1541906431,RO
+1541906432,1541906687,UA
+1541906688,1541907455,RU
+1541907456,1541908479,IT
+1541908480,1541908991,PL
+1541908992,1541909247,UA
+1541909248,1541909503,CZ
+1541909504,1541910527,NL
+1541910528,1541911039,RU
+1541911040,1541911295,PL
+1541911296,1541911551,IT
+1541911552,1541912575,RU
+1541912576,1541912831,NL
+1541912832,1541913087,UA
+1541913088,1541914623,RU
+1541914624,1541915647,IL
+1541915648,1541916671,RU
+1541916672,1541917695,RO
+1541917696,1541917951,CH
+1541917952,1541918207,PL
+1541918208,1541918463,UA
+1541918464,1541919743,RO
+1541919744,1541919999,DK
+1541920000,1541920767,RU
+1541920768,1541921279,PT
+1541921280,1541921791,RU
+1541921792,1541922047,DE
+1541922048,1541922303,PL
+1541922304,1541922559,RU
+1541922560,1541923839,RO
+1541923840,1541924095,FR
+1541924096,1541924351,UA
+1541924352,1541924863,PL
+1541924864,1541925119,RO
+1541925120,1541926911,RU
+1541926912,1541927167,UA
+1541927168,1541927679,PL
+1541927680,1541927935,DE
+1541927936,1541929983,PL
+1541929984,1541931007,RU
+1541931008,1541932031,UA
+1541932032,1541932543,PL
+1541932544,1541935103,RU
+1541935104,1541936383,RO
+1541936384,1541936639,UA
+1541936640,1541936895,DE
+1541936896,1541937151,FR
+1541937152,1541937663,NL
+1541937664,1541937919,GE
+1541937920,1541938175,PL
+1541938176,1541939199,UA
+1541939200,1541939967,RU
+1541939968,1541940223,ES
+1541940224,1541940479,GB
+1541940480,1541940735,CH
+1541940736,1541940991,PL
+1541940992,1541941247,RU
+1541941248,1541942271,FR
+1541942272,1541944831,PL
+1541944832,1541945087,DE
+1541945088,1541945855,RO
+1541945856,1541946111,PL
+1541946112,1541946879,SE
1543503872,1545601023,GB
1545601024,1545673167,SE
1545673168,1545673175,FI
@@ -55395,7 +56021,9 @@
1546878976,1546895359,DE
1546895360,1546911743,IE
1546911744,1546928127,SK
-1546928128,1546944511,GB
+1546928128,1546929407,GB
+1546929408,1546929415,A2
+1546929416,1546944511,GB
1546944512,1546960895,UA
1546960896,1546977279,HU
1546977280,1546993663,MK
@@ -55439,7 +56067,7 @@
1547522048,1547526143,CZ
1547526144,1547534335,HU
1547534336,1547538431,FR
-1547538432,1547542527,DE
+1547538432,1547542527,EU
1547542528,1547546623,FR
1547546624,1547550719,IR
1547550720,1547554815,IE
@@ -55595,7 +56223,8 @@
1547623736,1547624447,A2
1547624448,1547628543,CZ
1547628544,1547632639,BG
-1547632640,1547636735,TR
+1547632640,1547634687,GB
+1547634688,1547636735,TR
1547636736,1547640831,SI
1547640832,1547644927,PL
1547644928,1547649023,CZ
@@ -55620,7 +56249,11 @@
1548157120,1548157183,DE
1548157184,1548157951,NL
1548157952,1548158207,SE
-1548158208,1548222463,NL
+1548158208,1548158623,NL
+1548158624,1548158639,DE
+1548158640,1548158975,NL
+1548158976,1548159103,DE
+1548159104,1548222463,NL
1548222464,1548746751,DE
1548746752,1549271039,RO
1549271040,1549795327,FR
@@ -55917,22 +56550,24 @@
1566400920,1566400923,NE
1566400924,1566400943,NO
1566400944,1566400955,NE
-1566400956,1566400975,NO
-1566400976,1566400979,GB
+1566400956,1566400967,NO
+1566400968,1566400979,GB
1566400980,1566400983,GE
1566400984,1566400987,NE
1566400988,1566401023,NO
1566401024,1566401055,US
1566401056,1566401087,NO
-1566401088,1566401215,US
-1566401216,1566401279,NO
-1566401280,1566401327,US
-1566401328,1566401399,NO
+1566401088,1566401247,US
+1566401248,1566401279,NO
+1566401280,1566401311,US
+1566401312,1566401399,NO
1566401400,1566401463,US
1566401464,1566401467,NO
-1566401468,1566401503,US
-1566401504,1566401507,NO
-1566401508,1566401535,US
+1566401468,1566401483,US
+1566401484,1566401491,NO
+1566401492,1566401499,US
+1566401500,1566401503,NO
+1566401504,1566401535,US
1566401536,1566401599,IN
1566401600,1566401631,HK
1566401632,1566401663,NO
@@ -55945,7 +56580,7 @@
1566401888,1566401919,US
1566401920,1566401967,NO
1566401968,1566401975,HK
-1566401976,1566401987,NO
+1566401976,1566401987,AU
1566401988,1566401991,HK
1566401992,1566401999,SG
1566402000,1566402003,AU
@@ -55998,7 +56633,9 @@
1566470144,1566470159,IE
1566470160,1566470171,GB
1566470172,1566470239,IE
-1566470240,1566470303,GB
+1566470240,1566470279,GB
+1566470280,1566470283,IE
+1566470284,1566470303,GB
1566470304,1566470351,IE
1566470352,1566470367,GB
1566470368,1566470511,IE
@@ -56007,18 +56644,20 @@
1566470560,1566470563,GB
1566470564,1566470623,IE
1566470624,1566470655,GB
-1566470656,1566470719,IE
-1566470720,1566470727,GB
-1566470728,1566470739,IE
+1566470656,1566470739,IE
1566470740,1566470743,GB
-1566470744,1566470847,IE
-1566470848,1566470879,GB
-1566470880,1566470895,IE
-1566470896,1566470911,GB
-1566470912,1566471051,IE
-1566471052,1566471191,GB
+1566470744,1566470855,IE
+1566470856,1566470859,GB
+1566470860,1566471031,IE
+1566471032,1566471039,GB
+1566471040,1566471051,IE
+1566471052,1566471151,GB
+1566471152,1566471157,IE
+1566471158,1566471191,GB
1566471192,1566471229,IE
-1566471230,1566474239,GB
+1566471230,1566471247,GB
+1566471248,1566471263,IE
+1566471264,1566474239,GB
1566474240,1566476287,DE
1566476288,1566478335,BG
1566478336,1566482431,RU
@@ -56096,7 +56735,9 @@
1567712768,1567713279,DE
1567713280,1567715327,RO
1567715328,1567717375,MD
-1567717376,1567752191,RO
+1567717376,1567750655,RO
+1567750656,1567751167,SE
+1567751168,1567752191,RO
1567752192,1567756287,MD
1567756288,1567775743,RO
1567775744,1567776767,MD
@@ -56104,7 +56745,9 @@
1567830016,1567831039,MD
1567831040,1567840255,RO
1567840256,1567842303,DE
-1567842304,1567883263,RO
+1567842304,1567880191,RO
+1567880192,1567881215,SE
+1567881216,1567883263,RO
1567883264,1567948799,MD
1567948800,1568026623,RO
1568026624,1568030719,MD
@@ -56297,7 +56940,9 @@
1570666192,1570666223,FR
1570666224,1570666227,SE
1570666228,1570666231,NO
-1570666232,1570666367,SE
+1570666232,1570666263,SE
+1570666264,1570666267,US
+1570666268,1570666367,SE
1570666368,1570666383,FR
1570666384,1570666387,SE
1570666388,1570666391,NL
@@ -56338,7 +56983,8 @@
1570667248,1570667263,SE
1570667264,1570667267,ES
1570667268,1570667283,SE
-1570667284,1570667295,ES
+1570667284,1570667287,MT
+1570667288,1570667295,ES
1570667296,1570667327,GB
1570667328,1570667335,SE
1570667336,1570667339,GB
@@ -56358,7 +57004,9 @@
1570667588,1570667591,US
1570667592,1570667599,SE
1570667600,1570667603,DE
-1570667604,1570667711,SE
+1570667604,1570667647,SE
+1570667648,1570667651,US
+1570667652,1570667711,SE
1570667712,1570667727,FR
1570667728,1570667743,NL
1570667744,1570667775,SE
@@ -56384,7 +57032,9 @@
1570668292,1570668351,SE
1570668352,1570668415,NO
1570668416,1570668543,SE
-1570668544,1570701311,RU
+1570668544,1570671983,RU
+1570671984,1570671987,TR
+1570671988,1570701311,RU
1570701312,1570717695,PL
1570717696,1570725887,HR
1570725888,1570734079,DE
@@ -56405,7 +57055,8 @@
1571432448,1571434495,CZ
1571434496,1571435519,UA
1571435520,1571436031,NL
-1571436032,1571438591,RU
+1571436032,1571436287,UA
+1571436288,1571438591,RU
1571438592,1571441663,UA
1571441664,1571442175,KZ
1571442176,1571442687,NL
@@ -56903,9 +57554,7 @@
1578591152,1578591183,FR
1578591184,1578591187,CH
1578591188,1578591195,GB
-1578591196,1578591247,FR
-1578591248,1578591263,PL
-1578591264,1578591279,FR
+1578591196,1578591279,FR
1578591280,1578591287,ES
1578591288,1578591291,DE
1578591292,1578591295,ES
@@ -56942,7 +57591,9 @@
1578591712,1578591743,PL
1578591744,1578591759,ES
1578591760,1578591791,FR
-1578591792,1578591807,PL
+1578591792,1578591795,ES
+1578591796,1578591799,NL
+1578591800,1578591807,PL
1578591808,1578591887,FR
1578591888,1578591891,DE
1578591892,1578591899,FR
@@ -56951,8 +57602,8 @@
1578591920,1578591939,ES
1578591940,1578591951,FR
1578591952,1578591967,PT
-1578591968,1578591983,FR
-1578591984,1578592031,PL
+1578591968,1578591999,FR
+1578592000,1578592031,PL
1578592032,1578592039,PT
1578592040,1578592043,ES
1578592044,1578592047,PL
@@ -56964,7 +57615,7 @@
1578592144,1578592159,NL
1578592160,1578592163,FR
1578592164,1578592171,IT
-1578592172,1578592175,FR
+1578592172,1578592175,ES
1578592176,1578592183,CZ
1578592184,1578592191,PT
1578592192,1578592199,BE
@@ -56982,12 +57633,13 @@
1578592336,1578592351,FR
1578592352,1578592367,PL
1578592368,1578592395,FR
-1578592396,1578592399,ES
+1578592396,1578592399,DE
1578592400,1578592415,GB
1578592416,1578592423,IT
1578592424,1578592431,IE
-1578592432,1578592447,FR
-1578592448,1578592495,PL
+1578592432,1578592483,FR
+1578592484,1578592487,PL
+1578592488,1578592495,BE
1578592496,1578592511,FR
1578592512,1578592515,GB
1578592516,1578592519,PL
@@ -57010,14 +57662,14 @@
1578592752,1578592767,IE
1578592768,1578592783,DE
1578592784,1578592799,FR
-1578592800,1578592807,GB
-1578592808,1578592811,FR
+1578592800,1578592803,IE
+1578592804,1578592811,FR
1578592812,1578592815,PL
1578592816,1578592831,FR
1578592832,1578592847,PL
1578592848,1578592851,BE
1578592852,1578592855,DE
-1578592856,1578592859,CH
+1578592856,1578592859,FR
1578592860,1578592879,PL
1578592880,1578592883,FR
1578592884,1578592891,GB
@@ -57040,7 +57692,9 @@
1578593412,1578593415,FR
1578593416,1578593423,PL
1578593424,1578593439,FR
-1578593440,1578593455,PL
+1578593440,1578593443,IT
+1578593444,1578593447,PL
+1578593448,1578593455,DE
1578593456,1578593471,FR
1578593472,1578593479,GB
1578593480,1578593483,PL
@@ -57082,7 +57736,9 @@
1578593936,1578593943,FR
1578593944,1578593947,IT
1578593948,1578593955,FR
-1578593956,1578593967,PL
+1578593956,1578593959,LT
+1578593960,1578593963,FR
+1578593964,1578593967,ES
1578593968,1578593983,FR
1578593984,1578593999,PL
1578594000,1578594015,FR
@@ -57095,17 +57751,14 @@
1578594064,1578594079,PL
1578594080,1578594087,CH
1578594088,1578594095,CZ
-1578594096,1578594111,FR
-1578594112,1578594127,PL
-1578594128,1578594143,FR
+1578594096,1578594143,FR
1578594144,1578594147,PL
1578594148,1578594151,ES
1578594152,1578594159,IT
1578594160,1578594163,PT
1578594164,1578594167,ES
1578594168,1578594171,DE
-1578594172,1578594191,FR
-1578594192,1578594207,IT
+1578594172,1578594207,FR
1578594208,1578594211,DE
1578594212,1578594239,PL
1578594240,1578594255,FR
@@ -57149,15 +57802,13 @@
1578594712,1578594715,IT
1578594716,1578594751,FR
1578594752,1578594767,ES
-1578594768,1578594771,GB
-1578594772,1578594775,FR
+1578594768,1578594775,GB
1578594776,1578594783,ES
1578594784,1578594799,FR
1578594800,1578594815,DE
1578594816,1578594847,FR
1578594848,1578594863,IT
-1578594864,1578594867,PL
-1578594868,1578594871,BE
+1578594864,1578594871,PL
1578594872,1578595039,FR
1578595040,1578595055,GB
1578595056,1578595103,FR
@@ -57188,7 +57839,7 @@
1578595388,1578595407,PL
1578595408,1578595411,IE
1578595412,1578595419,PL
-1578595420,1578595423,FR
+1578595420,1578595423,IT
1578595424,1578595439,PL
1578595440,1578595447,FR
1578595448,1578595455,ES
@@ -57204,7 +57855,12 @@
1578595548,1578595607,FR
1578595608,1578595611,GB
1578595612,1578595615,ES
-1578595616,1578595647,PL
+1578595616,1578595619,PL
+1578595620,1578595623,BE
+1578595624,1578595635,FR
+1578595636,1578595639,ES
+1578595640,1578595643,DE
+1578595644,1578595647,GB
1578595648,1578595679,FR
1578595680,1578595695,PL
1578595696,1578595711,FR
@@ -57225,7 +57881,9 @@
1578595968,1578595983,IE
1578595984,1578595991,NL
1578595992,1578595995,IT
-1578595996,1578596095,FR
+1578595996,1578596031,FR
+1578596032,1578596063,IT
+1578596064,1578596095,IE
1578596096,1578596099,DE
1578596100,1578596103,GB
1578596104,1578596107,PL
@@ -57270,7 +57928,7 @@
1578610820,1578610823,NL
1578610824,1578610831,DE
1578610832,1578610847,CH
-1578610848,1578610851,GB
+1578610848,1578610851,PL
1578610852,1578610855,IE
1578610856,1578610859,IT
1578610860,1578610863,PL
@@ -57279,7 +57937,8 @@
1578610872,1578610879,PL
1578610880,1578610943,FR
1578610944,1578610975,ES
-1578610976,1578611039,PL
+1578610976,1578611007,PL
+1578611008,1578611039,FR
1578611040,1578611043,ES
1578611044,1578611047,CZ
1578611048,1578611051,ES
@@ -57303,7 +57962,8 @@
1578611220,1578611223,DE
1578611224,1578611227,ES
1578611228,1578611231,PL
-1578611232,1578611247,FR
+1578611232,1578611235,IT
+1578611236,1578611247,FR
1578611248,1578611251,ES
1578611252,1578611255,IT
1578611256,1578611263,PL
@@ -57360,7 +58020,12 @@
1578612304,1578612319,DE
1578612320,1578612383,FR
1578612384,1578612415,PL
-1578612416,1578612607,FR
+1578612416,1578612479,FR
+1578612480,1578612575,GB
+1578612576,1578612579,PL
+1578612580,1578612583,FR
+1578612584,1578612587,IE
+1578612588,1578612607,IT
1578612608,1578612623,PT
1578612624,1578612639,CH
1578612640,1578612671,PL
@@ -57387,7 +58052,8 @@
1578613712,1578613719,BE
1578613720,1578613723,ES
1578613724,1578613727,IT
-1578613728,1578613739,PL
+1578613728,1578613735,FR
+1578613736,1578613739,PL
1578613740,1578613743,FR
1578613744,1578613751,ES
1578613752,1578613759,NL
@@ -57499,13 +58165,18 @@
1581989888,1582006271,PL
1582006272,1582022655,RU
1582022656,1582039039,NL
+1582039040,1582055423,BH
1582055424,1582071807,UA
1582071808,1582088191,ES
1582088192,1582104575,GB
1582104576,1582153727,RU
1582153728,1582170111,SA
1582170112,1582186495,CH
-1582186496,1582202879,TR
+1582186496,1582193919,GB
+1582193920,1582194207,TR
+1582194208,1582196991,GB
+1582196992,1582198015,TR
+1582198016,1582202879,GB
1582202880,1582219263,PL
1582219264,1582252031,RU
1582252032,1582268415,TR
@@ -57581,13 +58252,13 @@
1583783936,1583788031,EU
1583788032,1583792127,TM
1583792128,1583796223,IE
-1583796224,1583800319,DE
+1583796224,1583800063,DE
+1583800064,1583800095,AT
+1583800096,1583800319,DE
1583800320,1583804415,ME
1583804416,1583808511,GB
1583808512,1583812607,MD
-1583812608,1583813139,NL
-1583813140,1583813143,DE
-1583813144,1583813171,NL
+1583812608,1583813171,NL
1583813172,1583813183,US
1583813184,1583813199,NL
1583813200,1583813215,RU
@@ -57596,17 +58267,11 @@
1583813240,1583813243,US
1583813244,1583813663,NL
1583813664,1583813671,US
-1583813672,1583813679,NL
-1583813680,1583813683,GB
-1583813684,1583813711,NL
+1583813672,1583813711,NL
1583813712,1583813727,US
1583813728,1583813735,NL
1583813736,1583813743,DE
-1583813744,1583813808,NL
-1583813809,1583813815,US
-1583813816,1583814655,NL
-1583814656,1583814783,US
-1583814784,1583815167,NL
+1583813744,1583815167,NL
1583815168,1583815215,US
1583815216,1583815343,NL
1583815344,1583815351,US
@@ -57662,8 +58327,8 @@
1585205248,1585207295,FR
1585207296,1585209855,NL
1585209856,1585210111,IQ
-1585210112,1585210879,IR
-1585210880,1585211391,NL
+1585210112,1585210367,IR
+1585210368,1585211391,NL
1585211392,1585213439,CZ
1585213440,1585214463,GB
1585214464,1585217535,NL
@@ -57745,6 +58410,7 @@
1585354752,1585356799,RU
1585356800,1585358847,FI
1585358848,1585360895,PT
+1585360896,1585362943,DK
1585362944,1585363455,IT
1585363456,1585363551,ES
1585363552,1585364991,IT
@@ -57855,7 +58521,9 @@
1586216960,1586225151,BG
1586225152,1586233343,RU
1586233344,1586241535,FR
-1586241536,1586243779,SE
+1586241536,1586242983,SE
+1586242984,1586242991,DK
+1586242992,1586243779,SE
1586243780,1586243787,NO
1586243788,1586249727,SE
1586249728,1586257919,SI
@@ -57966,6 +58634,15 @@
1588723712,1588854783,UA
1588854784,1588985855,RU
1588985856,1589182463,IR
+1589182464,1589198847,OM
+1589198848,1589200895,FR
+1589200896,1589202943,IT
+1589202944,1589203711,SE
+1589203712,1589203967,NL
+1589203968,1589204223,SE
+1589204224,1589204991,NL
+1589204992,1589207039,DE
+1589207040,1589215231,IT
1589215232,1589247999,GB
1589248000,1589280767,NO
1589280768,1589313535,DE
@@ -58161,6 +58838,7 @@
1592326144,1592328191,UA
1592328192,1592393727,RU
1592393728,1592459263,SE
+1592459264,1592524799,TR
1592524800,1592540415,GB
1592540416,1592540423,A2
1592540424,1592557567,GB
@@ -58192,9 +58870,7 @@
1593147392,1593163775,RU
1593163776,1593180159,AT
1593180160,1593196543,NO
-1593196544,1593196783,SE
-1593196784,1593196799,GB
-1593196800,1593202687,SE
+1593196544,1593202687,SE
1593202688,1593202815,NO
1593202816,1593203455,SE
1593203456,1593203487,NO
@@ -58337,6 +59013,10 @@
1599504384,1599520767,AZ
1599520768,1599537151,RU
1599537152,1599553535,BG
+1599553536,1599561727,KG
+1599561728,1599565823,GB
+1599565824,1599567871,SY
+1599567872,1599569919,IT
1599569920,1599586303,SI
1599586304,1599602687,BG
1599602688,1599864831,DE
@@ -58363,7 +59043,9 @@
1600963176,1600963183,RU
1600963184,1600963191,BY
1600963192,1600963199,KZ
-1600963200,1600978943,RU
+1600963200,1600971087,RU
+1600971088,1600971091,TR
+1600971092,1600978943,RU
1600978944,1601011711,SE
1601011712,1601044479,UA
1601044480,1601077247,RU
@@ -58462,6 +59144,7 @@
1602347008,1602349055,PL
1602349056,1602351103,RU
1602351104,1602353151,CZ
+1602353152,1602355199,ES
1602355200,1602357247,GB
1602357248,1602359295,FR
1602359296,1602361343,DE
@@ -58581,7 +59264,11 @@
1603085872,1603085879,CH
1603085880,1603087047,IT
1603087048,1603087103,DE
-1603087104,1603087515,IT
+1603087104,1603087199,IT
+1603087200,1603087231,SM
+1603087232,1603087472,IT
+1603087473,1603087474,CH
+1603087475,1603087515,IT
1603087516,1603087517,CH
1603087518,1603087544,IT
1603087545,1603087546,CH
@@ -58626,12 +59313,14 @@
1603159824,1603159839,CH
1603159840,1603160079,DE
1603160080,1603160095,NL
-1603160096,1603161007,DE
+1603160096,1603160111,GB
+1603160112,1603161007,DE
1603161008,1603161023,GB
1603161024,1603161103,DE
1603161104,1603161119,GB
1603161120,1603161135,AT
-1603161136,1603161567,DE
+1603161136,1603161151,GB
+1603161152,1603161567,DE
1603161568,1603161599,FR
1603161600,1603162111,DE
1603162112,1603166207,TJ
@@ -58724,13 +59413,13 @@
1603895296,1603928063,RU
1603928064,1603944447,DK
1603944448,1603977215,RU
-1603977216,1603980463,GB
+1603977216,1603979295,GB
+1603979296,1603979327,US
+1603979328,1603980463,GB
1603980464,1603980479,CH
1603980480,1603980863,GB
1603980864,1603980927,ID
-1603980928,1603981823,GB
-1603981824,1603982079,IE
-1603982080,1603982655,GB
+1603980928,1603982655,GB
1603982656,1603982687,DK
1603982688,1603982719,AN
1603982720,1603982783,GB
@@ -58774,8 +59463,7 @@
1604853760,1604861951,HU
1604861952,1604870143,RS
1604870144,1604878335,HR
-1604878336,1604886591,DE
-1604886592,1604886655,US
+1604878336,1604886655,DE
1604886656,1604886783,RU
1604886784,1604887039,DE
1604887040,1604887295,GB
@@ -58916,7 +59604,11 @@
1607467008,1607532543,DE
1607532544,1607569407,SE
1607569408,1607571455,DK
-1607571456,1607585791,SE
+1607571456,1607575551,SE
+1607575552,1607577599,DK
+1607577600,1607581695,SE
+1607581696,1607583743,DK
+1607583744,1607585791,SE
1607585792,1607598079,DK
1607598080,1607610367,IT
1607610368,1607612415,IE
@@ -58972,7 +59664,7 @@
1607968768,1607969791,SE
1607970816,1607972863,RU
1607972864,1607974911,NL
-1607979008,1607980031,RU
+1607976960,1607980031,RU
1607980032,1607981055,DE
1607981056,1607982079,UA
1607983104,1607984127,GB
@@ -58988,7 +59680,28 @@
1608515584,1610612735,IT
1610612736,1610678271,US
1610678272,1610743807,CA
-1610743808,1611227135,US
+1610743808,1611165943,US
+1611165944,1611165951,BD
+1611165952,1611166111,US
+1611166112,1611166119,NZ
+1611166120,1611166167,US
+1611166168,1611166175,AF
+1611166176,1611166527,US
+1611166528,1611166559,IN
+1611166560,1611166911,US
+1611166912,1611166943,IN
+1611166944,1611166975,US
+1611166976,1611167039,IN
+1611167040,1611167103,US
+1611167104,1611167167,IN
+1611167168,1611167199,US
+1611167200,1611167231,IN
+1611167232,1611167679,US
+1611167680,1611167727,SE
+1611167728,1611169279,US
+1611169280,1611169663,IE
+1611169664,1611169791,GB
+1611169792,1611227135,US
1611227136,1611235327,CA
1611235328,1611923455,US
1611923456,1612185599,CA
@@ -59081,7 +59794,9 @@
1613635584,1613639679,CA
1613639680,1613676543,US
1613676544,1613680639,CA
-1613680640,1613737983,US
+1613680640,1613703670,US
+1613703671,1613703678,LK
+1613703679,1613737983,US
1613737984,1613742079,CA
1613742080,1613750591,US
1613750592,1613750607,BR
@@ -59136,7 +59851,9 @@
1652293632,1652310015,CA
1652310016,1652481279,US
1652481280,1652481791,CN
-1652481792,1652621327,US
+1652481792,1652487286,US
+1652487287,1652487287,TR
+1652487288,1652621327,US
1652621328,1652621335,CA
1652621336,1652621343,AU
1652621344,1652621359,CA
@@ -59722,9 +60439,7 @@
1652681472,1652681479,GB
1652681480,1652681511,US
1652681512,1652681519,IL
-1652681520,1653496847,US
-1653496848,1653496863,AU
-1653496864,1653534719,US
+1652681520,1653534719,US
1653534720,1653538815,CA
1653538816,1653555199,US
1653555200,1653560319,CA
@@ -59744,8 +60459,8 @@
1654558720,1654583103,US
1654583104,1654583135,CA
1654583136,1654597823,US
-1654597824,1654597887,GB
-1654597888,1654599455,US
+1654597824,1654597855,GB
+1654597856,1654599455,US
1654599456,1654599471,CA
1654599472,1654599487,US
1654599488,1654599519,BA
@@ -60164,6 +60879,77 @@
1728378880,1728380927,IN
1728380928,1728382975,PH
1728382976,1728383999,SG
+1728384000,1728385023,HK
+1728385024,1728386047,IN
+1728386048,1728387071,JP
+1728387072,1728388095,TH
+1728388096,1728388351,NZ
+1728388352,1728388607,AU
+1728388608,1728389119,VN
+1728389120,1728390143,TW
+1728390144,1728391167,CN
+1728391168,1728392191,JP
+1728392192,1728393215,SG
+1728393216,1728394239,ID
+1728394240,1728396287,CN
+1728396288,1728397311,PH
+1728397312,1728398335,JP
+1728398336,1728398847,AU
+1728398848,1728399103,IN
+1728399104,1728400383,NZ
+1728400384,1728400895,AU
+1728400896,1728401151,IN
+1728401152,1728401407,SG
+1728401408,1728402431,NZ
+1728402432,1728403455,IN
+1728403456,1728406527,AU
+1728406528,1728407551,TW
+1728407552,1728407807,JP
+1728407808,1728408063,MY
+1728408064,1728408319,NZ
+1728408320,1728408575,ID
+1728408576,1728409599,NZ
+1728409600,1728410623,IN
+1728410624,1728411647,JP
+1728411648,1728412671,TH
+1728412672,1728413695,KH
+1728413696,1728414719,KR
+1728414720,1728415743,IN
+1728415744,1728416767,PK
+1728416768,1728417791,JP
+1728417792,1728418815,KR
+1728418816,1728419071,ID
+1728419072,1728419327,HK
+1728419328,1728419583,NP
+1728419584,1728419839,SG
+1728419840,1728420863,JP
+1728420864,1728421887,NZ
+1728421888,1728422911,JP
+1728422912,1728423935,AU
+1728423936,1728424959,TW
+1728424960,1728425983,AF
+1728425984,1728427007,JP
+1728427008,1728428031,MY
+1728428032,1728430079,IN
+1728430080,1728431103,JP
+1728431104,1728431615,AF
+1728431616,1728431871,HK
+1728431872,1728432127,SG
+1728432128,1728433151,IN
+1728433152,1728435199,VN
+1728435200,1728435967,AU
+1728435968,1728436223,ID
+1728436224,1728437247,IN
+1728437248,1728438271,HK
+1728438272,1728439295,NZ
+1728439296,1728439807,NP
+1728439808,1728440319,AU
+1728440320,1728441343,BD
+1728441344,1728442367,MY
+1728442368,1728443391,SG
+1728443392,1728444415,IN
+1728444416,1728445439,JP
+1728445440,1728446463,CN
1728708608,1728709631,CN
1728709632,1728710655,TW
1728710656,1728710911,AU
@@ -60241,6 +61027,60 @@
1728772096,1728773375,IN
1728773376,1728773631,ID
1728773632,1728774143,PH
+1728774144,1728775167,AU
+1728775168,1728776191,JP
+1728776192,1728777215,AU
+1728777216,1728778239,TH
+1728778240,1728779263,JP
+1728779264,1728779519,IN
+1728779520,1728779775,NZ
+1728779776,1728780287,ID
+1728780288,1728781311,KR
+1728781312,1728782335,ID
+1728782336,1728783359,LK
+1728783360,1728784383,HK
+1728784384,1728785407,PH
+1728785408,1728786431,KR
+1728786432,1728787455,SG
+1728787456,1728788479,AU
+1728788480,1728789503,KR
+1728789504,1728790527,PK
+1728790528,1728791551,PH
+1728791552,1728792575,PK
+1728792576,1728793087,NZ
+1728793088,1728793599,ID
+1728793600,1728794623,AU
+1728794624,1728796671,IN
+1728796672,1728798719,HK
+1728798720,1728799743,ID
+1728799744,1728801279,HK
+1728801280,1728801791,ID
+1728801792,1728802815,HK
+1728802816,1728803839,PH
+1728803840,1728804863,IN
+1728804864,1728805887,JP
+1728805888,1728806911,NZ
+1728806912,1728807935,KR
+1728807936,1728808959,ID
+1728808960,1728809983,BD
+1728809984,1728810495,SG
+1728810496,1728810751,AU
+1728810752,1728811007,SG
+1728811008,1728812031,AU
+1728812032,1728812543,ID
+1728812544,1728813055,SG
+1728813056,1728814079,IN
+1728814080,1728815103,JP
+1728815104,1728818175,AU
+1728818176,1728819199,VN
+1728819200,1728819711,ID
+1728819712,1728819967,NZ
+1728819968,1728820223,ID
+1728820224,1728821247,CN
+1728821248,1728821759,AU
+1728822272,1728823295,SG
+1728823296,1728824319,MN
+1728824320,1728825343,JP
1729495040,1729519615,CN
1729519616,1729520639,HK
1729520640,1729527807,CN
@@ -60413,7 +61253,8 @@
1744235520,1744236543,KR
1744236544,1744237567,IN
1744237568,1744238591,HK
-1744238592,1744239615,NZ
+1744238592,1744238847,US
+1744238848,1744239615,NZ
1744239616,1744240639,JP
1769996288,1772093439,MA
1778384896,1778385151,CN
@@ -60442,7 +61283,58 @@
1790967808,1793064959,IN
1793064960,1794113535,CN
1794113536,1795162111,KR
-1795162112,1815822335,US
+1795162112,1795555359,US
+1795555360,1795555455,CA
+1795555456,1795555519,US
+1795555520,1795555583,CA
+1795555584,1795555839,US
+1795555840,1795555855,CA
+1795555856,1795555863,US
+1795555864,1795555903,CA
+1795555904,1795555967,AN
+1795555968,1795556095,CA
+1795556096,1795556103,US
+1795556104,1795556127,CA
+1795556128,1795556175,US
+1795556176,1795556183,CA
+1795556184,1795556191,US
+1795556192,1795556255,CA
+1795556256,1795556287,US
+1795556288,1795556319,QA
+1795556320,1795556351,US
+1795556352,1795556607,GB
+1795556608,1795556639,US
+1795556640,1795556671,CA
+1795556672,1795556735,US
+1795556736,1795556863,CA
+1795556864,1795556927,US
+1795556928,1795556959,CA
+1795556960,1795556991,US
+1795556992,1795557119,CA
+1795557120,1795557135,US
+1795557136,1795557143,CA
+1795557144,1795557151,US
+1795557152,1795557215,CA
+1795557216,1795557247,US
+1795557248,1795557287,CA
+1795557288,1795557311,US
+1795557312,1795557375,CA
+1795557376,1795557887,IN
+1795557888,1795558143,US
+1795558144,1795558655,IN
+1795558656,1795558911,US
+1795558912,1795559423,IN
+1795559424,1795559679,AR
+1795559680,1795559743,US
+1795559744,1795559807,AE
+1795559808,1795560447,US
+1795560448,1795560959,CA
+1795560960,1795561471,US
+1795561472,1795561983,CA
+1795561984,1795565055,US
+1795565056,1795565567,IN
+1795565568,1803550719,US
+1809842176,1815822335,US
1815822336,1815826431,CA
1815826432,1815871487,US
1815871488,1815879679,CA
@@ -60450,18 +61342,40 @@
1815912448,1815920639,CA
1815920640,1815928831,US
1815928832,1815937023,BS
-1815937024,1816024319,US
+1815937024,1816001791,US
+1816001792,1816002559,NL
+1816002560,1816024319,US
1816024320,1816024575,CA
1816024576,1816068095,US
1816068096,1816133631,CA
-1816133632,1828716543,US
+1816133632,1822429183,US
+1822429184,1822433279,CA
+1822433280,1822445567,US
+1822445568,1822453759,CA
+1822453760,1822486527,US
+1822486528,1822490623,CA
+1822490624,1822498815,US
+1822498816,1822502911,CA
+1822502912,1822511103,US
+1822515200,1822519295,US
+1822519296,1822523391,CA
+1822523392,1822527487,US
+1822556160,1822572543,US
+1822572544,1822605311,CA
+1822605312,1822621695,US
+1822687232,1822752767,US
+1824522240,1828716543,US
1828716544,1830813695,FR
1830813696,1831337983,NL
1831337984,1831862271,DE
1831862272,1832124415,PT
1832124416,1832386559,IT
1832386560,1832517631,DK
-1832517632,1832583167,SE
+1832517632,1832552448,SE
+1832552449,1832553471,DK
+1832553472,1832553472,SE
+1832553473,1832554495,DK
+1832554496,1832583167,SE
1832583168,1832648703,DK
1832648704,1832681471,HR
1832681472,1832714239,RU
@@ -60636,7 +61550,9 @@
1833468160,1833468287,RU
1833468288,1833468575,CH
1833468576,1833468591,RU
-1833468592,1833471999,CH
+1833468592,1833469439,CH
+1833469440,1833469951,IN
+1833469952,1833471999,CH
1833472000,1833474047,EU
1833474048,1833474559,UA
1833474560,1833474815,RU
@@ -60705,7 +61621,9 @@
1833672704,1833676799,GB
1833676800,1833677567,DE
1833677568,1833677599,CH
-1833677600,1833678903,DE
+1833677600,1833677775,DE
+1833677776,1833677783,FR
+1833677784,1833678903,DE
1833678904,1833678935,HK
1833678936,1833678959,DE
1833678960,1833678975,BA
@@ -60822,13 +61740,11 @@
1835913216,1835917311,RU
1835917312,1835920127,GB
1835920128,1835920199,PT
-1835920200,1835920223,GB
-1835920224,1835920247,PT
-1835920248,1835920255,GB
-1835920256,1835920287,PT
-1835920288,1835920295,GB
-1835920296,1835920319,PT
-1835920320,1835925503,GB
+1835920200,1835920207,GB
+1835920208,1835920271,PT
+1835920272,1835920279,GB
+1835920280,1835920335,PT
+1835920336,1835925503,GB
1835925504,1835933695,LV
1835933696,1835941887,RU
1835941888,1835950079,UA
@@ -60887,6 +61803,16 @@
1839333376,1839366143,UA
1839366144,1839398911,IR
1839398912,1839431679,NO
+1839431680,1839448063,BA
+1839448064,1839450111,KZ
+1839450112,1839452159,NO
+1839452160,1839454207,FI
+1839454208,1839456255,RU
+1839456256,1839459327,RO
+1839459328,1839459839,DE
+1839459840,1839460351,RO
+1839460352,1839462399,RU
+1839462400,1839464447,FI
1839464448,1839497215,CZ
1839497216,1839529983,CH
1839529984,1839562751,RU
@@ -60898,17 +61824,13 @@
1839756328,1839756335,FR
1839756336,1839759359,IT
1839759360,1839792127,RU
-1839792128,1839794687,GB
-1839794688,1839794943,US
-1839794944,1839795151,GB
+1839792128,1839795151,GB
1839795152,1839795167,US
1839795168,1839796607,GB
1839796608,1839796671,US
1839796672,1839797759,GB
1839797760,1839798015,GR
-1839798016,1839798271,GB
-1839798272,1839798399,DE
-1839798400,1839798527,GB
+1839798016,1839798527,GB
1839798528,1839798559,US
1839798560,1839800447,GB
1839800448,1839800479,SG
@@ -60917,15 +61839,15 @@
1839800960,1839801023,GR
1839801024,1839801279,GB
1839801280,1839801311,VG
-1839801312,1839801343,GB
-1839801344,1839801471,CN
-1839801472,1839801551,GB
+1839801312,1839801551,GB
1839801552,1839801567,US
1839801568,1839802111,GB
1839802112,1839802239,RO
1839802240,1839806463,GB
1839806464,1839811071,US
-1839811072,1839816703,GB
+1839811072,1839812607,GB
+1839812608,1839814143,US
+1839814144,1839816703,GB
1839816704,1839824895,NO
1839824896,1839890431,RU
1839890432,1839923199,GB
@@ -60950,6 +61872,7 @@
1840906240,1840971775,IL
1840971776,1841102847,RU
1841102848,1841168383,NO
+1841168384,1841233919,FR
1841233920,1841299455,RU
1841299456,1841430527,DE
1841430528,1841561599,RU
@@ -61061,7 +61984,15 @@
1842154240,1842154247,HK
1842154248,1842154367,NO
1842154368,1842154431,US
-1842154432,1842155519,NO
+1842154432,1842154495,NO
+1842154496,1842154511,CN
+1842154512,1842154527,SG
+1842154528,1842154559,AU
+1842154560,1842154751,NO
+1842154752,1842154815,AU
+1842154816,1842155007,NO
+1842155008,1842155263,AU
+1842155264,1842155519,SG
1842155520,1842157567,IT
1842157568,1842159615,AE
1842159616,1842161663,BA
@@ -61143,7 +62074,10 @@
1843789824,1843806207,SK
1843806208,1843822591,IR
1843822592,1843838975,RU
-1843838976,1843849215,DE
+1843838976,1843841535,DE
+1843841536,1843841791,CH
+1843841792,1843842047,AU
+1843842048,1843849215,DE
1843849216,1843850239,GB
1843850240,1843855359,DE
1843855360,1843871743,PL
@@ -61220,6 +62154,8 @@
1844058112,1844062207,RU
1844062208,1844064255,CZ
1844064256,1844068351,IT
+1844068352,1844068607,FR
+1844068608,1844070399,ES
1844070400,1844072447,GB
1844072448,1844076543,ES
1844076544,1844078591,IE
@@ -61296,15 +62232,19 @@
1844170016,1844170019,NG
1844170020,1844170027,AF
1844170028,1844170031,IQ
-1844170032,1844170047,AF
-1844170048,1844170051,DE
+1844170032,1844170043,AF
+1844170044,1844170051,DE
1844170052,1844170055,GH
1844170056,1844170063,AF
-1844170064,1844170239,DE
+1844170064,1844170067,DE
+1844170068,1844170071,NG
+1844170072,1844170083,DE
+1844170084,1844170091,NG
+1844170092,1844170239,DE
1844170240,1844170255,AF
1844170256,1844170263,IQ
-1844170264,1844170271,AF
-1844170272,1844170751,DE
+1844170264,1844170279,AF
+1844170280,1844170751,DE
1844170752,1844174847,RU
1844174848,1844178943,DE
1844178944,1844180991,EE
@@ -61377,7 +62317,8 @@
1844318208,1844322303,IT
1844322304,1844326399,CZ
1844326400,1844329983,DK
-1844329984,1844330495,LU
+1844329984,1844330303,LU
+1844330304,1844330495,DK
1844330496,1844334591,GB
1844334592,1844342783,RU
1844342784,1844346879,IT
@@ -61733,12 +62674,7 @@
1877721088,1877737471,TW
1877737472,1877999615,JP
1877999616,1879048191,TW
-1879048192,1883218547,CN
-1883218548,1883218551,ES
-1883218552,1883218555,FR
-1883218556,1883218579,CN
-1883218580,1883218583,BE
-1883218584,1883504639,CN
+1879048192,1883504639,CN
1883504640,1883766783,JP
1883766784,1883770879,MN
1883770880,1883783167,KR
@@ -63059,7 +63995,7 @@
2033362944,2033364991,TH
2033364992,2033369087,TW
2033369088,2033377279,AU
-2033377280,2033385471,PH
+2033377280,2033385471,KR
2033385472,2033451007,CN
2033451008,2033487871,ID
2033487872,2033491967,PK
@@ -63087,12 +64023,7 @@
2033889280,2033891327,JP
2033891328,2033893375,ID
2033893376,2033909759,PH
-2033909760,2034213775,CN
-2034213776,2034213779,FR
-2034213780,2034213783,DE
-2034213784,2034213787,CN
-2034213788,2034213791,SL
-2034213792,2034237439,CN
+2033909760,2034237439,CN
2034237440,2034499583,KR
2034499584,2034761727,CN
2034761728,2035023871,NZ
@@ -63677,7 +64608,7 @@
2090745856,2090762239,MN
2090762240,2090778623,ID
2090778624,2090786815,HK
-2090786816,2090795007,SG
+2090786816,2090795007,MY
2090795008,2090860543,JP
2090860544,2091384831,CN
2091384832,2091646975,AU
@@ -63881,7 +64812,8 @@
2113830912,2113863679,CN
2113863680,2113929215,AU
2113929216,2130706431,JP
-2147483648,2147942399,US
+2147483648,2147549183,EU
+2147549184,2147942399,US
2147942400,2148007935,DE
2148007936,2148220515,US
2148220516,2148220535,AU
@@ -63894,7 +64826,27 @@
2150105088,2150236159,GB
2150236160,2150301695,US
2150301696,2150367231,CA
-2150367232,2151743487,US
+2150367232,2150432767,US
+2150432768,2150498303,IT
+2150498304,2151743487,US
+2151743488,2151759871,BY
+2151759872,2151768063,US
+2151768064,2151770111,GB
+2151770112,2151772159,BA
+2151772160,2151776255,IT
+2151776256,2151778303,AT
+2151778304,2151780351,RU
+2151780352,2151782399,DE
+2151782400,2151784447,ES
+2151784448,2151792639,IR
+2151792640,2151794687,CH
+2151794688,2151796735,IT
+2151796736,2151797759,NL
+2151797760,2151797775,DE
+2151797776,2151800319,NL
+2151800320,2151800831,DE
+2151800832,2151809023,PT
+2151809024,2151940095,IT
2152726528,2153119743,US
2153119744,2153250815,GB
2153250816,2153578495,US
@@ -63903,12 +64855,52 @@
2153906176,2153971711,GB
2153971712,2154037247,US
2154037248,2154102783,CA
-2154102784,2156003327,US
+2154102784,2155610111,US
+2155610112,2155675647,UA
+2155675648,2155806719,US
+2155806720,2155808767,IT
+2155808768,2155810815,RU
+2155810816,2155812863,FR
+2155812864,2155814911,GB
+2155814912,2155819007,NL
+2155819008,2155821055,DE
+2155821056,2155823103,IT
+2155823104,2155825151,DE
+2155825152,2155827199,AE
+2155827200,2155831295,PL
+2155831296,2155833343,RU
+2155833344,2155833855,SE
+2155833856,2155834367,NL
+2155834368,2155834879,SE
+2155834880,2155835391,NL
+2155835392,2155839487,RO
+2155839488,2155843583,FR
+2155843584,2155845631,RU
+2155845632,2155847679,DE
+2155847680,2155849727,ES
+2155849728,2155851775,TR
+2155851776,2155853823,KZ
+2155853824,2155855871,SE
+2155855872,2155872255,RO
+2155872256,2156003327,US
2156003328,2156134399,AT
2156134400,2156265471,US
2156265472,2156331007,KR
2156331008,2156593151,US
2156593152,2156658687,IL
+2156658688,2156691455,IR
+2156691456,2156695551,A2
+2156695552,2156697599,FR
+2156697600,2156699647,CY
+2156699648,2156703743,RU
+2156703744,2156707839,BG
+2156707840,2156709887,RU
+2156709888,2156711935,ES
+2156711936,2156713983,DE
+2156713984,2156716031,NL
+2156716032,2156718079,RO
+2156718080,2156720127,IS
+2156720128,2156724223,BY
2156724224,2156855295,CH
2156855296,2156920831,US
2156920832,2156986367,CA
@@ -63922,11 +64914,21 @@
2159869952,2159935487,CA
2159935488,2160525311,US
2160525312,2160590847,GB
-2160590848,2161508351,US
+2160590848,2160852991,US
+2160852992,2160885759,RU
+2160885760,2160893951,AT
+2160893952,2160902143,RU
+2160902144,2160906239,NL
+2160906240,2160908287,FR
+2160908288,2160910335,PL
+2160910336,2160914431,NL
+2160914432,2160918527,SA
+2160918528,2161508351,US
2161508352,2161573887,FI
2161573888,2162687999,US
2162688000,2162753535,GB
2162753536,2162819071,CA
+2162819072,2162884607,RO
2162884608,2163212287,US
2163212288,2163277823,GB
2163277824,2163288063,US
@@ -64030,12 +65032,32 @@
2180579328,2180644863,JP
2180644864,2180907007,US
2180907008,2180972543,KR
-2180972544,2181824511,US
+2180972544,2181038079,US
+2181038080,2181040127,GB
+2181040128,2181042175,AZ
+2181042176,2181044223,DE
+2181044224,2181046271,AL
+2181046272,2181054463,UA
+2181054464,2181056511,AT
+2181056512,2181058559,DE
+2181058560,2181060607,GB
+2181060608,2181062655,BA
+2181062656,2181070847,FR
+2181070848,2181087231,IT
+2181087232,2181089279,FR
+2181089280,2181091327,SE
+2181091328,2181093375,IT
+2181093376,2181095423,RU
+2181095424,2181097471,GB
+2181097472,2181099519,UA
+2181099520,2181103615,SY
+2181103616,2181824511,US
2181824512,2181890047,CA
2181890048,2182021119,US
2182021120,2182086655,CA
2182086656,2182610943,US
2182610944,2182676479,GB
+2182676480,2182742015,IT
2182742016,2182873087,US
2182873088,2182938623,SE
2182938624,2183135231,US
@@ -64044,7 +65066,11 @@
2183266304,2183331839,JP
2183331840,2183462911,US
2183462912,2183528447,NL
-2183528448,2184577023,US
+2183528448,2183856127,US
+2183856128,2183888895,GR
+2183888896,2183905279,GB
+2183905280,2183921663,HU
+2183921664,2184577023,US
2184577024,2184642559,JP
2184642560,2184708095,US
2184708096,2184773631,AU
@@ -64137,9 +65163,32 @@
2191589376,2191654911,NL
2191654912,2192769023,US
2192769024,2192834559,CA
+2192834560,2192867327,DE
+2192867328,2192883711,SY
+2192883712,2192885759,PL
+2192885760,2192887807,GB
+2192887808,2192891903,UA
+2192891904,2192900095,RS
2192900096,2193031167,US
2193031168,2193096703,DE
2193096704,2193162239,US
+2193162240,2193178623,UA
+2193178624,2193180671,GB
+2193180672,2193182719,IR
+2193182720,2193184767,PT
+2193184768,2193186815,ES
+2193186816,2193188863,PL
+2193188864,2193190911,DE
+2193190912,2193195007,RU
+2193195008,2193199103,DK
+2193199104,2193201151,GB
+2193201152,2193202175,SE
+2193202176,2193203199,US
+2193203200,2193205247,GB
+2193205248,2193207295,FR
+2193207296,2193209343,CZ
+2193209344,2193211391,FR
+2193211392,2193227775,BG
2193227776,2193293311,IT
2193293312,2193358847,US
2193358848,2193424383,FI
@@ -64147,6 +65196,17 @@
2193489920,2193555455,FR
2193555456,2193620991,US
2193620992,2193686527,IT
+2193686528,2193688575,FR
+2193688576,2193692671,CZ
+2193692672,2193694719,FR
+2193694720,2193704959,RU
+2193704960,2193707007,IT
+2193707008,2193711103,GB
+2193711104,2193713151,DE
+2193713152,2193715199,ES
+2193715200,2193717247,DE
+2193717248,2193719295,AM
+2193719296,2193752063,IQ
2193752064,2193817599,AU
2193817600,2193883135,NZ
2193883136,2194014207,US
@@ -64154,6 +65214,7 @@
2194079744,2194210815,US
2194210816,2194276351,GB
2194276352,2194407423,US
+2194407424,2194472959,BG
2194472960,2194538495,US
2194538496,2194604031,ES
2194604032,2194669567,US
@@ -64176,7 +65237,18 @@
2197225472,2197422079,US
2197422080,2197487615,CA
2197487616,2197553151,IT
-2197553152,2197815295,US
+2197553152,2197749759,US
+2197749760,2197751807,IQ
+2197751808,2197753855,RU
+2197753856,2197757951,GB
+2197757952,2197766143,RU
+2197766144,2197768191,PS
+2197768192,2197770239,IL
+2197770240,2197772287,RU
+2197772288,2197774335,IQ
+2197774336,2197776383,IT
+2197776384,2197778431,DE
+2197778432,2197780479,IT
2197880832,2197946367,IT
2197946368,2204172287,US
2204172288,2204237823,SE
@@ -65211,11 +66283,25 @@
2365644800,2365652991,NO
2365652992,2366111743,DE
2366111744,2366144511,MT
-2366144512,2366162943,RU
+2366144512,2366149375,RU
+2366149376,2366149407,DE
+2366149408,2366149423,PL
+2366149424,2366149439,SK
+2366149440,2366149455,PT
+2366149456,2366149471,ES
+2366149472,2366149487,FR
+2366149488,2366149495,MD
+2366149496,2366149503,LT
+2366149504,2366149511,LV
+2366149512,2366149519,EE
+2366149520,2366149527,BG
+2366149528,2366149535,RS
+2366149536,2366162943,RU
2366162944,2366164991,AL
2366164992,2366167039,GE
2366167040,2366169087,GB
-2366169088,2366308351,DE
+2366169088,2366171135,CH
+2366171136,2366308351,DE
2366308352,2366373887,GB
2366373888,2367487999,DE
2367488000,2367553535,SI
@@ -65237,7 +66323,9 @@
2372218880,2372220927,FR
2372220928,2372222975,KW
2372222976,2372239359,EU
-2372239360,2372272127,RU
+2372239360,2372264447,RU
+2372264448,2372266495,UA
+2372266496,2372272127,RU
2372272128,2372337663,US
2372337664,2372403199,ID
2372403200,2372468735,US
@@ -65247,7 +66335,11 @@
2372474624,2372474879,GB
2372474880,2372483071,RU
2372483072,2372485119,JO
-2372485120,2372487167,RU
+2372485120,2372485247,RU
+2372485248,2372485375,IN
+2372485376,2372485823,RU
+2372485824,2372485887,NL
+2372485888,2372487167,RU
2372487168,2372489215,FR
2372489216,2372493311,LB
2372493312,2372497407,ES
@@ -65302,7 +66394,8 @@
2374512640,2374514687,SK
2374514688,2374516735,ES
2374516736,2374524927,AM
-2374524928,2374529023,FR
+2374524928,2374525183,DE
+2374525184,2374529023,FR
2374529024,2374531071,RU
2374531072,2374533119,NL
2374533120,2374565887,HR
@@ -65317,8 +66410,21 @@
2374670336,2374672383,FR
2374672384,2374674431,PL
2374674432,2374676479,NL
+2374676480,2374680575,LB
2374680576,2374684671,NL
-2374684672,2374686719,GB
+2374684672,2374684991,GB
+2374684992,2374685119,FI
+2374685120,2374685247,GB
+2374685248,2374685375,NO
+2374685376,2374685503,GB
+2374685504,2374685631,DK
+2374685632,2374685759,GB
+2374685760,2374685887,NL
+2374685888,2374686015,GB
+2374686016,2374686143,PL
+2374686144,2374686271,GB
+2374686272,2374686303,NL
+2374686304,2374686719,GB
2374686720,2374688767,NL
2374688768,2374696959,GB
2374696960,2374959103,US
@@ -65336,6 +66442,7 @@
2376761344,2376777727,CZ
2376777728,2376781823,BA
2376781824,2376783871,ES
+2376783872,2376785919,FR
2376785920,2376794111,UA
2376794112,2376859647,CH
2376859648,2376925183,FI
@@ -65638,50 +66745,7 @@
2447679820,2447679839,IT
2447679840,2447704063,DE
2447704064,2447769599,GB
-2447769600,2447769855,DE
-2447769856,2447770111,GB
-2447770112,2447775743,DE
-2447775744,2447777791,GB
-2447777792,2447781887,DE
-2447781888,2447782911,GB
-2447782912,2447783935,LU
-2447783936,2447784959,GB
-2447784960,2447785983,LU
-2447785984,2447788031,DE
-2447788032,2447790079,QA
-2447790080,2447792127,DE
-2447792128,2447792383,GB
-2447792384,2447793919,DE
-2447793920,2447794175,QA
-2447794176,2447796223,DE
-2447796224,2447798271,GB
-2447798272,2447801343,DE
-2447801344,2447802367,IT
-2447802368,2447806463,DE
-2447806464,2447808511,HU
-2447808512,2447810559,DE
-2447810560,2447812607,GB
-2447812608,2447813631,HU
-2447813632,2447813887,IE
-2447813888,2447814143,DE
-2447814144,2447814655,GB
-2447814656,2447815679,DE
-2447815680,2447816191,IT
-2447816192,2447816447,GB
-2447816448,2447816703,DE
-2447816704,2447817727,GB
-2447817728,2447821055,DE
-2447821056,2447821311,QA
-2447821312,2447821823,GB
-2447821824,2447824895,IT
-2447824896,2447826943,DE
-2447826944,2447827967,GB
-2447827968,2447830015,DE
-2447830016,2447830527,IT
-2447830528,2447833087,DE
-2447833088,2447833599,GB
-2447833600,2447834111,DE
-2447834112,2447835135,IT
+2447769600,2447835135,DE
2447835136,2447900671,FR
2447900672,2447966207,CH
2447966208,2448031743,GB
@@ -65713,6 +66777,7 @@
2449481728,2449489919,RO
2449489920,2449491967,FR
2449491968,2449494015,NL
+2449494016,2449496063,UA
2449496064,2449498111,FR
2449498112,2449506303,DE
2449506304,2449539071,RO
@@ -65744,6 +66809,7 @@
2453733376,2453798911,US
2453798912,2453800959,GB
2453800960,2453803007,RU
+2453803008,2453805055,KZ
2453805056,2453807103,FI
2453807104,2453815295,GB
2453815296,2453831679,RO
@@ -65805,11 +66871,13 @@
2457141248,2457206783,JP
2457206784,2457272319,AU
2457272320,2457337855,FI
-2457337856,2457360895,RU
-2457360896,2457361151,UA
+2457337856,2457360383,RU
+2457360384,2457361151,UA
2457361152,2457361407,CZ
2457361408,2457364479,RU
-2457364480,2457376767,CZ
+2457364480,2457366527,CZ
+2457366528,2457367551,GB
+2457367552,2457376767,CZ
2457376768,2457378815,DE
2457378816,2457380863,RU
2457380864,2457382911,EE
@@ -65870,12 +66938,14 @@
2461612032,2461614079,IL
2461614080,2461630463,TR
2461630464,2461651967,RU
-2461651968,2461652991,GB
+2461651968,2461652991,CY
2461652992,2461659135,RU
2461659136,2461659391,UA
2461659392,2461659903,RU
2461659904,2461660159,UA
-2461660160,2461663231,RU
+2461660160,2461660415,RU
+2461660416,2461660671,RO
+2461660672,2461663231,RU
2461663232,2461794303,US
2461794304,2461859839,GB
2461859840,2461990911,US
@@ -66180,7 +67250,9 @@
2500038656,2500040703,IT
2500040704,2500042751,LB
2500042752,2500046847,SA
-2500046848,2500048895,IT
+2500046848,2500047359,IT
+2500047360,2500047615,DE
+2500047616,2500048895,IT
2500048896,2500050943,MD
2500050944,2500067327,KZ
2500067328,2501574655,US
@@ -66190,6 +67262,10 @@
2503081984,2503671807,US
2503671808,2503737343,NL
2503737344,2503868415,US
+2503868416,2503876607,RU
+2503876608,2503880703,ES
+2503880704,2503882751,RU
+2503882752,2503884799,DE
2503884800,2503901183,SI
2503901184,2503905279,IT
2503905280,2503907327,CZ
@@ -66248,11 +67324,9 @@
2509928448,2509930495,FI
2509930496,2509934591,RU
2509934592,2509936639,DE
-2509936640,2509936914,AT
-2509936915,2509936915,IR
-2509936916,2509937681,AT
+2509936640,2509937681,AT
2509937682,2509937682,ME
-2509937683,2509937683,AT
+2509937683,2509937683,IR
2509937684,2509937684,IQ
2509937685,2509937685,AQ
2509937686,2509937686,MP
@@ -66266,7 +67340,26 @@
2509937694,2509937694,NA
2509937695,2509937695,AM
2509937696,2509937697,CN
-2509937698,2509938687,AT
+2509937698,2509937713,AT
+2509937714,2509937714,CV
+2509937715,2509937715,ER
+2509937716,2509937716,ET
+2509937717,2509937717,KE
+2509937718,2509937718,NG
+2509937719,2509937719,DO
+2509937720,2509937720,JM
+2509937721,2509937721,AG
+2509937722,2509937722,VI
+2509937723,2509937723,MQ
+2509937724,2509937724,KI
+2509937725,2509937725,VU
+2509937726,2509937726,TK
+2509937727,2509937727,MK
+2509937728,2509937728,TM
+2509937729,2509937729,IM
+2509937730,2509938175,AT
+2509938176,2509938431,US
+2509938432,2509938687,DE
2509938688,2509946879,UA
2509946880,2509963263,BE
2509963264,2510028799,GB
@@ -66295,14 +67388,17 @@
2514419712,2514485247,GB
2514485248,2514514431,DE
2514514432,2514514687,NL
-2514514688,2516254719,DE
+2514514688,2515599359,DE
+2515599360,2515664895,GB
+2515664896,2516254719,DE
2516254720,2516320255,FR
2516320256,2516451327,US
2516451328,2516516863,GB
2516516864,2516520959,RU
2516520960,2516523007,SA
2516523008,2516525055,RU
-2516525056,2516527103,NL
+2516525056,2516525823,US
+2516525824,2516527103,NL
2516527104,2516529151,GB
2516529152,2516531199,CH
2516531200,2516533247,GB
@@ -66375,7 +67471,7 @@
2531459072,2531524607,SE
2531524608,2531590143,US
2531590144,2531655679,AU
-2531655680,2532048895,US
+2531721216,2532048895,US
2532048896,2532114431,SE
2532114432,2532179967,GB
2532179968,2532376575,US
@@ -66457,7 +67553,9 @@
2556559360,2556624895,AU
2556624896,2556690431,KR
2556690432,2556755967,US
-2556755968,2557018111,HK
+2556755968,2556821503,HK
+2556821504,2556887039,SG
+2556887040,2557018111,HK
2557018112,2557083647,GB
2557083648,2557542399,ZA
2557542400,2557607935,US
@@ -66500,12 +67598,9 @@
2568224768,2568290303,SG
2568290304,2569142271,US
2569142272,2569404415,CN
-2569404416,2569601023,US
-2569601024,2569666559,CA
-2569666560,2569797631,US
+2569404416,2569797631,US
2569797632,2569863167,NO
-2569863168,2569928703,US
-2569928704,2569994239,CH
+2569863168,2569994239,CH
2569994240,2570125311,US
2570125312,2570190847,BE
2570190848,2572681215,US
@@ -66531,7 +67626,9 @@
2574319616,2574647295,US
2574647296,2574778367,CN
2574778368,2583691263,JP
-2583691264,2584215551,US
+2583691264,2584018943,US
+2584018944,2584084479,CA
+2584084480,2584215551,US
2584215552,2584281087,GB
2584281088,2584346623,US
2584346624,2584412159,KR
@@ -66676,9 +67773,7 @@
2621636608,2621702143,DE
2621702144,2621767679,US
2621767680,2621833215,NZ
-2621833216,2622423039,US
-2622423040,2622488575,CA
-2622488576,2622685183,US
+2621833216,2622685183,US
2622685184,2622750719,NL
2622750720,2623602687,US
2623602688,2623668223,CL
@@ -66820,7 +67915,11 @@
2653880320,2653945855,IT
2653945856,2654011391,US
2654011392,2654076927,ES
-2654076928,2654142463,FR
+2654076928,2654085119,FR
+2654085120,2654089215,HK
+2654089216,2654093311,FR
+2654093312,2654097407,US
+2654097408,2654142463,FR
2654208000,2654339071,US
2654339072,2654404607,AU
2654404608,2654994431,US
@@ -66937,6 +68036,9 @@
2668892160,2668894207,BA
2668894208,2668896255,MT
2668896256,2668904447,GB
+2668904448,2668912639,TR
+2668912640,2668916735,IR
+2668918784,2668920831,ES
2668920832,2668953599,IT
2668953600,2669019135,US
2669019136,2669084671,CH
@@ -67023,6 +68125,7 @@
2677800960,2677866495,CH
2677866496,2677997567,US
2677997568,2678063103,CA
+2678063104,2678128639,UA
2678128640,2678194175,US
2678194176,2678259711,NO
2678259712,2678521855,US
@@ -67055,6 +68158,7 @@
2680553472,2680684543,US
2680684544,2680750079,SE
2680750080,2681012223,US
+2681012224,2681077759,PL
2681077760,2681143295,CA
2681143296,2681208831,AU
2681208832,2681274367,CA
@@ -67069,6 +68173,7 @@
2681864192,2681929727,US
2681929728,2681995263,GB
2681995264,2682257407,US
+2682257408,2682322943,UA
2682322944,2682388479,US
2682388480,2682454015,CN
2682454016,2682519551,US
@@ -67093,7 +68198,54 @@
2683699200,2683830271,US
2683830272,2683895807,AU
2683895808,2684157951,US
+2684157952,2684159999,NL
+2684160000,2684162047,NO
+2684162048,2684164095,EE
+2684164096,2684166143,SE
+2684166144,2684170239,TR
+2684170240,2684178431,GB
+2684178432,2684180479,TR
+2684180480,2684182527,DK
+2684182528,2684184575,IT
+2684184576,2684186623,SK
+2684186624,2684188671,DE
+2684188672,2684190719,RU
+2684190720,2684197119,NL
+2684197120,2684197631,GB
+2684197632,2684198399,NL
+2684198400,2684200959,GB
+2684200960,2684203007,RU
+2684203008,2684204031,CZ
+2684204032,2684204543,HK
+2684204544,2684205055,GB
+2684205056,2684207103,IT
+2684207104,2684213247,GB
+2684213248,2684215295,MK
+2684215296,2684217343,BE
+2684217344,2684219391,CZ
+2684219392,2684221439,PL
+2684221440,2684223487,IL
2684223488,2684289023,GB
+2684289024,2684297215,RU
+2684297216,2684299263,IR
+2684299264,2684301311,CY
+2684301312,2684305407,PT
+2684305408,2684321791,RU
+2684321792,2684329983,IT
+2684329984,2684332031,IQ
+2684332032,2684334079,DE
+2684334080,2684338175,PL
+2684338176,2684338303,NL
+2684338304,2684338399,ES
+2684338400,2684338687,NL
+2684338688,2684339103,ES
+2684339104,2684339119,NL
+2684339120,2684339135,ES
+2684339136,2684339199,NL
+2684339200,2684340223,ES
+2684340224,2684344319,GB
+2684344320,2684346367,NL
+2684346368,2684354559,FI
2684354560,2684616703,US
2684616704,2684682239,NZ
2684682240,2684747775,GB
@@ -67465,7 +68617,9 @@
2755330048,2755395583,DE
2755395584,2755461119,FR
2755461120,2755526655,DE
-2755526656,2755985407,US
+2755526656,2755592191,US
+2755592192,2755657727,GB
+2755657728,2755985407,US
2755985408,2756182015,JP
2756182016,2756247551,US
2756247552,2756313087,UY
@@ -67860,7 +69014,9 @@
2816004352,2816004367,US
2816004368,2816004415,IL
2816004416,2816004479,US
-2816004480,2816008191,IL
+2816004480,2816004703,IL
+2816004704,2816004711,GB
+2816004712,2816008191,IL
2816008192,2816008207,IE
2816008208,2816010495,IL
2816010496,2816010751,US
@@ -68002,7 +69158,7 @@
2849179136,2849898495,KR
2849898496,2849898751,AU
2849898752,2849964031,KR
-2849964032,2850029567,PH
+2849964032,2850029567,CN
2850029568,2851995647,US
2852126720,2853306367,US
2853306368,2853371903,CL
@@ -68052,8 +69208,10 @@
2870018048,2870083583,DE
2870083584,2870087935,FR
2870087936,2870088191,ES
-2870088192,2870089727,FR
-2870089728,2870091775,GE
+2870088192,2870088959,FR
+2870088960,2870088991,ES
+2870088992,2870089727,FR
+2870089728,2870091775,DE
2870091776,2870095871,FR
2870095872,2870096383,SG
2870096384,2870149119,FR
@@ -68155,7 +69313,9 @@
2902507520,2902515711,CA
2902515712,2904555519,US
2904555520,2904817663,CA
-2904817664,2905376767,US
+2904817664,2905350751,US
+2905350752,2905350783,RU
+2905350784,2905376767,US
2905376768,2905377535,CA
2905377536,2905378303,US
2905378304,2905378815,CA
@@ -68220,7 +69380,11 @@
2915520512,2915521023,AU
2915521024,2915521279,JP
2915521280,2915521535,PL
-2915521536,2915765279,US
+2915521536,2915526911,US
+2915526912,2915527167,DE
+2915527168,2915527679,US
+2915527680,2915528711,NL
+2915528712,2915765279,US
2915765280,2915765287,IN
2915765288,2915765367,US
2915765368,2915765375,ZA
@@ -68262,9 +69426,7 @@
2915768376,2915768383,GB
2915768384,2915768431,US
2915768432,2915768439,IE
-2915768440,2915768487,US
-2915768488,2915768495,CA
-2915768496,2915768703,US
+2915768440,2915768703,US
2915768704,2915768767,GB
2915768768,2915768903,US
2915768904,2915768911,GR
@@ -68291,7 +69453,8 @@
2915772712,2915772719,GB
2915772720,2915772751,US
2915772752,2915772759,DE
-2915772760,2915773023,US
+2915772760,2915773015,US
+2915773016,2915773023,SG
2915773024,2915773039,IN
2915773040,2915773175,US
2915773176,2915773183,KW
@@ -68516,9 +69679,15 @@
2915810648,2915810663,CA
2915810664,2915811135,US
2915811136,2915811199,IN
-2915811200,2915958783,US
+2915811200,2915821791,US
+2915821792,2915821823,IL
+2915821824,2915958783,US
2915958784,2916024319,CA
-2916024320,2916118223,US
+2916024320,2916101535,US
+2916101536,2916101543,CA
+2916101544,2916101615,US
+2916101616,2916101623,CA
+2916101624,2916118223,US
2916118224,2916118231,LK
2916118232,2916120823,US
2916120824,2916120831,CA
@@ -68581,8 +69750,7 @@
2916581376,2916614143,PR
2916614144,2917167679,US
2917167680,2917167743,BR
-2917167744,2917167807,US
-2917167808,2917167839,RS
+2917167744,2917167839,US
2917167840,2917167871,TR
2917167872,2917167903,US
2917167904,2917167935,TR
@@ -68628,7 +69796,9 @@
2917210464,2917257215,US
2917257216,2917261311,KY
2917261312,2917265407,US
-2917265408,2917269503,JM
+2917265408,2917268223,JM
+2917268224,2917268479,BB
+2917268480,2917269503,JM
2917269504,2917449727,US
2917449728,2917466111,PR
2917466112,2917572607,US
@@ -68741,13 +69911,13 @@
2917710592,2917710847,CA
2917710848,2917714175,US
2917714176,2917714431,CA
-2917714432,2917718527,US
+2917714432,2917715967,US
+2917715968,2917716223,DE
+2917716224,2917718527,US
2917718528,2917719039,CA
2917719040,2917722367,US
2917722368,2917722623,CA
-2917722624,2917723135,US
-2917723136,2917723391,CA
-2917723392,2917724159,US
+2917722624,2917724159,US
2917724160,2917724415,CA
2917724416,2917726207,US
2917726208,2917726463,CA
@@ -68780,7 +69950,9 @@
2917811512,2917811519,LK
2917811520,2917811583,US
2917811584,2917811647,LK
-2917811648,2917815575,US
+2917811648,2917813679,US
+2917813680,2917813687,LK
+2917813688,2917815575,US
2917815576,2917815583,RO
2917815584,2917823871,US
2917823872,2917823887,CA
@@ -68884,7 +70056,9 @@
2918534992,2918535807,US
2918535808,2918535967,CN
2918535968,2918535999,US
-2918536000,2918536127,CN
+2918536000,2918536023,CN
+2918536024,2918536031,US
+2918536032,2918536127,CN
2918536128,2918536167,US
2918536168,2918536191,CN
2918536192,2918536703,A1
@@ -68924,12 +70098,10 @@
2919020656,2919020711,US
2919020712,2919020719,CA
2919020720,2919020727,US
-2919020728,2919020759,CA
-2919020760,2919020767,US
-2919020768,2919020799,CA
+2919020728,2919020799,CA
2919020800,2919021343,US
-2919021344,2919021471,CA
-2919021472,2919063551,US
+2919021344,2919021567,CA
+2919021568,2919063551,US
2919063552,2919064063,MX
2919064064,2919067655,CN
2919067656,2919067695,US
@@ -69147,7 +70319,11 @@
2919070944,2919070951,BR
2919070952,2919071143,US
2919071144,2919071151,CN
-2919071152,2919170327,US
+2919071152,2919153695,US
+2919153696,2919153703,DE
+2919153704,2919153807,US
+2919153808,2919153815,AU
+2919153816,2919170327,US
2919170328,2919170335,PE
2919170336,2919170351,US
2919170352,2919170359,PE
@@ -69167,9 +70343,7 @@
2919170528,2919170535,BR
2919170536,2919170551,US
2919170552,2919170559,FR
-2919170560,2919170575,US
-2919170576,2919170583,FR
-2919170584,2919170599,US
+2919170560,2919170599,US
2919170600,2919170607,JP
2919170608,2919170615,US
2919170616,2919170623,CN
@@ -69199,7 +70373,9 @@
2919170936,2919170943,PH
2919170944,2919170967,US
2919170968,2919170975,NZ
-2919170976,2919171071,US
+2919170976,2919171055,US
+2919171056,2919171063,TR
+2919171064,2919171071,US
2919171072,2919171079,IN
2919171080,2919171087,CL
2919171088,2919171095,TR
@@ -69229,7 +70405,11 @@
2919171456,2919171463,BR
2919171464,2919171479,US
2919171480,2919171487,BR
-2919171488,2919174143,US
+2919171488,2919171535,US
+2919171536,2919171543,BR
+2919171544,2919171655,US
+2919171656,2919171663,BR
+2919171664,2919174143,US
2919174144,2919178239,CA
2919178240,2919186431,US
2919186432,2919190527,CA
@@ -70310,7 +71490,17 @@
2948595712,2952790015,KR
2952790016,2953314303,DE
2953314304,2953379839,UA
-2953379840,2953445375,DE
+2953379840,2953438191,DE
+2953438192,2953438199,ES
+2953438200,2953438231,DE
+2953438232,2953438239,CH
+2953438240,2953441263,DE
+2953441264,2953441279,IT
+2953441280,2953443031,DE
+2953443032,2953443039,IT
+2953443040,2953444183,DE
+2953444184,2953444191,IT
+2953444192,2953445375,DE
2953445376,2953453567,IT
2953453568,2953455615,IS
2953455616,2953457663,SK
@@ -70323,7 +71513,9 @@
2953466128,2953467903,EU
2953467904,2953469951,BE
2953469952,2953478143,CH
-2953478144,2953510911,SE
+2953478144,2953503551,SE
+2953503552,2953503559,NO
+2953503560,2953510911,SE
2953510912,2953576447,NO
2953576448,2953592831,BG
2953592832,2953596927,IR
@@ -70331,6 +71523,7 @@
2953598976,2953601023,IT
2953601024,2953603071,RU
2953603072,2953605119,GB
+2953605120,2953609215,CZ
2953609216,2953707519,IL
2953707520,2953838591,RU
2953838592,2954100735,SA
@@ -70343,14 +71536,451 @@
2954647552,2954657791,ES
2954657792,2954756095,JO
2954756096,2954821631,TR
-2954821632,2954870783,FR
+2954821632,2954838015,FR
+2954838016,2954838019,PL
+2954838020,2954838047,FR
+2954838048,2954838055,DE
+2954838056,2954838087,FR
+2954838088,2954838091,IT
+2954838092,2954838095,FR
+2954838096,2954838099,ES
+2954838100,2954838111,FR
+2954838112,2954838115,CZ
+2954838116,2954838119,GB
+2954838120,2954838123,CZ
+2954838124,2954838127,IT
+2954838128,2954838135,FR
+2954838136,2954838139,ES
+2954838140,2954838143,CH
+2954838144,2954838151,FR
+2954838152,2954838159,BE
+2954838160,2954838167,FR
+2954838168,2954838171,NL
+2954838172,2954838175,IT
+2954838176,2954838179,GB
+2954838180,2954838183,DE
+2954838184,2954838191,IT
+2954838192,2954838199,NL
+2954838200,2954838203,ES
+2954838204,2954838207,DE
+2954838208,2954838211,ES
+2954838212,2954838215,IE
+2954838216,2954838219,GB
+2954838220,2954838223,ES
+2954838224,2954838239,FR
+2954838240,2954838263,PL
+2954838264,2954838271,IT
+2954838272,2954838279,DE
+2954838280,2954838287,IT
+2954838288,2954838303,BE
+2954838304,2954838371,FR
+2954838372,2954838375,GB
+2954838376,2954838379,NL
+2954838380,2954838383,PL
+2954838384,2954854403,FR
+2954854404,2954854407,IT
+2954854408,2954854411,FR
+2954854412,2954854415,PL
+2954854416,2954854431,GB
+2954854432,2954854495,FR
+2954854496,2954854527,ES
+2954854528,2954854619,FR
+2954854620,2954854623,IT
+2954854624,2954854691,FR
+2954854692,2954854695,IT
+2954854696,2954854699,PL
+2954854700,2954854703,GB
+2954854704,2954854711,FR
+2954854712,2954854719,DE
+2954854720,2954854783,ES
+2954854784,2954854799,FR
+2954854800,2954854815,FI
+2954854816,2954854847,FR
+2954854848,2954854851,PL
+2954854852,2954854855,GB
+2954854856,2954854863,FR
+2954854864,2954854867,NL
+2954854868,2954854871,GB
+2954854872,2954854875,ES
+2954854876,2954854895,FR
+2954854896,2954854903,PL
+2954854904,2954855039,FR
+2954855040,2954855043,ES
+2954855044,2954855047,FR
+2954855048,2954855051,PL
+2954855052,2954855055,ES
+2954855056,2954855059,PL
+2954855060,2954855063,ES
+2954855064,2954855067,BE
+2954855068,2954855071,ES
+2954855072,2954855075,FR
+2954855076,2954855079,DE
+2954855080,2954855087,GB
+2954855088,2954855103,FR
+2954855104,2954855167,IE
+2954855168,2954855199,GB
+2954855200,2954855207,FR
+2954855208,2954855211,NL
+2954855212,2954855215,CH
+2954855216,2954855295,FR
+2954855296,2954855359,BE
+2954855360,2954855439,FR
+2954855440,2954855455,LT
+2954855456,2954855479,FR
+2954855480,2954855487,IT
+2954855488,2954855527,GB
+2954855528,2954855535,PT
+2954855536,2954855551,FR
+2954855552,2954855567,GB
+2954855568,2954855571,FR
+2954855572,2954855575,PT
+2954855576,2954855583,DE
+2954855584,2954855615,FR
+2954855616,2954855619,IE
+2954855620,2954855623,FR
+2954855624,2954855627,IT
+2954855628,2954855631,GB
+2954855632,2954855639,FI
+2954855640,2954855643,PL
+2954855644,2954855655,GB
+2954855656,2954855659,CH
+2954855660,2954855663,FR
+2954855664,2954855679,ES
+2954855680,2954855711,FR
+2954855712,2954855743,PL
+2954855744,2954855807,FR
+2954855808,2954855871,IE
+2954855872,2954855879,FR
+2954855880,2954855887,ES
+2954855888,2954855903,FR
+2954855904,2954855919,PL
+2954855920,2954855999,FR
+2954856000,2954856063,PL
+2954856064,2954856067,FR
+2954856068,2954856071,PL
+2954856072,2954856079,FR
+2954856080,2954856083,ES
+2954856084,2954856087,FR
+2954856088,2954856095,ES
+2954856096,2954856167,FR
+2954856168,2954856175,ES
+2954856176,2954856187,PL
+2954856188,2954856447,FR
+2954856448,2954856511,ES
+2954856512,2954856559,FR
+2954856560,2954856567,BE
+2954856568,2954856571,FR
+2954856572,2954856575,PL
+2954856576,2954856583,ES
+2954856584,2954856587,FR
+2954856588,2954856591,GB
+2954856592,2954856607,PL
+2954856608,2954856611,BE
+2954856612,2954856619,ES
+2954856620,2954856623,GB
+2954856624,2954856627,IT
+2954856628,2954856631,GB
+2954856632,2954856635,FR
+2954856636,2954856639,DE
+2954856640,2954856671,IT
+2954856672,2954856687,NL
+2954856688,2954856691,BE
+2954856692,2954856699,FR
+2954856700,2954856959,PL
+2954856960,2954856975,ES
+2954856976,2954856979,PL
+2954856980,2954856983,FR
+2954856984,2954856987,GB
+2954856988,2954856991,FR
+2954856992,2954856999,FI
+2954857000,2954857007,PL
+2954857008,2954857087,FR
+2954857088,2954857091,PL
+2954857092,2954857095,CZ
+2954857096,2954857099,PL
+2954857100,2954857111,GB
+2954857112,2954857115,PL
+2954857116,2954857119,IE
+2954857120,2954857135,PT
+2954857136,2954857143,LT
+2954857144,2954857151,ES
+2954857152,2954857215,IE
+2954857216,2954857343,GB
+2954857344,2954857351,ES
+2954857352,2954857355,PT
+2954857356,2954857359,IT
+2954857360,2954857367,FR
+2954857368,2954857375,PT
+2954857376,2954857383,PL
+2954857384,2954857407,GB
+2954857408,2954857423,CH
+2954857424,2954857431,GB
+2954857432,2954857435,IT
+2954857436,2954857439,PL
+2954857440,2954857471,PT
+2954857472,2954857503,FR
+2954857504,2954857519,IT
+2954857520,2954857523,FR
+2954857524,2954857527,IE
+2954857528,2954857531,GB
+2954857532,2954857535,NL
+2954857536,2954857551,CH
+2954857552,2954857567,IT
+2954857568,2954857571,PL
+2954857572,2954857575,PT
+2954857576,2954857583,FR
+2954857584,2954857599,ES
+2954857600,2954857663,IE
+2954857664,2954857695,FR
+2954857696,2954857699,IE
+2954857700,2954857703,ES
+2954857704,2954857707,PL
+2954857708,2954857711,ES
+2954857712,2954857727,IE
+2954857728,2954857751,FR
+2954857752,2954857755,IE
+2954857756,2954857759,PL
+2954857760,2954857823,FR
+2954857824,2954857855,ES
+2954857856,2954857983,IE
+2954857984,2954857999,IT
+2954858000,2954858015,FR
+2954858016,2954858023,PL
+2954858024,2954858027,ES
+2954858028,2954858031,IT
+2954858032,2954858035,DE
+2954858036,2954858039,PL
+2954858040,2954858043,FR
+2954858044,2954858047,IE
+2954858048,2954858055,PT
+2954858056,2954858059,IE
+2954858060,2954858063,PL
+2954858064,2954858079,IE
+2954858080,2954858095,PT
+2954858096,2954858111,ES
+2954858112,2954858143,DE
+2954858144,2954858175,ES
+2954858176,2954858191,PL
+2954858192,2954858207,IE
+2954858208,2954858239,IT
+2954858240,2954858271,NL
+2954858272,2954858303,GB
+2954858304,2954858335,DE
+2954858336,2954858351,FR
+2954858352,2954858383,PL
+2954858384,2954858415,FR
+2954858416,2954858423,GB
+2954858424,2954858427,DE
+2954858428,2954858431,IE
+2954858432,2954858439,GB
+2954858440,2954858443,FR
+2954858444,2954858447,GB
+2954858448,2954858463,IT
+2954858464,2954858479,FR
+2954858480,2954858483,NL
+2954858484,2954858487,DE
+2954858488,2954858491,IT
+2954858492,2954858495,NL
+2954858496,2954858751,ES
+2954858752,2954858815,IE
+2954858816,2954858819,ES
+2954858820,2954858823,PT
+2954858824,2954858827,GB
+2954858828,2954858831,CZ
+2954858832,2954858847,IE
+2954858848,2954858879,GB
+2954858880,2954858895,FR
+2954858896,2954858911,ES
+2954858912,2954858943,DE
+2954858944,2954858975,ES
+2954858976,2954858991,FR
+2954858992,2954859007,GB
+2954859008,2954859023,FR
+2954859024,2954859027,IT
+2954859028,2954859031,PT
+2954859032,2954859043,FR
+2954859044,2954859055,DE
+2954859056,2954859071,FR
+2954859072,2954859079,PL
+2954859080,2954859087,GB
+2954859088,2954859103,BE
+2954859104,2954859119,PT
+2954859120,2954859123,FR
+2954859124,2954859127,NL
+2954859128,2954859135,PT
+2954859136,2954859239,FR
+2954859240,2954859243,ES
+2954859244,2954859247,PL
+2954859248,2954859263,ES
+2954859264,2954859271,FR
+2954859272,2954859275,PL
+2954859276,2954859279,ES
+2954859280,2954859295,FR
+2954859296,2954859327,PT
+2954859328,2954859343,GB
+2954859344,2954859391,FR
+2954859392,2954859423,IT
+2954859424,2954859455,GB
+2954859456,2954859487,NL
+2954859488,2954859495,FR
+2954859496,2954859503,IT
+2954859504,2954859519,GB
+2954859520,2954859551,DE
+2954859552,2954859559,FR
+2954859560,2954859575,IT
+2954859576,2954859579,FI
+2954859580,2954859583,LT
+2954859584,2954859647,FR
+2954859648,2954859655,ES
+2954859656,2954859663,NL
+2954859664,2954859679,FR
+2954859680,2954859695,CH
+2954859696,2954859703,FR
+2954859704,2954859707,GB
+2954859708,2954859711,DE
+2954859712,2954859775,FR
+2954859776,2954859807,PL
+2954859808,2954859839,GB
+2954859840,2954859903,PL
+2954859904,2954859935,DE
+2954859936,2954859951,FR
+2954859952,2954859955,PL
+2954859956,2954859959,GB
+2954859960,2954859963,ES
+2954859964,2954860031,PL
+2954860032,2954860063,DE
+2954860064,2954860095,FR
+2954860096,2954860103,GB
+2954860104,2954860111,FR
+2954860112,2954860127,DE
+2954860128,2954860131,ES
+2954860132,2954860135,FR
+2954860136,2954860151,PL
+2954860152,2954860167,IE
+2954860168,2954860171,PL
+2954860172,2954860175,IE
+2954860176,2954860183,DE
+2954860184,2954860191,ES
+2954860192,2954860223,PT
+2954860224,2954860231,BE
+2954860232,2954860239,ES
+2954860240,2954860255,FR
+2954860256,2954860259,PT
+2954860260,2954860263,FI
+2954860264,2954860267,CZ
+2954860268,2954860271,PL
+2954860272,2954860275,GB
+2954860276,2954860319,FR
+2954860320,2954860327,DE
+2954860328,2954860335,PL
+2954860336,2954860351,CH
+2954860352,2954860415,FR
+2954860416,2954860423,PL
+2954860424,2954860427,FR
+2954860428,2954860431,IE
+2954860432,2954860439,FR
+2954860440,2954860443,IT
+2954860444,2954860447,FI
+2954860448,2954860479,PT
+2954860480,2954860483,GB
+2954860484,2954860487,FR
+2954860488,2954860491,GB
+2954860492,2954860495,DE
+2954860496,2954860511,FR
+2954860512,2954860543,DE
+2954860544,2954860799,CZ
+2954860800,2954860863,IE
+2954860864,2954861067,FR
+2954861068,2954861071,GB
+2954861072,2954861087,FR
+2954861088,2954861119,CH
+2954861120,2954861135,FR
+2954861136,2954861143,GB
+2954861144,2954861167,ES
+2954861168,2954861183,FR
+2954861184,2954861191,IT
+2954861192,2954861195,FR
+2954861196,2954861199,IE
+2954861200,2954861215,GB
+2954861216,2954861231,FR
+2954861232,2954861239,PL
+2954861240,2954861247,FR
+2954861248,2954861311,PL
+2954861312,2954861323,FR
+2954861324,2954861327,IT
+2954861328,2954861343,NL
+2954861344,2954861359,FR
+2954861360,2954861363,IE
+2954861364,2954861367,FR
+2954861368,2954861371,ES
+2954861372,2954861375,PT
+2954861376,2954861407,DE
+2954861408,2954861423,FR
+2954861424,2954861431,CH
+2954861432,2954861571,FR
+2954861572,2954861575,GB
+2954861576,2954861599,FR
+2954861600,2954861615,PT
+2954861616,2954861623,FR
+2954861624,2954861631,IT
+2954861632,2954861635,NL
+2954861636,2954861639,GB
+2954861640,2954861647,PL
+2954861648,2954861651,FR
+2954861652,2954861655,GB
+2954861656,2954861659,FR
+2954861660,2954861663,PL
+2954861664,2954861671,ES
+2954861672,2954861675,NL
+2954861676,2954861687,PL
+2954861688,2954861691,GB
+2954861692,2954861695,FR
+2954861696,2954861763,GB
+2954861764,2954861767,PL
+2954861768,2954861779,FR
+2954861780,2954861783,DE
+2954861784,2954861787,FR
+2954861788,2954861791,PL
+2954861792,2954861823,GB
+2954861824,2954861827,PL
+2954861828,2954861831,GB
+2954861832,2954861835,DE
+2954861836,2954861839,PL
+2954861840,2954861843,GB
+2954861844,2954861847,PL
+2954861848,2954861863,FR
+2954861864,2954861867,NL
+2954861868,2954861871,FR
+2954861872,2954861887,IE
+2954861888,2954861919,PT
+2954861920,2954861923,PL
+2954861924,2954861927,ES
+2954861928,2954861935,FR
+2954861936,2954861943,DE
+2954861944,2954861955,FR
+2954861956,2954861967,GB
+2954861968,2954861975,IE
+2954861976,2954861983,DE
+2954861984,2954862015,GB
+2954862016,2954862047,NL
+2954862048,2954862143,FR
+2954862144,2954862207,ES
+2954862208,2954862211,PL
+2954862212,2954862215,PT
+2954862216,2954862219,FR
+2954862220,2954862223,DE
+2954862224,2954862239,FR
+2954862240,2954862247,IT
+2954862248,2954862271,FR
+2954862272,2954862303,FI
+2954862304,2954870783,FR
2954870784,2954870787,DE
2954870788,2954870799,GB
2954870800,2954870831,FR
2954870832,2954870835,PL
2954870836,2954870839,GB
2954870840,2954870843,DE
-2954870844,2954870847,GB
+2954870844,2954870847,FR
2954870848,2954870863,PL
2954870864,2954870871,FR
2954870872,2954870875,ES
@@ -70370,13 +72000,16 @@
2954871636,2954871639,ES
2954871640,2954871643,FR
2954871644,2954871647,IT
-2954871648,2954871663,FR
-2954871664,2954871671,IE
-2954871672,2954871703,FR
+2954871648,2954871667,FR
+2954871668,2954871671,PL
+2954871672,2954871695,FR
+2954871696,2954871703,DE
2954871704,2954871707,CH
-2954871708,2954871711,IT
-2954871712,2954871807,FR
-2954871808,2954871823,NL
+2954871708,2954871711,GB
+2954871712,2954871743,FR
+2954871744,2954871759,PT
+2954871760,2954871807,FR
+2954871808,2954871823,ES
2954871824,2954871831,FR
2954871832,2954871839,PL
2954871840,2954871887,FR
@@ -70391,17 +72024,20 @@
2954871948,2954871951,DE
2954871952,2954871955,ES
2954871956,2954871959,PT
-2954871960,2954871967,FR
+2954871960,2954871963,IE
+2954871964,2954871967,FR
2954871968,2954871999,PL
2954872000,2954872323,FR
2954872324,2954872327,PL
2954872328,2954872335,DE
-2954872336,2954872351,ES
+2954872336,2954872351,FR
2954872352,2954872383,DE
2954872384,2954872415,GB
-2954872416,2954872419,DE
+2954872416,2954872419,ES
2954872420,2954872435,PL
-2954872436,2954872587,FR
+2954872436,2954872439,FR
+2954872440,2954872447,PL
+2954872448,2954872587,FR
2954872588,2954872591,DE
2954872592,2954872607,IT
2954872608,2954872639,FR
@@ -70428,8 +72064,296 @@
2954873632,2954873635,NL
2954873636,2954873639,PL
2954873640,2954873647,FR
-2954873648,2954873663,GB
-2954873664,2954887167,FR
+2954873648,2954873663,PL
+2954873664,2954873679,IT
+2954873680,2954873695,FR
+2954873696,2954873727,ES
+2954873728,2954873759,FR
+2954873760,2954873791,DE
+2954873792,2954873803,FR
+2954873804,2954873807,NL
+2954873808,2954873815,DE
+2954873816,2954873819,FI
+2954873820,2954873831,FR
+2954873832,2954873835,IT
+2954873836,2954873839,PL
+2954873840,2954873847,IT
+2954873848,2954873851,GB
+2954873852,2954873855,PL
+2954873856,2954874111,GB
+2954874112,2954874367,FR
+2954874368,2954874371,BE
+2954874372,2954874375,GB
+2954874376,2954874387,FR
+2954874388,2954874391,PL
+2954874392,2954874415,IE
+2954874416,2954874419,NL
+2954874420,2954874423,FR
+2954874424,2954874427,GB
+2954874428,2954874431,ES
+2954874432,2954874495,FR
+2954874496,2954874559,NL
+2954874560,2954874567,GB
+2954874568,2954874591,FR
+2954874592,2954874623,PT
+2954874624,2954874627,BE
+2954874628,2954874631,FR
+2954874632,2954874639,GB
+2954874640,2954874647,ES
+2954874648,2954874651,FR
+2954874652,2954874655,PL
+2954874656,2954874671,FR
+2954874672,2954874675,PL
+2954874676,2954874679,GB
+2954874680,2954874687,FR
+2954874688,2954874719,IE
+2954874720,2954874751,FI
+2954874752,2954874799,IE
+2954874800,2954874815,GB
+2954874816,2954874827,FR
+2954874828,2954874831,PL
+2954874832,2954874855,FR
+2954874856,2954874859,GB
+2954874860,2954874863,LT
+2954874864,2954874867,FR
+2954874868,2954874871,PL
+2954874872,2954874919,FR
+2954874920,2954874923,PL
+2954874924,2954874927,FR
+2954874928,2954874943,PL
+2954874944,2954874975,IE
+2954874976,2954874979,PL
+2954874980,2954874983,DE
+2954874984,2954874987,GB
+2954874988,2954874991,PL
+2954874992,2954875007,IE
+2954875008,2954875039,FR
+2954875040,2954875047,PL
+2954875048,2954875051,FR
+2954875052,2954875055,NL
+2954875056,2954875063,IT
+2954875064,2954875067,DE
+2954875068,2954875071,FI
+2954875072,2954875075,NL
+2954875076,2954875079,GB
+2954875080,2954875099,FR
+2954875100,2954875103,PL
+2954875104,2954875199,FR
+2954875200,2954875203,PL
+2954875204,2954875207,DE
+2954875208,2954875215,NL
+2954875216,2954875231,FR
+2954875232,2954875263,ES
+2954875264,2954875295,FR
+2954875296,2954875311,PL
+2954875312,2954875327,FR
+2954875328,2954875359,PL
+2954875360,2954875383,FR
+2954875384,2954875391,DE
+2954875392,2954875463,ES
+2954875464,2954875467,NL
+2954875468,2954875471,GB
+2954875472,2954875487,FR
+2954875488,2954875491,LT
+2954875492,2954875495,GB
+2954875496,2954875503,IT
+2954875504,2954875519,FR
+2954875520,2954875543,PL
+2954875544,2954875551,FR
+2954875552,2954875583,PL
+2954875584,2954875587,ES
+2954875588,2954875591,IT
+2954875592,2954875599,FR
+2954875600,2954875615,PT
+2954875616,2954875623,PL
+2954875624,2954875627,DE
+2954875628,2954875631,ES
+2954875632,2954875639,FR
+2954875640,2954875647,BE
+2954875648,2954875651,ES
+2954875652,2954875655,BE
+2954875656,2954875659,FR
+2954875660,2954875663,PT
+2954875664,2954875671,ES
+2954875672,2954875679,FR
+2954875680,2954875711,PT
+2954875712,2954875775,IE
+2954875776,2954875903,PT
+2954875904,2954875907,IT
+2954875908,2954875911,CH
+2954875912,2954875935,FR
+2954875936,2954875951,PL
+2954875952,2954875999,IE
+2954876000,2954876031,GB
+2954876032,2954876039,IT
+2954876040,2954876043,FR
+2954876044,2954876047,GB
+2954876048,2954876051,ES
+2954876052,2954876055,NL
+2954876056,2954876059,PL
+2954876060,2954876063,ES
+2954876064,2954876079,FR
+2954876080,2954876095,PL
+2954876096,2954876111,FR
+2954876112,2954876119,IE
+2954876120,2954876123,CZ
+2954876124,2954876127,NL
+2954876128,2954876147,FR
+2954876148,2954876151,BE
+2954876152,2954876159,FR
+2954876160,2954876167,FI
+2954876168,2954876175,NL
+2954876176,2954876191,FR
+2954876192,2954876223,PT
+2954876224,2954876231,FR
+2954876232,2954876235,PL
+2954876236,2954876239,IE
+2954876240,2954876247,PL
+2954876248,2954876287,ES
+2954876288,2954876351,FR
+2954876352,2954876383,ES
+2954876384,2954876391,FR
+2954876392,2954876395,DE
+2954876396,2954876399,IE
+2954876400,2954876403,GB
+2954876404,2954876407,NL
+2954876408,2954876411,LT
+2954876412,2954876415,DE
+2954876416,2954876575,PT
+2954876576,2954876579,ES
+2954876580,2954876583,FR
+2954876584,2954876587,ES
+2954876588,2954876591,DE
+2954876592,2954876639,IE
+2954876640,2954876643,DE
+2954876644,2954876647,IT
+2954876648,2954876655,FR
+2954876656,2954876671,BE
+2954876672,2954876703,PT
+2954876704,2954876719,FR
+2954876720,2954876727,GB
+2954876728,2954876731,PL
+2954876732,2954876735,DE
+2954876736,2954876767,IT
+2954876768,2954876783,GB
+2954876784,2954876795,FR
+2954876796,2954876799,DE
+2954876800,2954876863,IE
+2954876864,2954876895,DE
+2954876896,2954876899,GB
+2954876900,2954876903,IT
+2954876904,2954876959,FR
+2954876960,2954876975,DE
+2954876976,2954876983,PL
+2954876984,2954876987,FR
+2954876988,2954876991,ES
+2954876992,2954877007,PL
+2954877008,2954877023,CZ
+2954877024,2954877027,ES
+2954877028,2954877031,PL
+2954877032,2954877035,FR
+2954877036,2954877039,GB
+2954877040,2954877055,FR
+2954877056,2954877059,PL
+2954877060,2954877063,GB
+2954877064,2954877071,DE
+2954877072,2954877087,CH
+2954877088,2954877119,GB
+2954877120,2954877151,ES
+2954877152,2954877159,NL
+2954877160,2954877163,PL
+2954877164,2954877167,FR
+2954877168,2954877183,DE
+2954877184,2954877455,FR
+2954877456,2954877459,PL
+2954877460,2954877463,FR
+2954877464,2954877471,DE
+2954877472,2954877503,FR
+2954877504,2954877519,ES
+2954877520,2954877523,BE
+2954877524,2954877527,ES
+2954877528,2954877535,FI
+2954877536,2954877539,PL
+2954877540,2954877547,FR
+2954877548,2954877551,PL
+2954877552,2954877583,FR
+2954877584,2954877595,DE
+2954877596,2954877599,PT
+2954877600,2954877615,PL
+2954877616,2954877631,NL
+2954877632,2954877663,FR
+2954877664,2954877667,GB
+2954877668,2954877671,PL
+2954877672,2954877675,FR
+2954877676,2954877679,PL
+2954877680,2954877727,FR
+2954877728,2954877743,IE
+2954877744,2954877775,FR
+2954877776,2954877779,IT
+2954877780,2954877783,A1
+2954877784,2954877791,IT
+2954877792,2954877819,FR
+2954877820,2954877823,PL
+2954877824,2954877963,FR
+2954877964,2954877967,DE
+2954877968,2954877983,PT
+2954877984,2954877991,LT
+2954877992,2954877999,PL
+2954878000,2954878007,FR
+2954878008,2954878011,IT
+2954878012,2954878031,GB
+2954878032,2954878035,NL
+2954878036,2954878039,FR
+2954878040,2954878047,PL
+2954878048,2954878063,FR
+2954878064,2954878079,IT
+2954878080,2954878095,FR
+2954878096,2954878103,ES
+2954878104,2954878111,FR
+2954878112,2954878143,PT
+2954878144,2954878207,FR
+2954878208,2954878463,ES
+2954878464,2954878471,CH
+2954878472,2954878475,FR
+2954878476,2954878495,NL
+2954878496,2954878499,GB
+2954878500,2954878511,FR
+2954878512,2954878559,IE
+2954878560,2954878575,FR
+2954878576,2954878579,GB
+2954878580,2954878583,DE
+2954878584,2954878591,GB
+2954878592,2954878607,BE
+2954878608,2954878623,FI
+2954878624,2954878631,PL
+2954878632,2954878635,IT
+2954878636,2954878639,FR
+2954878640,2954878655,IT
+2954878656,2954878687,PL
+2954878688,2954878695,FR
+2954878696,2954878703,IE
+2954878704,2954878707,IT
+2954878708,2954878711,PL
+2954878712,2954878719,ES
+2954878720,2954878763,FR
+2954878764,2954878767,GB
+2954878768,2954878783,FR
+2954878784,2954878847,IE
+2954878848,2954878855,FR
+2954878856,2954878863,IE
+2954878864,2954878879,IT
+2954878880,2954878883,ES
+2954878884,2954878887,PL
+2954878888,2954878891,FR
+2954878892,2954878895,GB
+2954878896,2954878899,DE
+2954878900,2954878903,GB
+2954878904,2954878915,FR
+2954878916,2954878919,PL
+2954878920,2954878931,FR
+2954878932,2954878939,GB
+2954878940,2954878943,PL
+2954878944,2954887167,FR
2954887168,2954891263,UA
2954891264,2954895359,IT
2954895360,2954897407,RU
@@ -70440,7 +72364,9 @@
2954905600,2954907647,IE
2954907648,2954909695,GB
2954909696,2954911743,DE
-2954911744,2954919935,IE
+2954911744,2954918911,IE
+2954918912,2954919423,NL
+2954919424,2954919935,IE
2954919936,2954928127,RU
2954928128,2954932223,PL
2954932224,2954936319,RU
@@ -70600,9 +72526,13 @@
2954942728,2954942731,RO
2954942732,2954942743,DE
2954942744,2954942747,TR
-2954942748,2954942843,DE
+2954942748,2954942839,DE
+2954942840,2954942843,FR
2954942844,2954942847,TR
-2954942848,2954942943,DE
+2954942848,2954942851,FR
+2954942852,2954942871,GB
+2954942872,2954942875,FR
+2954942876,2954942943,DE
2954942944,2954942947,TR
2954942948,2954942979,DE
2954942980,2954942983,TR
@@ -70686,14 +72616,15 @@
2954948608,2954950655,RU
2954950656,2954952703,ES
2954952704,2955018239,TR
-2955018240,2955051007,IE
-2955051008,2955055103,NL
-2955055104,2955069439,IE
+2955018240,2955026431,FR
+2955026432,2955034623,NL
+2955034624,2955051007,IE
+2955051008,2955067391,NL
+2955067392,2955069439,IE
2955069440,2955071487,NL
2955071488,2955073535,IE
2955073536,2955075583,FR
-2955075584,2955081727,NL
-2955081728,2955083775,IE
+2955075584,2955083775,NL
2955083776,2955149311,GB
2955149312,2955411455,UA
2955411456,2955673599,TR
@@ -70727,7 +72658,8 @@
2956496896,2956500991,IR
2956500992,2956507135,RU
2956507136,2956508159,NL
-2956508160,2956508671,RU
+2956508160,2956508415,RU
+2956508416,2956508671,FR
2956508672,2956509183,NL
2956509184,2956517375,GB
2956517376,2956521471,NL
@@ -70750,6 +72682,7 @@
2956587008,2956589055,FR
2956589056,2956593151,GB
2956593152,2956595199,ES
+2956595200,2956597247,PL
2956597248,2956599295,NL
2956599296,2956607487,RU
2956607488,2956611583,PS
@@ -70767,8 +72700,16 @@
2956822528,2956823551,SE
2956823552,2956824575,US
2956824576,2956826623,PT
-2956826624,2956828671,DK
-2956828672,2956836863,AT
+2956826624,2956827647,US
+2956827648,2956828671,DK
+2956828672,2956828767,BA
+2956828768,2956828799,AT
+2956828800,2956828943,BA
+2956828944,2956828959,AT
+2956828960,2956828991,BA
+2956828992,2956829055,AT
+2956829056,2956829695,BA
+2956829696,2956836863,AT
2956836864,2956853247,SK
2956853248,2956865535,HR
2956865536,2956869631,IT
@@ -70777,8 +72718,8 @@
2956888064,2956890111,BE
2956890112,2956892159,IR
2956892160,2956894207,IT
-2956894208,2956895743,BE
-2956895744,2956898303,NL
+2956894208,2956896255,BE
+2956896256,2956898303,NL
2956898304,2956902399,RU
2956902400,2956904447,NL
2956904448,2956906495,DK
@@ -70794,7 +72735,83 @@
2957068288,2957070335,LU
2957070336,2957074431,IT
2957074432,2957082623,RU
-2957082624,2957115391,DE
+2957082624,2957093887,DE
+2957093888,2957096959,CH
+2957096960,2957105912,DE
+2957105913,2957105918,AT
+2957105919,2957106168,DE
+2957106169,2957106174,AT
+2957106175,2957106424,DE
+2957106425,2957106430,AT
+2957106431,2957106680,DE
+2957106681,2957106686,AT
+2957106687,2957106936,DE
+2957106937,2957106942,AT
+2957106943,2957107192,DE
+2957107193,2957107198,AT
+2957107199,2957107448,DE
+2957107449,2957107454,AT
+2957107455,2957107704,DE
+2957107705,2957107710,AT
+2957107711,2957107960,DE
+2957107961,2957107966,AT
+2957107967,2957108216,DE
+2957108217,2957108222,AT
+2957108223,2957108472,DE
+2957108473,2957108478,AT
+2957108479,2957108728,DE
+2957108729,2957108734,AT
+2957108735,2957108984,DE
+2957108985,2957108990,AT
+2957108991,2957109240,DE
+2957109241,2957109246,AT
+2957109247,2957109496,DE
+2957109497,2957109502,AT
+2957109503,2957109752,DE
+2957109753,2957109758,AT
+2957109759,2957110008,DE
+2957110009,2957110014,AT
+2957110015,2957110264,DE
+2957110265,2957110270,AT
+2957110271,2957110520,DE
+2957110521,2957110526,AT
+2957110527,2957110776,DE
+2957110777,2957110782,AT
+2957110783,2957111032,DE
+2957111033,2957111038,AT
+2957111039,2957111288,DE
+2957111289,2957111294,AT
+2957111295,2957111544,DE
+2957111545,2957111550,AT
+2957111551,2957111800,DE
+2957111801,2957111806,AT
+2957111807,2957112056,DE
+2957112057,2957112062,AT
+2957112063,2957112312,DE
+2957112313,2957112318,AT
+2957112319,2957112568,DE
+2957112569,2957112574,AT
+2957112575,2957112824,DE
+2957112825,2957112830,AT
+2957112831,2957113080,DE
+2957113081,2957113086,AT
+2957113087,2957113336,DE
+2957113337,2957113342,AT
+2957113343,2957113592,DE
+2957113593,2957113598,AT
+2957113599,2957113848,DE
+2957113849,2957113854,AT
+2957113855,2957114104,DE
+2957114105,2957114110,AT
+2957114111,2957114360,DE
+2957114361,2957114366,AT
+2957114367,2957114616,DE
+2957114617,2957114622,AT
+2957114623,2957114872,DE
+2957114873,2957114878,AT
+2957114879,2957115128,DE
+2957115129,2957115134,AT
+2957115135,2957115391,DE
2957115392,2957180927,AT
2957180928,2957189119,UA
2957189120,2957193215,LV
@@ -70819,7 +72836,11 @@
2957201872,2957201887,RU
2957201888,2957201903,KR
2957201904,2957201919,TW
-2957201920,2957202431,US
+2957201920,2957202175,US
+2957202176,2957202179,GB
+2957202180,2957202183,BR
+2957202184,2957202187,CA
+2957202188,2957202431,US
2957202432,2957202463,GB
2957202464,2957202467,PL
2957202468,2957202471,KR
@@ -70908,7 +72929,17 @@
2957203120,2957203123,US
2957203124,2957203127,MT
2957203128,2957203131,RS
-2957203132,2957203455,US
+2957203132,2957203199,US
+2957203200,2957203203,AU
+2957203204,2957203207,US
+2957203208,2957203211,SE
+2957203212,2957203215,FR
+2957203216,2957203219,ZA
+2957203220,2957203223,CH
+2957203224,2957203227,DE
+2957203228,2957203231,PL
+2957203232,2957203263,GB
+2957203264,2957203455,US
2957203456,2957205503,FR
2957205504,2957213695,PS
2957213696,2957221887,FR
@@ -70944,7 +72975,8 @@
2957901824,2958032895,PT
2958032896,2958557183,ES
2958557184,2958819327,TR
-2958819328,2958884863,CY
+2958819328,2958884863,GR
+2958884864,2958950399,FI
2958950400,2959081471,DE
2959081472,2959089663,RU
2959089664,2959093759,PL
@@ -70962,13 +72994,50 @@
2959128576,2959130623,RU
2959130624,2959138815,UA
2959138816,2959147007,RU
+2959147008,2959149055,UA
+2959149056,2959151103,CZ
+2959151104,2959155199,PL
+2959155200,2959159295,RU
+2959159296,2959161343,PL
+2959161344,2959163391,RO
+2959163392,2959167487,UA
+2959167488,2959171583,PL
+2959171584,2959175679,RU
+2959175680,2959179775,UA
+2959179776,2959181823,RU
+2959181824,2959183871,PL
+2959183872,2959187967,RO
+2959187968,2959204351,RU
+2959204352,2959208447,RO
+2959208448,2959210495,CZ
+2959210496,2959212543,PL
+2959212544,2959220735,UA
+2959220736,2959224831,RO
+2959224832,2959226879,UA
+2959226880,2959228927,RO
+2959228928,2959237119,UA
+2959237120,2959241215,CZ
+2959241216,2959245311,PL
+2959245312,2959253503,RU
+2959253504,2959255551,DE
+2959255552,2959261695,RU
+2959261696,2959278079,KZ
+2959278080,2959343615,DE
+2959343616,2959351807,UA
+2959351808,2959353855,DE
+2959353856,2959355903,RU
+2959355904,2959357951,RO
+2959357952,2959359999,UA
+2959360000,2959384575,RU
+2959384576,2959392767,UA
2961178624,2965372927,FR
2965372928,2965766143,RU
2965766144,2965897215,DE
2965897216,2966028287,IT
2966028288,2966159359,QA
2966159360,2966290431,AE
-2966421504,2966683647,RU
+2966290432,2966421503,IT
+2966421504,2966945791,RU
2969567232,2977955839,BR
2986344448,2987393023,DE
2987393024,2987397119,IM
@@ -71196,11 +73265,8 @@
2988179456,2988441599,SE
2988441600,2988441603,CH
2988441604,2988441607,GB
-2988441608,2988441611,DE
-2988441612,2988441615,CH
-2988441616,2988441647,FR
-2988441648,2988441651,GB
-2988441652,2988441655,FR
+2988441608,2988441615,CH
+2988441616,2988441655,FR
2988441656,2988441663,DE
2988441664,2988441695,IT
2988441696,2988441791,FR
@@ -71229,7 +73295,7 @@
2988441984,2988441991,FR
2988441992,2988441995,ES
2988441996,2988441999,PT
-2988442000,2988442003,FR
+2988442000,2988442003,PL
2988442004,2988442007,ES
2988442008,2988442047,FR
2988442048,2988442063,GB
@@ -71261,7 +73327,9 @@
2988442920,2988442923,LT
2988442924,2988442927,GB
2988442928,2988442975,FR
-2988442976,2988443007,GB
+2988442976,2988442995,GB
+2988442996,2988442999,IE
+2988443000,2988443007,GB
2988443008,2988443023,PT
2988443024,2988443027,CZ
2988443028,2988443031,BE
@@ -71336,7 +73404,9 @@
2988445984,2988446207,DE
2988446208,2988446271,PL
2988446272,2988446275,IT
-2988446276,2988446291,FR
+2988446276,2988446279,FR
+2988446280,2988446287,ES
+2988446288,2988446291,FR
2988446292,2988446295,ES
2988446296,2988446299,GB
2988446300,2988446307,FR
@@ -71374,9 +73444,7 @@
2988448608,2988448639,ES
2988448640,2988448671,GB
2988448672,2988448691,IT
-2988448692,2988448695,DE
-2988448696,2988448699,IT
-2988448700,2988448703,LT
+2988448692,2988448703,DE
2988448704,2988448767,GB
2988448768,2988448783,FR
2988448784,2988448815,PL
@@ -71385,9 +73453,7 @@
2988448896,2988448899,PT
2988448900,2988448903,PL
2988448904,2988448907,ES
-2988448908,2988448959,FR
-2988448960,2988448991,DE
-2988448992,2988449007,FR
+2988448908,2988449007,FR
2988449008,2988449023,GB
2988449024,2988449055,PL
2988449056,2988449087,ES
@@ -71397,8 +73463,15 @@
2988449124,2988449127,DE
2988449128,2988449135,ES
2988449136,2988449151,FR
-2988449152,2988449279,PL
-2988449280,2988449535,GB
+2988449152,2988449167,PL
+2988449168,2988449175,GB
+2988449176,2988449183,FR
+2988449184,2988449199,PL
+2988449200,2988449203,FR
+2988449204,2988449207,PL
+2988449208,2988449215,ES
+2988449216,2988449247,FR
+2988449248,2988449535,GB
2988449536,2988449579,FR
2988449580,2988449583,PL
2988449584,2988449631,FR
@@ -71433,7 +73506,8 @@
2988458280,2988458283,ES
2988458284,2988458295,FR
2988458296,2988458299,GB
-2988458300,2988458319,ES
+2988458300,2988458303,ES
+2988458304,2988458319,FR
2988458320,2988458323,CZ
2988458324,2988458331,FR
2988458332,2988458335,GB
@@ -71470,16 +73544,21 @@
2988459184,2988459199,PL
2988459200,2988459223,FR
2988459224,2988459231,DE
-2988459232,2988459235,IT
+2988459232,2988459235,FR
2988459236,2988459239,PL
2988459240,2988459243,FR
2988459244,2988459247,ES
2988459248,2988459251,LT
2988459252,2988459255,GB
2988459256,2988459259,FR
-2988459260,2988459263,NL
+2988459260,2988459263,PL
2988459264,2988459519,ES
-2988459520,2988459583,FR
+2988459520,2988459535,FR
+2988459536,2988459539,GB
+2988459540,2988459543,PL
+2988459544,2988459547,ES
+2988459548,2988459551,PL
+2988459552,2988459583,FR
2988459584,2988459599,ES
2988459600,2988459603,GB
2988459604,2988459615,FR
@@ -71497,7 +73576,7 @@
2988459716,2988459719,FR
2988459720,2988459727,DE
2988459728,2988459731,FR
-2988459732,2988459735,BE
+2988459732,2988459735,ES
2988459736,2988459743,PL
2988459744,2988459747,ES
2988459748,2988459751,PL
@@ -71545,7 +73624,7 @@
2988460336,2988460339,FR
2988460340,2988460343,GB
2988460344,2988460367,FR
-2988460368,2988460375,ES
+2988460368,2988460375,PL
2988460376,2988460543,FR
2988460544,2988460547,GB
2988460548,2988460551,DE
@@ -71556,9 +73635,7 @@
2988460616,2988460623,PT
2988460624,2988460679,FR
2988460680,2988460687,DE
-2988460688,2988460719,FR
-2988460720,2988460735,ES
-2988460736,2988460755,FR
+2988460688,2988460755,FR
2988460756,2988460759,PT
2988460760,2988460767,FR
2988460768,2988460799,PL
@@ -71590,7 +73667,7 @@
2988461424,2988461431,IT
2988461432,2988461435,PT
2988461436,2988461439,BE
-2988461440,2988461471,FR
+2988461440,2988461471,FI
2988461472,2988461475,PL
2988461476,2988461479,IE
2988461480,2988461483,CZ
@@ -71603,8 +73680,12 @@
2988461520,2988461523,GB
2988461524,2988461559,FR
2988461560,2988461567,GB
-2988461568,2988461599,FR
-2988461600,2988461615,BE
+2988461568,2988461583,FR
+2988461584,2988461587,ES
+2988461588,2988461591,GB
+2988461592,2988461595,ES
+2988461596,2988461599,GB
+2988461600,2988461615,FR
2988461616,2988461623,IT
2988461624,2988461695,FR
2988461696,2988461699,DE
@@ -71633,8 +73714,8 @@
2988461872,2988461879,FR
2988461880,2988461883,ES
2988461884,2988461887,PL
-2988461888,2988461903,FR
-2988461904,2988461911,ES
+2988461888,2988461907,FR
+2988461908,2988461911,ES
2988461912,2988461915,IT
2988461916,2988461919,NL
2988461920,2988461935,FR
@@ -71741,8 +73822,7 @@
2988463836,2988463839,FR
2988463840,2988463871,PL
2988463872,2988463907,FR
-2988463908,2988463911,PL
-2988463912,2988463915,FR
+2988463908,2988463915,PL
2988463916,2988463919,GB
2988463920,2988463939,FR
2988463940,2988463943,DE
@@ -71772,9 +73852,7 @@
2988464356,2988464359,FR
2988464360,2988464363,PL
2988464364,2988464367,GB
-2988464368,2988464511,FR
-2988464512,2988464519,PT
-2988464520,2988464527,FR
+2988464368,2988464527,FR
2988464528,2988464543,DE
2988464544,2988464551,FR
2988464552,2988464555,IT
@@ -71795,12 +73873,12 @@
2988464796,2988464799,GB
2988464800,2988464815,DE
2988464816,2988464819,FR
-2988464820,2988464823,NL
+2988464820,2988464823,GB
2988464824,2988464827,ES
-2988464828,2988464831,GB
+2988464828,2988464831,PL
2988464832,2988464895,ES
2988464896,2988464911,PL
-2988464912,2988464915,CH
+2988464912,2988464915,FR
2988464916,2988464919,DE
2988464920,2988464923,FI
2988464924,2988464927,FR
@@ -71814,7 +73892,8 @@
2988464968,2988464971,PT
2988464972,2988464975,PL
2988464976,2988465215,FR
-2988465216,2988465223,ES
+2988465216,2988465219,ES
+2988465220,2988465223,IE
2988465224,2988465235,FR
2988465236,2988465239,ES
2988465240,2988465279,FR
@@ -71860,12 +73939,13 @@
2988465620,2988465623,ES
2988465624,2988465631,FR
2988465632,2988465647,IT
-2988465648,2988465663,CZ
+2988465648,2988465655,CZ
+2988465656,2988465663,GB
2988465664,2988466047,FR
2988466048,2988466111,PL
2988466112,2988466115,FR
2988466116,2988466127,NL
-2988466128,2988466131,PT
+2988466128,2988466131,PL
2988466132,2988466139,FR
2988466140,2988466143,PL
2988466144,2988466159,NL
@@ -71905,15 +73985,17 @@
2988482888,2988482891,ES
2988482892,2988482895,PL
2988482896,2988482927,GB
-2988482928,2988482935,FR
-2988482936,2988482939,PL
+2988482928,2988482931,FR
+2988482932,2988482939,PL
2988482940,2988482943,LT
2988482944,2988482959,PL
2988482960,2988482975,CZ
2988482976,2988482979,DE
2988482980,2988482983,GB
2988482984,2988482987,DE
-2988482988,2988483091,FR
+2988482988,2988483035,FR
+2988483036,2988483039,GB
+2988483040,2988483091,FR
2988483092,2988483095,BE
2988483096,2988483099,FR
2988483100,2988483103,PL
@@ -71982,9 +74064,10 @@
2988484024,2988484031,FR
2988484032,2988484039,IT
2988484040,2988484047,NL
-2988484048,2988484051,FR
+2988484048,2988484051,ES
2988484052,2988484055,GB
-2988484056,2988484095,FR
+2988484056,2988484063,FR
+2988484064,2988484095,GB
2988484096,2988484111,DE
2988484112,2988484127,FR
2988484128,2988484131,PT
@@ -72074,7 +74157,7 @@
2988485616,2988485631,GB
2988485632,2988485663,ES
2988485664,2988485671,PL
-2988485672,2988485675,ES
+2988485672,2988485675,DE
2988485676,2988485683,FR
2988485684,2988485687,PL
2988485688,2988485691,GB
@@ -72113,7 +74196,11 @@
2988486076,2988486079,ES
2988486080,2988486083,BE
2988486084,2988486087,IT
-2988486088,2988486111,FR
+2988486088,2988486095,FR
+2988486096,2988486099,CH
+2988486100,2988486103,CZ
+2988486104,2988486107,DE
+2988486108,2988486111,IE
2988486112,2988486135,PL
2988486136,2988486139,FR
2988486140,2988486143,GB
@@ -72124,9 +74211,9 @@
2988486180,2988486183,DE
2988486184,2988486191,IE
2988486192,2988486195,IT
-2988486196,2988486199,DE
+2988486196,2988486199,FR
2988486200,2988486207,PT
-2988486208,2988486211,ES
+2988486208,2988486211,PL
2988486212,2988486215,DE
2988486216,2988486219,ES
2988486220,2988486223,IT
@@ -72135,8 +74222,7 @@
2988486236,2988486239,ES
2988486240,2988486287,PL
2988486288,2988486291,FR
-2988486292,2988486295,DE
-2988486296,2988486299,GB
+2988486292,2988486299,GB
2988486300,2988486319,PL
2988486320,2988486323,IT
2988486324,2988486327,PT
@@ -72144,7 +74230,9 @@
2988486344,2988486347,FR
2988486348,2988486351,ES
2988486352,2988486399,FR
-2988486400,2988486431,GB
+2988486400,2988486415,PL
+2988486416,2988486423,FR
+2988486424,2988486431,PT
2988486432,2988486447,FR
2988486448,2988486463,ES
2988486464,2988486471,BE
@@ -72152,7 +74240,8 @@
2988486476,2988486479,PL
2988486480,2988486495,IE
2988486496,2988486503,DE
-2988486504,2988486515,ES
+2988486504,2988486511,PL
+2988486512,2988486515,DE
2988486516,2988486527,PL
2988486528,2988486575,FR
2988486576,2988486579,PL
@@ -72167,10 +74256,24 @@
2988486644,2988486647,GB
2988486648,2988486651,ES
2988486652,2988486655,PL
-2988486656,2988486719,GB
-2988486720,2988486735,CZ
-2988486736,2988486751,FR
-2988486752,2988486783,GB
+2988486656,2988486671,FR
+2988486672,2988486675,DE
+2988486676,2988486679,FR
+2988486680,2988486687,ES
+2988486688,2988486691,PL
+2988486692,2988486695,FR
+2988486696,2988486699,ES
+2988486700,2988486711,PL
+2988486712,2988486719,IT
+2988486720,2988486735,FR
+2988486736,2988486743,ES
+2988486744,2988486747,FR
+2988486748,2988486751,GB
+2988486752,2988486759,PL
+2988486760,2988486763,ES
+2988486764,2988486767,FR
+2988486768,2988486775,ES
+2988486776,2988486783,BE
2988486784,2988486787,DE
2988486788,2988486795,FR
2988486796,2988486799,PL
@@ -72211,18 +74314,20 @@
2988488128,2988488159,FR
2988488160,2988488175,ES
2988488176,2988488179,GB
-2988488180,2988488183,DE
+2988488180,2988488183,FR
2988488184,2988488187,IT
2988488188,2988488191,DE
2988488192,2988488479,FR
2988488480,2988488487,PL
2988488488,2988488491,FR
2988488492,2988488495,ES
-2988488496,2988488511,FR
-2988488512,2988488543,ES
-2988488544,2988488575,FR
-2988488576,2988488607,NL
-2988488608,2988488639,IT
+2988488496,2988488543,FR
+2988488544,2988488555,GB
+2988488556,2988488563,ES
+2988488564,2988488567,FR
+2988488568,2988488571,ES
+2988488572,2988488575,GB
+2988488576,2988488639,FR
2988488640,2988488647,ES
2988488648,2988488655,IT
2988488656,2988488663,PL
@@ -72325,14 +74430,13 @@
2988490192,2988490195,GB
2988490196,2988490199,PT
2988490200,2988490203,DE
-2988490204,2988490207,ES
-2988490208,2988490223,FR
+2988490204,2988490223,FR
2988490224,2988490227,DE
2988490228,2988490231,GB
2988490232,2988490239,ES
2988490240,2988490247,PL
2988490248,2988490251,ES
-2988490252,2988490255,FR
+2988490252,2988490255,GB
2988490256,2988490271,PL
2988490272,2988490287,ES
2988490288,2988490295,FR
@@ -72340,11 +74444,14 @@
2988490304,2988490319,ES
2988490320,2988490335,FR
2988490336,2988490367,PT
-2988490368,2988490379,FR
+2988490368,2988490371,ES
+2988490372,2988490375,NL
+2988490376,2988490379,FR
2988490380,2988490383,ES
2988490384,2988490399,FR
2988490400,2988490407,GB
-2988490408,2988490415,NL
+2988490408,2988490411,NL
+2988490412,2988490415,ES
2988490416,2988490423,GB
2988490424,2988490463,FR
2988490464,2988490623,PL
@@ -72358,8 +74465,7 @@
2988498984,2988498991,FR
2988498992,2988499007,PL
2988499008,2988499051,DE
-2988499052,2988499055,IT
-2988499056,2988499063,FR
+2988499052,2988499063,FR
2988499064,2988499067,DE
2988499068,2988499071,FR
2988499072,2988499103,PL
@@ -72370,8 +74476,7 @@
2988499144,2988499151,DE
2988499152,2988499167,FR
2988499168,2988499199,ES
-2988499200,2988499327,FR
-2988499328,2988499343,NL
+2988499200,2988499343,FR
2988499344,2988499347,PL
2988499348,2988499351,FR
2988499352,2988499359,IT
@@ -72429,7 +74534,7 @@
2988499848,2988499851,DE
2988499852,2988499855,PL
2988499856,2988499871,ES
-2988499872,2988499903,CH
+2988499872,2988499903,IE
2988499904,2988499907,FR
2988499908,2988499911,BE
2988499912,2988499915,FR
@@ -72439,15 +74544,15 @@
2988499928,2988499935,FR
2988499936,2988499967,IE
2988499968,2988500223,FR
-2988500224,2988500255,NL
+2988500224,2988500255,ES
2988500256,2988500271,IT
2988500272,2988500287,BE
2988500288,2988500303,PL
2988500304,2988500307,FR
-2988500308,2988500311,IT
+2988500308,2988500311,DE
2988500312,2988500315,ES
2988500316,2988500319,DE
-2988500320,2988500335,IT
+2988500320,2988500335,FR
2988500336,2988500339,DE
2988500340,2988500343,IE
2988500344,2988500347,FR
@@ -72472,9 +74577,7 @@
2988500680,2988500687,PL
2988500688,2988500703,NL
2988500704,2988500711,PL
-2988500712,2988500735,FR
-2988500736,2988500751,IE
-2988500752,2988500767,FR
+2988500712,2988500767,FR
2988500768,2988500771,PT
2988500772,2988500775,ES
2988500776,2988500779,GB
@@ -72550,18 +74653,17 @@
2988502080,2988502095,IE
2988502096,2988502099,FI
2988502100,2988502103,CZ
-2988502104,2988502111,PT
-2988502112,2988502143,PL
+2988502104,2988502143,PL
2988502144,2988502207,FR
2988502208,2988502223,GB
2988502224,2988502255,FR
-2988502256,2988502263,GB
+2988502256,2988502263,DE
2988502264,2988502267,ES
2988502268,2988502271,DE
2988502272,2988502399,FR
2988502400,2988502407,NL
2988502408,2988502411,FR
-2988502412,2988502415,CH
+2988502412,2988502415,NL
2988502416,2988502431,DE
2988502432,2988502447,FR
2988502448,2988502451,IE
@@ -72588,7 +74690,8 @@
2988502640,2988502655,FR
2988502656,2988502719,DE
2988502720,2988502723,ES
-2988502724,2988502731,FR
+2988502724,2988502727,BE
+2988502728,2988502731,GB
2988502732,2988502735,PL
2988502736,2988502751,FR
2988502752,2988502783,ES
@@ -72622,8 +74725,9 @@
2988503024,2988503031,GB
2988503032,2988503035,ES
2988503036,2988503039,GB
-2988503040,2988503079,FR
-2988503080,2988503103,GB
+2988503040,2988503071,FR
+2988503072,2988503075,NL
+2988503076,2988503103,GB
2988503104,2988503107,ES
2988503108,2988503111,NL
2988503112,2988503119,PL
@@ -72653,9 +74757,8 @@
2988503536,2988503551,FI
2988503552,2988503871,FR
2988503872,2988503903,DE
-2988503904,2988503911,FI
-2988503912,2988503919,NL
-2988503920,2988503927,FR
+2988503904,2988503919,FR
+2988503920,2988503927,ES
2988503928,2988503931,IT
2988503932,2988503935,NL
2988503936,2988503939,FR
@@ -72664,8 +74767,8 @@
2988503948,2988503951,IE
2988503952,2988503987,FR
2988503988,2988504007,PL
-2988504008,2988504015,FR
-2988504016,2988504019,GB
+2988504008,2988504015,BE
+2988504016,2988504019,FR
2988504020,2988504023,BE
2988504024,2988504031,FR
2988504032,2988504063,ES
@@ -72690,7 +74793,11 @@
2988504432,2988504435,FR
2988504436,2988504439,ES
2988504440,2988504443,FR
-2988504444,2988504463,GB
+2988504444,2988504447,GB
+2988504448,2988504451,BE
+2988504452,2988504455,ES
+2988504456,2988504459,PL
+2988504460,2988504463,GB
2988504464,2988504467,DE
2988504468,2988504471,ES
2988504472,2988504479,PL
@@ -72711,14 +74818,17 @@
2988504744,2988504751,GB
2988504752,2988504767,FR
2988504768,2988504799,ES
-2988504800,2988504815,PL
-2988504816,2988504863,FR
+2988504800,2988504823,PL
+2988504824,2988504827,DE
+2988504828,2988504863,FR
2988504864,2988504879,PL
2988504880,2988504959,FR
2988504960,2988504963,PT
2988504964,2988504967,FR
2988504968,2988504975,BE
-2988504976,2988504991,FR
+2988504976,2988504983,FR
+2988504984,2988504987,ES
+2988504988,2988504991,FR
2988504992,2988505023,CZ
2988505024,2988505087,FR
2988505088,2988505151,NL
@@ -72735,11 +74845,20 @@
2988505312,2988505315,DE
2988505316,2988505319,ES
2988505320,2988505323,PL
-2988505324,2988505327,FR
+2988505324,2988505327,ES
2988505328,2988505343,PL
-2988505344,2988505439,FR
+2988505344,2988505375,DE
+2988505376,2988505391,FR
+2988505392,2988505399,PL
+2988505400,2988505407,ES
+2988505408,2988505439,FR
2988505440,2988505455,PL
-2988505456,2988505487,FR
+2988505456,2988505459,FI
+2988505460,2988505463,CH
+2988505464,2988505471,IT
+2988505472,2988505475,ES
+2988505476,2988505479,NL
+2988505480,2988505487,IE
2988505488,2988505503,PL
2988505504,2988505599,FR
2988505600,2988505603,DE
@@ -72760,7 +74879,7 @@
2988505752,2988505755,CH
2988505756,2988505759,PL
2988505760,2988505775,FR
-2988505776,2988505791,ES
+2988505776,2988505791,GB
2988505792,2988505807,FR
2988505808,2988505811,PL
2988505812,2988505815,DE
@@ -72768,7 +74887,15 @@
2988505820,2988505823,PL
2988505824,2988505839,FR
2988505840,2988505843,CH
-2988505844,2988506111,FR
+2988505844,2988505851,FR
+2988505852,2988505855,PL
+2988505856,2988505919,IE
+2988505920,2988505935,GB
+2988505936,2988505951,PL
+2988505952,2988505967,GB
+2988505968,2988505971,BE
+2988505972,2988505975,GB
+2988505976,2988506111,FR
2988506112,2988506143,BE
2988506144,2988506175,PT
2988506176,2988506191,IT
@@ -72802,8 +74929,8 @@
2988506544,2988506551,DE
2988506552,2988506559,FR
2988506560,2988506563,DE
-2988506564,2988506567,A2
-2988506568,2988506571,GB
+2988506564,2988506567,GB
+2988506568,2988506571,PL
2988506572,2988506575,CH
2988506576,2988506623,FR
2988506624,2988506687,PL
@@ -72894,8 +75021,7 @@
2988507884,2988507887,GB
2988507888,2988507903,ES
2988507904,2988507919,PL
-2988507920,2988507923,DE
-2988507924,2988507927,IT
+2988507920,2988507927,DE
2988507928,2988507935,BE
2988507936,2988507951,FR
2988507952,2988507955,DE
@@ -72911,8 +75037,7 @@
2988508036,2988508039,CZ
2988508040,2988508047,FR
2988508048,2988508055,GB
-2988508056,2988508063,ES
-2988508064,2988508067,FR
+2988508056,2988508067,ES
2988508068,2988508071,PL
2988508072,2988508079,FR
2988508080,2988508095,ES
@@ -72945,8 +75070,8 @@
2988508428,2988508431,CZ
2988508432,2988508435,FR
2988508436,2988508439,DE
-2988508440,2988508447,PL
-2988508448,2988508479,FR
+2988508440,2988508455,PL
+2988508456,2988508479,FR
2988508480,2988508543,PT
2988508544,2988508607,GB
2988508608,2988508671,IT
@@ -72973,7 +75098,9 @@
2988508944,2988508947,DE
2988508948,2988508951,FR
2988508952,2988508959,ES
-2988508960,2988508991,FR
+2988508960,2988508983,FR
+2988508984,2988508987,DE
+2988508988,2988508991,PL
2988508992,2988509055,NL
2988509056,2988509119,FR
2988509120,2988509151,IT
@@ -73016,7 +75143,8 @@
2988509620,2988509623,GB
2988509624,2988509627,CZ
2988509628,2988509631,IT
-2988509632,2988509711,FR
+2988509632,2988509695,FR
+2988509696,2988509711,IT
2988509712,2988509715,IE
2988509716,2988509719,GB
2988509720,2988509727,IT
@@ -73148,7 +75276,7 @@
2988511740,2988511743,FR
2988511744,2988511747,PL
2988511748,2988511751,GB
-2988511752,2988511759,CZ
+2988511752,2988511759,IT
2988511760,2988511775,FR
2988511776,2988511807,GB
2988511808,2988511823,ES
@@ -73239,12 +75367,14 @@
2988512840,2988512847,DE
2988512848,2988512851,ES
2988512852,2988512855,DE
-2988512856,2988512895,FR
+2988512856,2988512879,FR
+2988512880,2988512895,DE
2988512896,2988512899,PL
-2988512900,2988512903,GB
+2988512900,2988512903,ES
2988512904,2988512907,PL
-2988512908,2988512943,FR
-2988512944,2988512951,GB
+2988512908,2988512911,ES
+2988512912,2988512943,FR
+2988512944,2988512951,ES
2988512952,2988512955,FR
2988512956,2988512959,LT
2988512960,2988512963,ES
@@ -73288,7 +75418,9 @@
2988513332,2988513343,FR
2988513344,2988513351,ES
2988513352,2988513359,IT
-2988513360,2988513375,GB
+2988513360,2988513363,DE
+2988513364,2988513367,FR
+2988513368,2988513375,ES
2988513376,2988513379,FR
2988513380,2988513383,PT
2988513384,2988513387,FR
@@ -73381,7 +75513,8 @@
2988514656,2988514671,FR
2988514672,2988514675,CH
2988514676,2988514679,IT
-2988514680,2988514687,FR
+2988514680,2988514683,GB
+2988514684,2988514687,DE
2988514688,2988514719,GB
2988514720,2988514735,ES
2988514736,2988514739,FR
@@ -73429,7 +75562,19 @@
2988523740,2988523743,FR
2988523744,2988523775,PT
2988523776,2988524031,FR
-2988524032,2988524159,DE
+2988524032,2988524035,DE
+2988524036,2988524039,LT
+2988524040,2988524047,ES
+2988524048,2988524055,FR
+2988524056,2988524063,CZ
+2988524064,2988524067,PL
+2988524068,2988524075,GB
+2988524076,2988524079,ES
+2988524080,2988524083,GB
+2988524084,2988524087,IT
+2988524088,2988524111,FR
+2988524112,2988524127,IT
+2988524128,2988524159,FR
2988524160,2988524163,ES
2988524164,2988524167,FR
2988524168,2988524175,ES
@@ -73452,7 +75597,8 @@
2988524272,2988524287,DE
2988524288,2988524291,ES
2988524292,2988524295,IT
-2988524296,2988524303,FR
+2988524296,2988524299,CZ
+2988524300,2988524303,FR
2988524304,2988524307,IT
2988524308,2988524319,GB
2988524320,2988524351,FR
@@ -73471,8 +75617,10 @@
2988524576,2988524591,FR
2988524592,2988524603,PL
2988524604,2988524607,ES
-2988524608,2988524623,GB
-2988524624,2988524639,FR
+2988524608,2988524627,GB
+2988524628,2988524631,IE
+2988524632,2988524635,DE
+2988524636,2988524639,FR
2988524640,2988524671,DE
2988524672,2988524735,FR
2988524736,2988524751,GB
@@ -73515,7 +75663,10 @@
2988526608,2988526615,DE
2988526616,2988526655,FR
2988526656,2988526663,PL
-2988526664,2988526687,FR
+2988526664,2988526671,FR
+2988526672,2988526679,DE
+2988526680,2988526683,ES
+2988526684,2988526687,FR
2988526688,2988526703,ES
2988526704,2988526711,FR
2988526712,2988526715,ES
@@ -73529,17 +75680,19 @@
2988526864,2988526867,GB
2988526868,2988526871,FR
2988526872,2988526875,DE
-2988526876,2988526911,FR
+2988526876,2988526879,PL
+2988526880,2988526911,FR
2988526912,2988526927,GB
2988526928,2988526935,DE
2988526936,2988526943,PL
2988526944,2988526951,DE
-2988526952,2988526955,IE
-2988526956,2988526975,FR
+2988526952,2988526955,FR
+2988526956,2988526959,IT
+2988526960,2988526975,FR
2988526976,2988526991,PL
2988526992,2988526995,DE
-2988526996,2988526999,ES
-2988527000,2988527055,FR
+2988526996,2988527003,ES
+2988527004,2988527055,FR
2988527056,2988527071,BE
2988527072,2988527087,FR
2988527088,2988527095,GB
@@ -73569,7 +75722,8 @@
2988527440,2988527451,PL
2988527452,2988527455,PT
2988527456,2988527459,LT
-2988527460,2988527475,FR
+2988527460,2988527463,IE
+2988527464,2988527475,FR
2988527476,2988527479,ES
2988527480,2988527487,FR
2988527488,2988527503,GB
@@ -73579,7 +75733,7 @@
2988527536,2988527551,GB
2988527552,2988527583,PL
2988527584,2988527591,GB
-2988527592,2988527595,IT
+2988527592,2988527595,IE
2988527596,2988527599,DE
2988527600,2988527603,NL
2988527604,2988527607,FR
@@ -73595,11 +75749,11 @@
2988527680,2988527683,ES
2988527684,2988527695,FR
2988527696,2988527711,GB
-2988527712,2988527743,FR
-2988527744,2988527747,IE
+2988527712,2988527747,FR
2988527748,2988527751,ES
2988527752,2988527755,DE
-2988527756,2988527823,FR
+2988527756,2988527759,PL
+2988527760,2988527823,FR
2988527824,2988527827,ES
2988527828,2988527831,DE
2988527832,2988527839,ES
@@ -73614,12 +75768,14 @@
2988527968,2988527983,PL
2988527984,2988527999,FR
2988528000,2988528007,IT
-2988528008,2988528015,ES
+2988528008,2988528011,ES
+2988528012,2988528015,PL
2988528016,2988528063,IE
2988528064,2988528071,GB
2988528072,2988528075,NL
2988528076,2988528079,BE
-2988528080,2988528127,FR
+2988528080,2988528095,ES
+2988528096,2988528127,FR
2988528128,2988528159,GB
2988528160,2988528175,ES
2988528176,2988528179,CH
@@ -73630,13 +75786,15 @@
2988528208,2988528215,FR
2988528216,2988528219,IE
2988528220,2988528223,DE
-2988528224,2988528231,CH
+2988528224,2988528227,FR
+2988528228,2988528231,IE
2988528232,2988528235,GB
2988528236,2988528239,FR
2988528240,2988528263,GB
2988528264,2988528267,PL
2988528268,2988528271,FR
-2988528272,2988528303,GB
+2988528272,2988528287,IE
+2988528288,2988528303,GB
2988528304,2988528351,FR
2988528352,2988528383,DE
2988528384,2988528399,GB
@@ -73645,7 +75803,7 @@
2988528424,2988528431,NL
2988528432,2988528435,PL
2988528436,2988528439,FR
-2988528440,2988528447,ES
+2988528440,2988528447,GB
2988528448,2988528451,DE
2988528452,2988528455,IT
2988528456,2988528459,GB
@@ -73663,15 +75821,9 @@
2988528644,2988528647,PL
2988528648,2988528671,FR
2988528672,2988528703,DE
-2988528704,2988528715,ES
-2988528716,2988528723,IT
-2988528724,2988528727,GB
-2988528728,2988528731,FR
-2988528732,2988528735,DE
-2988528736,2988528739,FI
-2988528740,2988528743,IE
-2988528744,2988528747,NL
-2988528748,2988528759,PL
+2988528704,2988528735,IE
+2988528736,2988528755,FR
+2988528756,2988528759,PL
2988528760,2988528763,GB
2988528764,2988528767,FR
2988528768,2988528771,DE
@@ -73721,23 +75873,28 @@
2988529340,2988529343,DE
2988529344,2988529351,PL
2988529352,2988529359,GB
-2988529360,2988529375,IE
+2988529360,2988529375,IT
2988529376,2988529383,GB
2988529384,2988529387,DE
2988529388,2988529391,FR
2988529392,2988529407,PL
-2988529408,2988529423,FR
+2988529408,2988529411,IT
+2988529412,2988529415,NL
+2988529416,2988529419,PT
+2988529420,2988529423,CH
2988529424,2988529431,DE
2988529432,2988529439,FR
2988529440,2988529455,PL
2988529456,2988529535,FR
2988529536,2988529567,FI
2988529568,2988529583,FR
-2988529584,2988529599,GB
+2988529584,2988529591,ES
+2988529592,2988529595,FR
+2988529596,2988529599,GB
2988529600,2988529607,IT
2988529608,2988529631,FR
2988529632,2988529647,LT
-2988529648,2988529663,FI
+2988529648,2988529663,FR
2988529664,2988529679,PL
2988529680,2988529703,FR
2988529704,2988529707,DE
@@ -73848,7 +76005,8 @@
2988531260,2988531271,GB
2988531272,2988531279,ES
2988531280,2988531287,PT
-2988531288,2988531295,ES
+2988531288,2988531291,FR
+2988531292,2988531295,PL
2988531296,2988531311,IE
2988531312,2988531319,FR
2988531320,2988531323,PT
@@ -73861,7 +76019,7 @@
2988531400,2988531403,DE
2988531404,2988531427,PL
2988531428,2988531451,FR
-2988531452,2988531455,CH
+2988531452,2988531455,GB
2988531456,2988535807,FR
2988535808,2988537855,ES
2988537856,2988539935,FR
@@ -73888,9 +76046,7 @@
2988540276,2988540279,PL
2988540280,2988540287,FR
2988540288,2988540303,BE
-2988540304,2988540319,FR
-2988540320,2988540351,PT
-2988540352,2988540363,FR
+2988540304,2988540363,FR
2988540364,2988540367,PL
2988540368,2988540375,FR
2988540376,2988540379,GB
@@ -73941,7 +76097,9 @@
2988540800,2988540831,FR
2988540832,2988540839,PL
2988540840,2988540847,GB
-2988540848,2988540931,FR
+2988540848,2988540855,FR
+2988540856,2988540863,IT
+2988540864,2988540931,FR
2988540932,2988540935,DE
2988540936,2988540943,FR
2988540944,2988540959,ES
@@ -73970,8 +76128,7 @@
2988541336,2988541343,FR
2988541344,2988541347,GB
2988541348,2988541351,IT
-2988541352,2988541355,IE
-2988541356,2988541359,IT
+2988541352,2988541359,IE
2988541360,2988541367,ES
2988541368,2988541371,PL
2988541372,2988541375,GB
@@ -74069,8 +76226,7 @@
2988542444,2988542447,FR
2988542448,2988542455,PL
2988542456,2988542459,FR
-2988542460,2988542463,ES
-2988542464,2988542495,NL
+2988542460,2988542495,ES
2988542496,2988542527,FR
2988542528,2988542535,DE
2988542536,2988542539,NL
@@ -74082,8 +76238,12 @@
2988542596,2988542599,FI
2988542600,2988542603,GB
2988542604,2988542611,FR
-2988542612,2988542623,DE
-2988542624,2988542655,FR
+2988542612,2988542627,DE
+2988542628,2988542631,FR
+2988542632,2988542635,CZ
+2988542636,2988542639,GB
+2988542640,2988542651,FR
+2988542652,2988542655,PL
2988542656,2988542719,BE
2988542720,2988542783,CH
2988542784,2988542847,CZ
@@ -74160,8 +76320,8 @@
2988543744,2988543935,FR
2988543936,2988543947,PL
2988543948,2988543959,BE
-2988543960,2988543967,PL
-2988543968,2988543999,FR
+2988543960,2988543983,PL
+2988543984,2988543999,PT
2988544000,2988544015,DE
2988544016,2988544023,GB
2988544024,2988544031,IE
@@ -74169,7 +76329,8 @@
2988544036,2988544039,FR
2988544040,2988544043,DE
2988544044,2988544047,GB
-2988544048,2988544063,FR
+2988544048,2988544055,FR
+2988544056,2988544063,FI
2988544064,2988544127,DE
2988544128,2988544159,GB
2988544160,2988544163,FR
@@ -74177,7 +76338,7 @@
2988544168,2988544175,GB
2988544176,2988544179,CH
2988544180,2988544183,IT
-2988544184,2988544191,DE
+2988544184,2988544191,FR
2988544192,2988544227,ES
2988544228,2988544271,FR
2988544272,2988544275,PL
@@ -74194,7 +76355,8 @@
2988544320,2988544323,PL
2988544324,2988544327,ES
2988544328,2988544331,PL
-2988544332,2988544351,FR
+2988544332,2988544335,A1
+2988544336,2988544351,FR
2988544352,2988544355,PL
2988544356,2988544359,DE
2988544360,2988544367,FR
@@ -74287,12 +76449,12 @@
2988545552,2988545555,PL
2988545556,2988545559,IT
2988545560,2988545563,FR
-2988545564,2988545567,DE
-2988545568,2988545571,NL
-2988545572,2988545575,DE
+2988545564,2988545575,DE
2988545576,2988545579,FR
2988545580,2988545583,ES
-2988545584,2988545663,FR
+2988545584,2988545599,FR
+2988545600,2988545631,DE
+2988545632,2988545663,FR
2988545664,2988545695,ES
2988545696,2988545727,DE
2988545728,2988545791,FR
@@ -74312,7 +76474,8 @@
2988545928,2988545931,BE
2988545932,2988545935,DE
2988545936,2988545943,FR
-2988545944,2988545967,NL
+2988545944,2988545947,CZ
+2988545948,2988545967,FR
2988545968,2988545971,IT
2988545972,2988545975,DE
2988545976,2988545979,FR
@@ -74353,7 +76516,8 @@
2988546368,2988546439,FR
2988546440,2988546443,DE
2988546444,2988546447,FR
-2988546448,2988546463,ES
+2988546448,2988546451,IE
+2988546452,2988546463,ES
2988546464,2988546527,FR
2988546528,2988546535,BE
2988546536,2988546539,FR
@@ -74440,8 +76604,8 @@
2988547256,2988547263,FR
2988547264,2988547267,GB
2988547268,2988547271,ES
-2988547272,2988547279,NL
-2988547280,2988547295,FR
+2988547272,2988547275,GB
+2988547276,2988547295,FR
2988547296,2988547303,BE
2988547304,2988547311,FR
2988547312,2988547327,PL
@@ -74467,13 +76631,12 @@
2988547548,2988547567,FR
2988547568,2988547583,DE
2988547584,2988547599,ES
-2988547600,2988547615,FR
-2988547616,2988547647,PL
-2988547648,2988547655,FR
+2988547600,2988547655,FR
2988547656,2988547663,PL
2988547664,2988547679,FR
2988547680,2988547711,CH
-2988547712,2988547751,FR
+2988547712,2988547743,FR
+2988547744,2988547751,PT
2988547752,2988547759,ES
2988547760,2988547775,FR
2988547776,2988547807,ES
@@ -74489,8 +76652,9 @@
2988547972,2988547975,DE
2988547976,2988547983,PL
2988547984,2988548015,FR
-2988548016,2988548031,ES
-2988548032,2988548047,FR
+2988548016,2988548019,ES
+2988548020,2988548023,LT
+2988548024,2988548047,FR
2988548048,2988548055,ES
2988548056,2988548059,PL
2988548060,2988548063,FR
@@ -74520,7 +76684,7 @@
2988556492,2988556495,DE
2988556496,2988556527,FR
2988556528,2988556535,PL
-2988556536,2988556539,GB
+2988556536,2988556539,FR
2988556540,2988556543,DE
2988556544,2988556831,FR
2988556832,2988556839,DE
@@ -74536,8 +76700,7 @@
2988556912,2988556919,NL
2988556920,2988556927,PL
2988556928,2988556943,FR
-2988556944,2988556959,PL
-2988556960,2988556963,ES
+2988556944,2988556963,PL
2988556964,2988556967,FR
2988556968,2988556975,BE
2988556976,2988556979,FI
@@ -74605,8 +76768,7 @@
2988557768,2988557771,PL
2988557772,2988557775,FR
2988557776,2988557791,BE
-2988557792,2988557823,FR
-2988557824,2988557951,DE
+2988557792,2988557951,FR
2988557952,2988557983,LT
2988557984,2988557999,FR
2988558000,2988558015,IE
@@ -74641,7 +76803,8 @@
2988558720,2988558727,PL
2988558728,2988558731,IT
2988558732,2988558735,PT
-2988558736,2988558751,GB
+2988558736,2988558747,FR
+2988558748,2988558751,GB
2988558752,2988558767,FR
2988558768,2988558783,CH
2988558784,2988558831,FR
@@ -74650,9 +76813,11 @@
2988558884,2988558887,BE
2988558888,2988558891,GB
2988558892,2988558895,NL
-2988558896,2988558903,FR
+2988558896,2988558899,CH
+2988558900,2988558903,FR
2988558904,2988558907,NL
-2988558908,2988558935,GB
+2988558908,2988558911,PL
+2988558912,2988558935,GB
2988558936,2988558939,PL
2988558940,2988558943,GB
2988558944,2988558975,FR
@@ -74660,17 +76825,14 @@
2988559008,2988559011,BE
2988559012,2988559015,PL
2988559016,2988559039,FR
-2988559040,2988559055,GB
-2988559056,2988559071,LT
+2988559040,2988559071,GB
2988559072,2988559103,ES
2988559104,2988559135,PL
2988559136,2988559139,DE
2988559140,2988559151,PL
2988559152,2988559231,FR
2988559232,2988559247,DE
-2988559248,2988559255,FR
-2988559256,2988559259,DE
-2988559260,2988559263,GB
+2988559248,2988559263,FR
2988559264,2988559295,LT
2988559296,2988559359,PL
2988559360,2988559631,FR
@@ -74682,7 +76844,8 @@
2988559700,2988559703,PL
2988559704,2988559707,DE
2988559708,2988559711,PL
-2988559712,2988559727,FR
+2988559712,2988559723,FR
+2988559724,2988559727,IT
2988559728,2988559731,DE
2988559732,2988559735,PL
2988559736,2988559743,GB
@@ -74703,7 +76866,9 @@
2988560512,2988560519,IT
2988560520,2988560523,DE
2988560524,2988560527,BE
-2988560528,2988560543,FR
+2988560528,2988560531,ES
+2988560532,2988560535,FR
+2988560536,2988560543,IE
2988560544,2988560575,GB
2988560576,2988560591,ES
2988560592,2988560595,NL
@@ -74736,8 +76901,8 @@
2988560960,2988560975,FR
2988560976,2988560991,ES
2988560992,2988560995,FR
-2988560996,2988561007,DE
-2988561008,2988561023,FR
+2988560996,2988560999,DE
+2988561000,2988561023,FR
2988561024,2988561027,BE
2988561028,2988561039,FR
2988561040,2988561043,GB
@@ -74746,7 +76911,7 @@
2988561052,2988561055,GB
2988561056,2988561059,FR
2988561060,2988561071,PL
-2988561072,2988561075,NL
+2988561072,2988561075,ES
2988561076,2988561079,LT
2988561080,2988561083,PL
2988561084,2988561087,GB
@@ -74803,7 +76968,8 @@
2988561848,2988561855,FR
2988561856,2988561871,IE
2988561872,2988561875,CH
-2988561876,2988561887,FR
+2988561876,2988561879,A1
+2988561880,2988561887,FR
2988561888,2988561903,PL
2988561904,2988561983,FR
2988561984,2988562015,DE
@@ -74828,7 +76994,7 @@
2988562688,2988562703,GB
2988562704,2988562707,PL
2988562708,2988562711,DE
-2988562712,2988562719,GB
+2988562712,2988562719,FR
2988562720,2988562815,BE
2988562816,2988562823,PL
2988562824,2988562831,PT
@@ -74836,8 +77002,7 @@
2988562836,2988562839,NL
2988562840,2988562843,LT
2988562844,2988562847,PL
-2988562848,2988562855,NL
-2988562856,2988562863,DE
+2988562848,2988562863,GB
2988562864,2988562911,FR
2988562912,2988562943,PL
2988562944,2988563011,FR
@@ -74859,7 +77024,7 @@
2988563152,2988563183,FR
2988563184,2988563187,CZ
2988563188,2988563191,PL
-2988563192,2988563199,CH
+2988563192,2988563199,FR
2988563200,2988563455,IE
2988563456,2988563487,FR
2988563488,2988563499,GB
@@ -75158,6 +77323,7 @@
2991538176,2991554559,SI
2991554560,2991571455,GB
2991571456,2991587327,IT
+2991587328,2991718399,SA
2991718400,2991849471,CH
2991849472,2991980543,NL
2991980544,2991980807,UA
@@ -75184,11 +77350,7 @@
2991985920,2991986175,JP
2991986176,2991986431,UA
2991986432,2991986687,JP
-2991986688,2991988263,UA
-2991988264,2991988271,IN
-2991988272,2992014727,UA
-2992014728,2992014735,IN
-2992014736,2992111615,UA
+2991986688,2992111615,UA
2992111616,2992373759,KZ
2992373760,2992635903,UA
2992635904,2993684479,GB
@@ -75198,6 +77360,26 @@
2994733056,2994798591,GR
2994798592,2994929663,RU
2994929664,2994995199,IR
+2994995200,2994997247,RU
+2994997248,2994999295,BE
+2994999296,2995003391,FR
+2995003392,2995007487,BH
+2995007488,2995009535,TR
+2995009536,2995011583,ES
+2995011584,2995013631,DE
+2995013632,2995015679,SE
+2995015680,2995017727,BG
+2995017728,2995019775,IT
+2995019776,2995021823,RU
+2995021824,2995023871,IT
+2995023872,2995044351,MD
+2995044352,2995046399,ES
+2995046400,2995048447,RU
+2995048448,2995050495,NL
+2995050496,2995052543,AL
+2995052544,2995056639,DK
+2995056640,2995058687,DE
+2995058688,2995060735,SE
2995060736,2995126271,UA
2995126272,2995191807,GE
2995191808,2995257343,LB
@@ -75280,9 +77462,7 @@
2997000960,2997001471,DE
2997001472,2997001727,BZ
2997001728,2997001983,TR
-2997001984,2997003023,DE
-2997003024,2997003039,US
-2997003040,2997003071,DE
+2997001984,2997003071,DE
2997003072,2997003135,RU
2997003136,2997003199,DE
2997003200,2997003263,RU
@@ -75302,8 +77482,7 @@
2997005376,2997005439,GR
2997005440,2997005567,GB
2997005568,2997005823,BZ
-2997005824,2997006079,DE
-2997006080,2997006335,GB
+2997005824,2997006335,DE
2997006336,2997006591,TR
2997006592,2997006655,DE
2997006656,2997006719,TR
@@ -75318,8 +77497,7 @@
2997009024,2997018623,DE
2997018624,2997019135,GB
2997019136,2997019391,TR
-2997019392,2997019647,GB
-2997019648,2997019711,DE
+2997019392,2997019711,DE
2997019712,2997019903,US
2997019904,2997020415,DE
2997020416,2997020671,CA
@@ -75327,9 +77505,7 @@
2997020720,2997020735,SE
2997020736,2997020799,DE
2997020800,2997020863,CA
-2997020864,2997021183,DE
-2997021184,2997021695,GB
-2997021696,2997022079,DE
+2997020864,2997022079,DE
2997022080,2997022143,GB
2997022144,2997022239,DE
2997022240,2997022303,NL
@@ -75338,8 +77514,7 @@
2997022752,2997022783,TR
2997022784,2997022847,DE
2997022848,2997023231,BZ
-2997023232,2997023287,DE
-2997023288,2997023295,US
+2997023232,2997023295,DE
2997023296,2997023423,IN
2997023424,2997024255,DE
2997024256,2997024511,TR
@@ -75742,100 +77917,7 @@
3001966592,3001968639,NL
3001968640,3001970687,BE
3001970688,3001974783,RU
-3001974784,3001975567,GB
-3001975568,3001975575,LK
-3001975576,3001975591,US
-3001975592,3001975599,MY
-3001975600,3001975615,CN
-3001975616,3001975623,UA
-3001975624,3001975631,RU
-3001975632,3001975655,GB
-3001975656,3001975663,RU
-3001975664,3001975671,FR
-3001975672,3001975679,CN
-3001975680,3001975687,TW
-3001975688,3001975695,US
-3001975696,3001975703,UA
-3001975704,3001975711,DE
-3001975712,3001975719,MY
-3001975720,3001975727,US
-3001975728,3001975735,RU
-3001975736,3001975743,MY
-3001975744,3001975751,CN
-3001975752,3001975759,UA
-3001975760,3001975767,US
-3001975768,3001975783,CN
-3001975784,3001975791,US
-3001975792,3001975799,IT
-3001975800,3001975807,US
-3001975808,3001975815,UA
-3001975816,3001975823,US
-3001975824,3001975831,UA
-3001975832,3001975847,GB
-3001975848,3001975855,US
-3001975856,3001975863,MY
-3001975864,3001975871,AE
-3001975872,3001975887,US
-3001975888,3001975895,CN
-3001975896,3001975919,GB
-3001975920,3001975927,CN
-3001975928,3001975935,AU
-3001975936,3001976623,GB
-3001976624,3001976639,PK
-3001976640,3001976655,RU
-3001976656,3001976671,GB
-3001976672,3001976679,IN
-3001976680,3001976687,US
-3001976688,3001976831,GB
-3001976832,3001976895,CN
-3001976896,3001976927,GB
-3001976928,3001976959,RU
-3001976960,3001977103,GB
-3001977104,3001977119,RU
-3001977120,3001977135,IN
-3001977136,3001977143,CN
-3001977144,3001977151,TW
-3001977152,3001977167,IN
-3001977168,3001977183,LK
-3001977184,3001977215,GB
-3001977216,3001977247,RU
-3001977248,3001977311,GB
-3001977312,3001977343,CN
-3001977344,3001977375,GB
-3001977376,3001977407,US
-3001977408,3001977447,GB
-3001977448,3001977455,IT
-3001977456,3001977471,US
-3001977472,3001977487,IN
-3001977488,3001977503,LK
-3001977504,3001977519,GB
-3001977520,3001977535,CN
-3001977536,3001977567,GB
-3001977568,3001977575,CA
-3001977576,3001977599,GB
-3001977600,3001977855,DK
-3001977856,3001978015,GB
-3001978016,3001978023,CN
-3001978024,3001978031,GB
-3001978032,3001978047,US
-3001978048,3001978367,GB
-3001978368,3001978495,US
-3001978496,3001978527,RU
-3001978528,3001978543,GB
-3001978544,3001978559,RU
-3001978560,3001978591,US
-3001978592,3001978607,RU
-3001978608,3001978615,IE
-3001978616,3001978623,CN
-3001978624,3001978687,US
-3001978688,3001978751,EE
-3001978752,3001978783,RU
-3001978784,3001978815,US
-3001978816,3001978823,LK
-3001978824,3001978847,GB
-3001978848,3001978863,UA
-3001978864,3001978879,PK
-3001978880,3001982975,GB
+3001974784,3001982975,GB
3001982976,3001987071,CH
3001987072,3001991167,JO
3001991168,3001995263,IR
@@ -75957,7 +78039,9 @@
3002763264,3002765311,RS
3002765312,3002767359,NL
3002767360,3002769407,RU
-3002769408,3002771711,DE
+3002769408,3002771655,DE
+3002771656,3002771663,NL
+3002771664,3002771711,DE
3002771712,3002771719,NL
3002771720,3002773503,DE
3002773504,3002775551,GB
@@ -76169,7 +78253,6 @@
3031582720,3031584767,SG
3031584768,3031587839,JP
3031587840,3031592959,ID
-3031592960,3031595007,HK
3031595008,3031596031,AU
3031596032,3031597055,KH
3031597056,3031613439,PK
@@ -76301,6 +78384,8 @@
3039428608,3039494143,CL
3039821824,3040346111,CO
3040870400,3041001471,PE
+3041918976,3042967551,AR
+3045064704,3045588991,CO
3053453312,3054501887,ID
3054501888,3054534655,HK
3054534656,3054537727,PH
@@ -76365,7 +78450,9 @@
3057041408,3057049599,MY
3057049600,3057050623,AU
3057050624,3057051647,SG
-3057051648,3057053695,AU
+3057051648,3057052415,AU
+3057052416,3057052671,ES
+3057052672,3057053695,AU
3057053696,3057054719,JP
3057054720,3057055743,HK
3057055744,3057057791,JP
@@ -76720,29 +78807,37 @@
3098148864,3098165247,JM
3098165248,3098181631,US
3098181632,3098185727,CA
-3098185728,3098263551,US
+3098185728,3098255903,US
+3098255904,3098255911,MV
+3098255912,3098263551,US
3098263552,3098271743,CA
3098271744,3098279943,US
3098279944,3098279951,KW
3098279952,3098280591,US
3098280592,3098280599,PA
-3098280600,3098281503,US
+3098280600,3098281311,US
+3098281312,3098281343,EG
+3098281344,3098281503,US
3098281504,3098281511,PA
3098281512,3098281711,US
3098281712,3098281719,PA
-3098281720,3098286287,US
+3098281720,3098281943,US
+3098281944,3098281951,AU
+3098281952,3098286287,US
3098286288,3098286295,IN
3098286296,3098286399,US
3098286400,3098286431,BR
-3098286432,3098288343,US
+3098286432,3098287711,US
+3098287712,3098287719,AU
+3098287720,3098288343,US
3098288344,3098288351,BR
3098288352,3098288775,US
3098288776,3098288783,BR
-3098288784,3098290223,US
+3098288784,3098289495,US
+3098289496,3098289503,AU
+3098289504,3098290223,US
3098290224,3098290231,IN
-3098290232,3098291087,US
-3098291088,3098291095,IN
-3098291096,3098291119,US
+3098290232,3098291119,US
3098291120,3098291135,NL
3098291136,3098291151,US
3098291152,3098291159,NL
@@ -76756,29 +78851,39 @@
3098322384,3098322391,BD
3098322392,3098322695,US
3098322696,3098322703,BD
-3098322704,3098331151,US
+3098322704,3098323679,US
+3098323680,3098323711,EG
+3098323712,3098331151,US
3098331152,3098331159,HK
3098331160,3098331471,US
3098331472,3098331479,CL
3098331480,3098333951,US
3098333952,3098333959,BD
-3098333960,3098336303,US
+3098333960,3098336047,US
+3098336048,3098336055,MA
+3098336056,3098336303,US
3098336304,3098336311,MY
-3098336312,3098365535,US
+3098336312,3098336975,US
+3098336976,3098336983,BR
+3098336984,3098365535,US
3098365536,3098365551,IN
-3098365552,3098365951,US
+3098365552,3098365631,US
+3098365632,3098365639,AU
+3098365640,3098365951,US
3098365952,3098365959,MX
3098365960,3098371191,US
3098371192,3098371199,BR
-3098371200,3098371303,US
-3098371304,3098371311,PE
-3098371312,3098371495,US
+3098371200,3098371495,US
3098371496,3098371503,JO
-3098371504,3098375583,US
+3098371504,3098373927,US
+3098373928,3098373935,MX
+3098373936,3098375583,US
3098375584,3098375615,BR
3098375616,3098376863,US
3098376864,3098376895,BR
-3098376896,3098377727,US
+3098376896,3098377655,US
+3098377656,3098377663,GB
+3098377664,3098377727,US
3098377728,3098377759,AR
3098377760,3098381455,US
3098381456,3098381471,LT
@@ -76799,13 +78904,13 @@
3120599040,3120601087,EC
3120601088,3120602111,AR
3120602112,3120603135,BO
-3120603136,3120608255,AR
-3120609280,3120610303,AR
+3120603136,3120610303,AR
3120610304,3120611327,PY
3120611328,3120627711,AR
3120627712,3120644095,NI
3120644096,3120660479,DO
3120660480,3120668671,PA
+3120668672,3120676863,CO
3120676864,3120680959,HT
3120680960,3120691199,AR
3120691200,3120693247,CO
@@ -76832,34 +78937,37 @@
3122298880,3122331647,VE
3122331648,3122348031,BO
3122397184,3122659327,CO
-3122659328,3122675711,CR
-3122675712,3122700287,GT
-3122700288,3122716671,CR
-3122716672,3122724863,GT
+3122659328,3122675711,GT
+3122675712,3122683903,SV
+3122683904,3122724863,GT
3122790400,3123052543,CL
3123052544,3123183615,AR
3123183616,3123314687,CL
3123314688,3123380223,EC
3123380224,3123412991,CO
+3123412992,3123429375,EC
3123445760,3123576831,TT
-3123576832,3123642367,EC
-3123707904,3123970047,UY
-3124232192,3124772863,AR
+3123576832,3123707903,EC
+3123707904,3124232191,UY
+3124232192,3124789247,AR
3124789248,3124822015,CR
3124822016,3124838399,EC
3124854784,3124887551,CL
3124887552,3124953087,EC
3124953088,3125018623,CL
3125018624,3125280767,EC
-3125280768,3125542911,PA
+3125280768,3125346303,CO
+3125346304,3125542911,PA
+3125542912,3125673983,NI
3125673984,3125805055,CL
3125805056,3126329343,CO
3126329344,3126853631,VE
3126853632,3126919167,AR
3126919168,3127115775,CO
3127115776,3127181311,AR
-3127246848,3127377919,CO
-3127377920,3127640063,CL
+3127181312,3127246847,EC
+3127246848,3127345151,CO
+3127345152,3127640063,CL
3127640064,3127902207,AR
3127902208,3128426495,CO
3128426496,3128492031,DO
@@ -76870,9 +78978,11 @@
3129999360,3130261503,CO
3130261504,3130277887,CL
3130294272,3130302463,AR
-3130310656,3130312703,PA
+3130302464,3130312703,PA
+3130312704,3130314751,AR
3130314752,3130315775,CL
3130315776,3130316799,CR
+3130316800,3130318847,AN
3130318848,3130327039,AR
3130327040,3130392575,DO
3130458112,3130523647,GT
@@ -76882,9 +78992,9 @@
3130851328,3130916863,AR
3131047936,3131310079,PE
3131310080,3131572223,VE
-3131572224,3131703295,CO
+3131572224,3131834367,CO
3131834368,3132096511,CL
-3132096512,3132162047,CR
+3132096512,3132227583,CR
3132227584,3132293119,EC
3132358656,3132489727,CO
3132489728,3132555263,AR
@@ -76912,6 +79022,7 @@
3154313216,3154378751,TR
3154378752,3154444287,GR
3154444288,3154509823,BE
+3154509824,3154575359,HU
3154575360,3154640895,FR
3154640896,3155165183,IT
3155165184,3155427327,RU
@@ -76920,6 +79031,7 @@
3155506336,3155689471,AT
3155689472,3155951615,RO
3155951616,3156213759,GB
+3156213760,3156279295,RU
3156279296,3156344831,PL
3156344832,3156410367,IR
3156410368,3156475903,RU
@@ -76939,6 +79051,11 @@
3156803584,3156869119,TR
3156869120,3156934655,LU
3156934656,3157000191,RU
+3157000192,3157008383,MK
+3157008384,3157016575,RU
+3157016576,3157024767,BE
+3157024768,3157032959,RU
+3157032960,3157065727,HU
3157065728,3157131263,AT
3157131264,3157196799,DE
3157196800,3157262335,PL
@@ -76990,9 +79107,7 @@
3158392832,3158394879,RU
3158394880,3158395007,AT
3158395008,3158395135,GB
-3158395136,3158395151,AT
-3158395152,3158395159,DE
-3158395160,3158395167,AT
+3158395136,3158395167,AT
3158395168,3158395175,DE
3158395176,3158395191,AT
3158395192,3158395199,DE
@@ -77377,8 +79492,8 @@
3162365952,3162374143,PL
3162374144,3162382335,BG
3162382336,3162390527,RU
-3162390528,3162391551,SE
-3162391552,3162398719,A1
+3162390528,3162392575,SE
+3162392576,3162398719,A1
3162398720,3162406911,BE
3162406912,3162415103,IR
3162415104,3162423295,DE
@@ -77420,7 +79535,8 @@
3163062272,3163095039,IR
3163095040,3163127807,PL
3163127808,3163160575,BH
-3163160576,3163161631,DE
+3163160576,3163161599,DE
+3163161600,3163161631,IN
3163161632,3163161663,DK
3163161664,3163161695,US
3163161696,3163161727,BG
@@ -77430,34 +79546,45 @@
3163161824,3163161855,US
3163161856,3163161887,BR
3163161888,3163161951,US
-3163161952,3163162079,DE
+3163161952,3163162015,DE
+3163162016,3163162047,US
+3163162048,3163162079,NL
3163162080,3163162111,RU
3163162112,3163162143,TR
3163162144,3163162271,DE
3163162272,3163162303,NL
-3163162304,3163162367,DE
+3163162304,3163162335,TH
+3163162336,3163162367,DE
3163162368,3163162399,TR
3163162400,3163162431,DE
3163162432,3163162463,CY
-3163162464,3163162559,DE
-3163162560,3163162591,US
-3163162592,3163163711,DE
+3163162464,3163162495,DE
+3163162496,3163162527,BR
+3163162528,3163162559,DE
+3163162560,3163162623,US
+3163162624,3163163711,DE
3163163712,3163163743,BR
-3163163744,3163163807,DE
+3163163744,3163163775,DE
+3163163776,3163163807,TR
3163163808,3163163839,CY
-3163163840,3163163871,DE
+3163163840,3163163871,PL
3163163872,3163163903,RU
3163163904,3163163935,GR
-3163163936,3163163967,VG
+3163163936,3163163967,BR
3163163968,3163163999,US
3163164000,3163164031,DE
-3163164032,3163164063,TW
+3163164032,3163164063,US
3163164064,3163164095,AM
3163164096,3163164127,RU
-3163164128,3163164287,DE
+3163164128,3163164159,MA
+3163164160,3163164191,US
+3163164192,3163164223,MA
+3163164224,3163164287,DE
3163164288,3163164319,CL
3163164320,3163164351,RU
-3163164352,3163164447,DE
+3163164352,3163164383,DE
+3163164384,3163164415,TR
+3163164416,3163164447,PL
3163164448,3163164479,RU
3163164480,3163164511,DE
3163164512,3163164543,HU
@@ -77467,14 +79594,16 @@
3163164640,3163164671,US
3163164672,3163165695,DE
3163165696,3163165727,US
-3163165728,3163165759,DE
+3163165728,3163165759,RU
3163165760,3163165791,PL
3163165792,3163165823,RU
3163165824,3163165855,BR
-3163165856,3163165983,DE
-3163165984,3163166015,CH
+3163165856,3163165887,DE
+3163165888,3163165919,AR
+3163165920,3163166015,DE
3163166016,3163166047,US
-3163166048,3163166175,DE
+3163166048,3163166079,BR
+3163166080,3163166175,DE
3163166176,3163166207,RU
3163166208,3163166239,TR
3163166240,3163166271,IT
@@ -77486,11 +79615,12 @@
3163166496,3163166527,RO
3163166528,3163166559,DE
3163166560,3163166591,HU
-3163166592,3163166623,DE
+3163166592,3163166623,IN
3163166624,3163166655,US
3163166656,3163166687,DE
3163166688,3163166719,RU
-3163166720,3163167775,DE
+3163166720,3163167743,DE
+3163167744,3163167775,RU
3163167776,3163167807,GR
3163167808,3163167839,US
3163167840,3163167871,BR
@@ -77510,50 +79640,54 @@
3163168320,3163168351,DK
3163168352,3163168383,RU
3163168384,3163168415,TR
-3163168416,3163168511,DE
+3163168416,3163168479,DE
+3163168480,3163168511,US
3163168512,3163168543,TR
3163168544,3163168575,DE
3163168576,3163168607,US
-3163168608,3163168671,DE
+3163168608,3163168639,MA
+3163168640,3163168671,DE
3163168672,3163168703,US
3163168704,3163168735,GR
3163168736,3163169823,DE
3163169824,3163169855,RU
-3163169856,3163170015,DE
+3163169856,3163169887,US
+3163169888,3163170015,DE
3163170016,3163170047,ES
3163170048,3163170079,RU
3163170080,3163170111,TR
-3163170112,3163170143,TW
+3163170112,3163170143,CZ
3163170144,3163170175,ZA
3163170176,3163170207,DE
3163170208,3163170239,RU
-3163170240,3163170271,DE
-3163170272,3163170303,TW
+3163170240,3163170303,DE
3163170304,3163170335,IT
3163170336,3163170367,RO
-3163170368,3163170495,DE
+3163170368,3163170463,DE
+3163170464,3163170495,TR
3163170496,3163170527,BG
3163170528,3163170591,DE
3163170592,3163170623,BR
3163170624,3163170655,GR
-3163170656,3163170751,DE
+3163170656,3163170719,DE
+3163170720,3163170751,MA
3163170752,3163170783,CH
3163170784,3163170815,US
3163170816,3163171871,DE
3163171872,3163171903,RO
-3163171904,3163171935,BZ
-3163171936,3163171967,DE
+3163171904,3163171967,DE
3163171968,3163171999,US
-3163172000,3163172095,DE
-3163172096,3163172127,BR
+3163172000,3163172127,BR
3163172128,3163172159,US
3163172160,3163172191,TR
-3163172192,3163172255,DE
+3163172192,3163172223,US
+3163172224,3163172255,FR
3163172256,3163172287,US
3163172288,3163172319,DE
3163172320,3163172351,NL
3163172352,3163172383,GB
-3163172384,3163172447,DE
+3163172384,3163172415,US
+3163172416,3163172447,DE
3163172448,3163172511,US
3163172512,3163172543,RU
3163172544,3163172575,DE
@@ -77563,20 +79697,22 @@
3163172672,3163172703,BR
3163172704,3163172735,DE
3163172736,3163172767,GR
-3163172768,3163173919,DE
-3163173920,3163173951,TW
-3163173952,3163174015,DE
+3163172768,3163173951,DE
+3163173952,3163173983,IN
+3163173984,3163174015,GB
3163174016,3163174047,RU
3163174048,3163174079,DK
-3163174080,3163174111,US
+3163174080,3163174111,DE
3163174112,3163174143,BE
3163174144,3163174175,BD
-3163174176,3163174239,DE
+3163174176,3163174207,DE
+3163174208,3163174239,RU
3163174240,3163174271,TW
3163174272,3163174303,DE
3163174304,3163174335,IL
3163174336,3163174367,RU
-3163174368,3163174431,DE
+3163174368,3163174399,US
+3163174400,3163174431,DE
3163174432,3163174463,BR
3163174464,3163174495,DE
3163174496,3163174527,US
@@ -77587,32 +79723,37 @@
3163174656,3163174687,RU
3163174688,3163174719,DE
3163174720,3163174751,NL
-3163174752,3163174783,TR
-3163174784,3163174815,DE
+3163174752,3163174783,DE
+3163174784,3163174815,TW
3163174816,3163174847,CA
3163174848,3163174879,TR
3163174880,3163174911,RU
-3163174912,3163175999,DE
-3163176000,3163176031,US
-3163176032,3163176063,DE
+3163174912,3163175967,DE
+3163175968,3163176031,US
+3163176032,3163176063,BG
3163176064,3163176095,RU
3163176096,3163176127,CY
3163176128,3163176159,US
3163176160,3163176255,DE
3163176256,3163176287,UG
-3163176288,3163176479,DE
+3163176288,3163176319,RU
+3163176320,3163176351,DE
+3163176352,3163176383,RO
+3163176384,3163176415,IN
+3163176416,3163176479,DE
3163176480,3163176511,GB
-3163176512,3163176543,DE
+3163176512,3163176543,RU
3163176544,3163176575,US
3163176576,3163176607,GR
-3163176608,3163176639,TW
-3163176640,3163176767,DE
+3163176608,3163176703,DE
+3163176704,3163176735,BR
+3163176736,3163176767,DE
3163176768,3163176799,PL
3163176800,3163176831,EG
-3163176832,3163176863,BR
-3163176864,3163176895,DE
+3163176832,3163176895,BR
3163176896,3163176927,SE
-3163176928,3163193343,DE
+3163176928,3163176959,TH
+3163176960,3163193343,DE
3163193344,3163226111,MD
3163226112,3163258879,SA
3163258880,3163291647,SY
@@ -77697,7 +79838,8 @@
3164949156,3164949159,DE
3164949160,3164949163,PL
3164949164,3164949167,FR
-3164949168,3164949175,GB
+3164949168,3164949171,IE
+3164949172,3164949175,FR
3164949176,3164949179,ES
3164949180,3164949183,FR
3164949184,3164949199,GB
@@ -77745,7 +79887,8 @@
3164950520,3164950523,FR
3164950524,3164950527,ES
3164950528,3164950543,BE
-3164950544,3164950591,NL
+3164950544,3164950559,IE
+3164950560,3164950591,NL
3164950592,3164950623,FR
3164950624,3164950655,GB
3164950656,3164950687,FR
@@ -77806,7 +79949,7 @@
3164951936,3164951999,DE
3164952000,3164952015,ES
3164952016,3164952031,FR
-3164952032,3164952063,PL
+3164952032,3164952063,PT
3164952064,3164952191,FR
3164952192,3164952207,ES
3164952208,3164952215,FR
@@ -77821,8 +79964,7 @@
3164952576,3164952831,FR
3164952832,3164952959,IT
3164952960,3164952975,GB
-3164952976,3164952991,FR
-3164952992,3164953007,PL
+3164952976,3164953007,FR
3164953008,3164953023,ES
3164953024,3164953087,FR
3164953088,3164953151,LT
@@ -77830,9 +79972,7 @@
3164953216,3164953247,FR
3164953248,3164953255,CH
3164953256,3164953263,CZ
-3164953264,3164953311,FR
-3164953312,3164953319,CZ
-3164953320,3164953327,BE
+3164953264,3164953327,FR
3164953328,3164953375,PL
3164953376,3164953379,NL
3164953380,3164953383,GB
@@ -77952,7 +80092,8 @@
3164960576,3164960591,DE
3164960592,3164960599,ES
3164960600,3164960623,DE
-3164960624,3164960639,FR
+3164960624,3164960627,FR
+3164960628,3164960639,PL
3164960640,3164960643,LT
3164960644,3164960647,FR
3164960648,3164960651,CH
@@ -77965,7 +80106,7 @@
3164960704,3164960719,FR
3164960720,3164960723,CH
3164960724,3164960727,FR
-3164960728,3164960735,GB
+3164960728,3164960735,PL
3164960736,3164960767,ES
3164960768,3164960799,GB
3164960800,3164960831,ES
@@ -77976,7 +80117,7 @@
3164960936,3164960939,GB
3164960940,3164960943,DE
3164960944,3164960959,PL
-3164960960,3164960963,DE
+3164960960,3164960963,ES
3164960964,3164960967,PT
3164960968,3164960975,PL
3164960976,3164960991,GB
@@ -78027,7 +80168,7 @@
3164961792,3164961855,FR
3164961856,3164961859,PL
3164961860,3164961863,ES
-3164961864,3164961871,FI
+3164961864,3164961871,FR
3164961872,3164961887,IE
3164961888,3164961903,ES
3164961904,3164961919,GB
@@ -78048,7 +80189,8 @@
3164962112,3164962143,GB
3164962144,3164962151,ES
3164962152,3164962159,DE
-3164962160,3164962199,FR
+3164962160,3164962191,FR
+3164962192,3164962199,DE
3164962200,3164962203,GB
3164962204,3164962207,PT
3164962208,3164962211,FI
@@ -78083,8 +80225,8 @@
3164962632,3164962639,FR
3164962640,3164962647,ES
3164962648,3164962655,PT
-3164962656,3164962663,GB
-3164962664,3164962687,ES
+3164962656,3164962671,GB
+3164962672,3164962687,FR
3164962688,3164962703,PL
3164962704,3164962715,FR
3164962716,3164962719,NL
@@ -78157,8 +80299,7 @@
3164969880,3164969883,ES
3164969884,3164969887,PL
3164969888,3164969903,IE
-3164969904,3164969919,GB
-3164969920,3164969983,FR
+3164969904,3164969983,FR
3164969984,3164970047,IE
3164970048,3164970079,GB
3164970080,3164970111,DE
@@ -78183,7 +80324,9 @@
3164970364,3164970367,ES
3164970368,3164970371,PL
3164970372,3164970375,ES
-3164970376,3164970399,IT
+3164970376,3164970379,FR
+3164970380,3164970383,PL
+3164970384,3164970399,IT
3164970400,3164970407,CH
3164970408,3164970411,IT
3164970412,3164970415,GB
@@ -78250,8 +80393,7 @@
3164971808,3164971903,BE
3164971904,3164971967,DE
3164971968,3164971983,FR
-3164971984,3164971991,ES
-3164971992,3164971999,FR
+3164971984,3164971999,ES
3164972000,3164972015,CH
3164972016,3164972019,ES
3164972020,3164972027,FR
@@ -78275,7 +80417,8 @@
3164972596,3164972599,PL
3164972600,3164972607,FR
3164972608,3164972639,PL
-3164972640,3164972671,IE
+3164972640,3164972655,IT
+3164972656,3164972671,FR
3164972672,3164972679,PL
3164972680,3164972691,FR
3164972692,3164972695,FI
@@ -78307,10 +80450,12 @@
3164973628,3164973631,CH
3164973632,3164973663,IE
3164973664,3164973695,ES
-3164973696,3164973727,FR
+3164973696,3164973727,DE
3164973728,3164973743,GB
3164973744,3164973759,FR
-3164973760,3164973815,GB
+3164973760,3164973791,GB
+3164973792,3164973807,DE
+3164973808,3164973815,GB
3164973816,3164973823,FR
3164973824,3164973855,DE
3164973856,3164973863,PL
@@ -78329,7 +80474,8 @@
3164973944,3164973951,PL
3164973952,3164974591,FR
3164974592,3164974623,PL
-3164974624,3164974647,FR
+3164974624,3164974643,FR
+3164974644,3164974647,PL
3164974648,3164974651,PT
3164974652,3164974655,DE
3164974656,3164974659,BE
@@ -78380,8 +80526,7 @@
3164975948,3164975951,NL
3164975952,3164975967,GB
3164975968,3164975983,NL
-3164975984,3164975987,PL
-3164975988,3164975991,DE
+3164975984,3164975991,DE
3164975992,3164976011,PL
3164976012,3164976015,ES
3164976016,3164976023,PL
@@ -78408,7 +80553,7 @@
3164976288,3164976295,ES
3164976296,3164976303,IT
3164976304,3164976307,FR
-3164976308,3164976311,DE
+3164976308,3164976311,IE
3164976312,3164976315,GB
3164976316,3164976319,FR
3164976320,3164976327,DE
@@ -78424,7 +80569,8 @@
3164976404,3164976407,FR
3164976408,3164976415,DE
3164976416,3164976431,IT
-3164976432,3164976459,FR
+3164976432,3164976447,PT
+3164976448,3164976459,FR
3164976460,3164976479,DE
3164976480,3164976511,PL
3164976512,3164976767,FR
@@ -78452,8 +80598,8 @@
3164977792,3164977823,FR
3164977824,3164977839,GB
3164977840,3164977871,FR
-3164977872,3164977875,DE
-3164977876,3164977879,ES
+3164977872,3164977875,GB
+3164977876,3164977879,NL
3164977880,3164977883,DE
3164977884,3164977887,GB
3164977888,3164977903,IT
@@ -78489,19 +80635,19 @@
3164978952,3164978955,PL
3164978956,3164978959,GB
3164978960,3164978975,FR
-3164978976,3164978991,ES
-3164978992,3164978999,PL
+3164978976,3164978983,ES
+3164978984,3164978999,PL
3164979000,3164979003,FR
3164979004,3164979007,DE
3164979008,3164979023,GB
3164979024,3164979047,FR
3164979048,3164979051,BE
3164979052,3164979103,FR
-3164979104,3164979111,GB
+3164979104,3164979107,PL
+3164979108,3164979111,GB
3164979112,3164979119,PL
3164979120,3164979135,NL
-3164979136,3164979151,DE
-3164979152,3164979159,FR
+3164979136,3164979159,FR
3164979160,3164979167,PL
3164979168,3164979175,DE
3164979176,3164979183,FR
@@ -78576,14 +80722,19 @@
3168829440,3168862207,RO
3168862208,3168894975,RU
3168894976,3168927743,PS
-3168927744,3169058815,RU
+3168927744,3169026047,RU
+3169026048,3169034239,CZ
+3169034240,3169042431,GB
+3169042432,3169044479,GR
+3169044480,3169046527,NL
+3169046528,3169050623,AZ
+3169050624,3169052671,HU
+3169052672,3169054719,PS
+3169054720,3169056767,GB
+3169056768,3169058815,EE
3169058816,3169091583,DK
3169091584,3169124351,IT
-3169124352,3169149439,RO
-3169149440,3169149695,IT
-3169149696,3169149951,PS
-3169149952,3169150463,SY
-3169150464,3169157119,RO
+3169124352,3169157119,RO
3169157120,3169189887,SY
3169189888,3169222655,UA
3169222656,3169255423,SI
@@ -78645,7 +80796,9 @@
3170263040,3170271231,CZ
3170271232,3170279423,PL
3170279424,3170287615,RU
-3170287616,3170295807,GB
+3170287616,3170289151,GB
+3170289152,3170289167,BA
+3170289168,3170295807,GB
3170295808,3170303999,RU
3170304000,3170312191,SY
3170312192,3170320383,RU
@@ -78690,7 +80843,7 @@
3187851264,3187855359,PY
3187855360,3187857407,PA
3187859456,3187863551,PA
-3187867648,3187908607,AR
+3187863552,3187908607,AR
3187908608,3187910655,CO
3187910656,3187914751,CL
3187914752,3187916799,BO
@@ -78702,6 +80855,7 @@
3187953664,3187955711,CL
3187955712,3187957759,CR
3187957760,3187961855,CL
+3187961856,3187965951,AR
3187965952,3187982335,AN
3187982336,3187998719,CL
3187998720,3188006911,AR
@@ -78724,6 +80878,7 @@
3188178944,3188187135,CR
3188187136,3188203519,AR
3188203520,3188207615,DO
+3188207616,3188211711,AR
3188211712,3188228095,CL
3188228096,3188236287,PE
3188236288,3188237311,PA
@@ -78733,7 +80888,9 @@
3188242432,3188244479,AR
3188244480,3188260863,CO
3188260864,3188269055,AR
-3188269056,3188273151,VE
+3188269056,3188269439,VE
+3188269440,3188269567,CO
+3188269568,3188273151,VE
3188273152,3188275199,PA
3188275200,3188277247,CL
3188277248,3188293631,CO
@@ -78751,14 +80908,23 @@
3188473856,3188482047,PE
3188482048,3188490239,AR
3188490240,3188498431,CO
-3188498432,3188513279,AR
+3188498432,3188509695,AR
+3188509696,3188510207,US
+3188510208,3188513279,AR
3188513280,3188513535,US
-3188513536,3188523007,AR
+3188513536,3188516351,AR
+3188516352,3188516607,US
+3188516608,3188517119,AR
+3188517120,3188517375,US
+3188517376,3188523007,AR
3188523008,3188539391,CO
3188539392,3188543487,CL
3188543488,3188545535,PA
3188545536,3188547583,AR
3188547584,3188551679,CO
+3188551680,3188552703,AR
+3188552704,3188553727,CL
+3188553728,3188555775,AN
3188555776,3188572159,CL
3188572160,3188576255,CO
3188576256,3188597759,AR
@@ -78828,7 +80994,9 @@
3191603200,3191608319,MX
3191608320,3191608831,CO
3191608832,3191609087,MX
-3191609088,3191635967,CO
+3191609088,3191611391,CO
+3191611392,3191619583,VE
+3191619584,3191635967,CO
3191635968,3191637503,AR
3191637504,3191638095,CO
3191638096,3191638103,AR
@@ -78865,18 +81033,23 @@
3193782272,3193798655,TT
3193798656,3193806847,CO
3193806848,3193810943,CR
+3193810944,3193815039,PY
3193815040,3193823231,AR
3193823232,3193827327,CL
3193831424,3193864191,DO
3193864192,3193872383,EC
+3193872384,3193880575,AR
3193880576,3193896959,VE
3193896960,3193929727,CL
3193929728,3193962495,EC
-3193962496,3193995263,CL
+3193962496,3193987071,CL
+3193987072,3193989119,EC
+3193991168,3193995263,AR
3193995264,3194028031,CO
3194028032,3194044415,AR
3194044416,3194052607,CO
3194052608,3194056703,TT
+3194056704,3194058751,AN
3194060800,3194093567,CO
3194093568,3194126335,SR
3194126336,3194127359,GT
@@ -78931,7 +81104,9 @@
3194642432,3194646527,AR
3194650624,3194653439,AR
3194653440,3194653695,US
-3194653696,3194665983,AR
+3194653696,3194663167,AR
+3194663168,3194663423,US
+3194663424,3194665983,AR
3194665984,3194666239,US
3194666240,3194667007,AR
3194683392,3194687487,CU
@@ -78950,7 +81125,7 @@
3194781696,3194798079,CL
3194798080,3194799103,AR
3194799104,3194802175,GY
-3194806272,3194810367,AR
+3194806272,3194814463,AR
3194818560,3194822655,AR
3194830848,3194839039,PA
3194847232,3194863615,CO
@@ -79072,8 +81247,9 @@
3198910464,3198926847,CL
3198943232,3199500799,AR
3199500800,3199501311,US
-3199501312,3199516671,AR
+3199501312,3199533055,AR
3199533056,3199549439,BO
+3199549440,3199565823,AR
3199565824,3199582207,NI
3199598592,3199631359,CO
3199664128,3199729663,AR
@@ -79092,9 +81268,12 @@
3201302528,3201433599,CL
3201433600,3201499135,AR
3201499136,3201515519,CL
-3201515520,3201519615,AR
-3201523712,3201531903,CR
-3201531904,3201540095,AR
+3201515520,3201522687,AR
+3201522688,3201531903,CR
+3201531904,3201533951,AR
+3201533952,3201534975,HN
+3201534976,3201535999,CO
+3201536000,3201540095,AR
3201540096,3201544191,CL
3201548288,3201556479,AR
3201556480,3201560575,BO
@@ -79123,8 +81302,18 @@
3203476736,3203476991,CR
3203476992,3203477375,CO
3203477376,3203530751,CR
-3203530752,3203538943,NI
-3203538944,3203661823,CO
+3203530752,3203531519,NI
+3203531520,3203531775,PA
+3203531776,3203532287,NI
+3203532288,3203532543,PA
+3203532544,3203532799,NI
+3203532800,3203534847,PA
+3203534848,3203535871,NI
+3203535872,3203536383,PA
+3203536384,3203538943,NI
+3203538944,3203547135,CO
+3203547136,3203549183,PA
+3203549184,3203661823,CO
3203661824,3203923967,AR
3203923968,3204448255,CO
3221233664,3221237759,US
@@ -79983,9 +82172,7 @@
3225937664,3225938431,SE
3225938432,3225938687,US
3225938688,3225944063,SE
-3225944064,3225977855,TW
-3225977856,3225978111,CH
-3225978112,3226008831,TW
+3225944064,3226008831,TW
3226008832,3226009343,US
3226009600,3226010879,US
3226010880,3226011135,CA
@@ -80016,9 +82203,7 @@
3226191360,3226191615,US
3226191872,3226201855,CA
3226201856,3226202111,US
-3226202112,3226205439,CA
-3226205440,3226205695,AE
-3226205696,3226205951,CA
+3226202112,3226206207,CA
3226206208,3226215423,GB
3226215424,3226236927,US
3226237184,3226237439,US
@@ -80904,9 +83089,15 @@
3229151744,3229155327,US
3229155328,3229155839,SE
3229155840,3229156095,ES
-3229156096,3229171455,SE
+3229156096,3229168895,SE
+3229168896,3229169151,JP
+3229169152,3229171455,SE
3229171456,3229171711,MT
-3229171712,3229200895,SE
+3229171712,3229189119,SE
+3229189120,3229189375,GB
+3229189376,3229191167,SE
+3229191168,3229191423,GB
+3229191424,3229200895,SE
3229200896,3229201151,DE
3229201152,3229201663,SE
3229201664,3229201919,DK
@@ -80965,22 +83156,7 @@
3229391872,3229394943,US
3229394944,3229408255,RU
3229408256,3229412095,US
-3229412096,3229470719,DE
-3229470720,3229471231,IE
-3229471232,3229471999,DE
-3229472000,3229472255,IE
-3229472256,3229472767,GB
-3229472768,3229473791,DE
-3229473792,3229474047,GB
-3229474048,3229474303,DE
-3229474304,3229475839,GB
-3229475840,3229478399,DE
-3229478400,3229478655,IE
-3229478656,3229478911,DE
-3229478912,3229480959,IE
-3229480960,3229481471,DE
-3229481472,3229482239,GB
-3229482240,3229483007,IE
+3229412096,3229483007,DE
3229483008,3229499647,FI
3229499648,3229500671,US
3229548544,3229679615,US
@@ -83021,7 +85197,6 @@
3239062784,3239063551,UA
3239063552,3239075839,DE
3239075840,3239076095,MT
-3239076096,3239076351,SE
3239076352,3239076607,DE
3239076608,3239076863,PL
3239076864,3239077119,NL
@@ -83066,7 +85241,6 @@
3239108096,3239109887,DE
3239109888,3239110143,PL
3239110144,3239110655,DE
-3239110656,3239110911,RU
3239110912,3239111167,UA
3239111168,3239111423,NL
3239111424,3239111935,DE
@@ -83094,6 +85268,7 @@
3239127040,3239127295,PT
3239127296,3239127551,PL
3239127552,3239127807,IL
+3239127808,3239128063,RU
3239128064,3239128319,AT
3239128320,3239128575,IT
3239128576,3239128831,UA
@@ -83128,7 +85303,6 @@
3239160576,3239160831,DE
3239160832,3239161087,PL
3239161088,3239161343,BY
-3239161344,3239161599,UA
3239161600,3239161855,HU
3239161856,3239162623,DE
3239162624,3239162879,BE
@@ -83216,6 +85390,7 @@
3239287808,3239288831,GB
3239288832,3239289855,DE
3239289856,3239290879,PL
+3239290880,3239291903,RU
3239291904,3239292927,BG
3239292928,3239293951,CZ
3239293952,3239294975,DE
@@ -83356,6 +85531,7 @@
3239556608,3239556863,HR
3239556864,3239557119,UA
3239557120,3239567359,DE
+3239567360,3239567615,GB
3239567616,3239567871,UA
3239567872,3239568127,DE
3239568128,3239568383,FR
@@ -83390,6 +85566,7 @@
3239634944,3239635967,RU
3239635968,3239636991,DE
3239636992,3239638015,BG
+3239638016,3239639039,PL
3239639040,3239640063,SI
3239640064,3239641087,DE
3239641088,3239643135,PL
@@ -83527,6 +85704,7 @@
3239793664,3239794175,RO
3239794176,3239794687,NL
3239794688,3239795199,GB
+3239795200,3239795711,PL
3239795712,3239796223,IL
3239796224,3239796735,NO
3239796736,3239821311,DE
@@ -83601,11 +85779,12 @@
3239877632,3239877887,UA
3239877888,3239878143,IT
3239878144,3239878399,PL
-3239878400,3239882751,DE
+3239878656,3239882751,DE
3239882752,3239883007,GB
3239883008,3239883263,UA
3239883264,3239883775,GB
3239883776,3239884031,DE
+3239884032,3239884287,IR
3239884288,3239884543,GB
3239884544,3239884799,FR
3239884800,3239885055,UA
@@ -83926,10 +86105,10 @@
3240281600,3240281727,JO
3240281728,3240281855,PL
3240281856,3240281983,NL
-3240281984,3240282111,FR
3240282112,3240282239,DE
3240282240,3240282367,UA
3240282368,3240282495,RO
+3240282496,3240282623,RU
3240282624,3240282879,SE
3240282880,3240283007,UA
3240283008,3240283391,PL
@@ -83944,7 +86123,16 @@
3240296448,3240296703,RO
3240296704,3240302847,GB
3240302848,3240303103,UA
-3240303104,3240361983,GB
+3240303104,3240321023,GB
+3240321024,3240321791,RU
+3240321792,3240322047,PL
+3240322048,3240322559,RU
+3240322560,3240324095,CZ
+3240324096,3240324351,RO
+3240324352,3240324607,RU
+3240324608,3240324863,PL
+3240324864,3240325119,SI
+3240325120,3240361983,GB
3240361984,3240362239,TR
3240362240,3240370175,GB
3240370176,3240370431,CH
@@ -84117,7 +86305,6 @@
3240730624,3240731647,ES
3240731648,3240732671,GB
3240732672,3240733695,SE
-3240733696,3240734719,UA
3240734720,3240735743,IT
3240735744,3240736255,FR
3240736256,3240736767,BG
@@ -84133,6 +86320,7 @@
3240740608,3240741119,DE
3240741120,3240741375,AT
3240741376,3240741631,IL
+3240741632,3240741887,RU
3240741888,3240742143,LV
3240742144,3240742399,IT
3240742400,3240742655,RO
@@ -84242,7 +86430,7 @@
3240867584,3240867839,CH
3240867840,3240873983,IT
3240873984,3240874495,RU
-3240874496,3240875007,UA
+3240874496,3240875007,CZ
3240875008,3240875519,AT
3240875520,3240876031,FR
3240876032,3240876543,DK
@@ -84370,7 +86558,6 @@
3241119232,3241119487,DK
3241119488,3241119743,BE
3241119744,3241119999,RO
-3241120000,3241120255,UA
3241120256,3241120511,RU
3241120512,3241120767,GB
3241120768,3241121023,RU
@@ -84429,7 +86616,6 @@
3241501440,3241501951,EU
3241501952,3241502975,BE
3241502976,3241503231,GR
-3241503232,3241503487,FR
3241503488,3241508095,BE
3241508096,3241508351,NL
3241508352,3241541375,BE
@@ -84535,7 +86721,8 @@
3243514112,3243514367,CH
3243514368,3243514623,IE
3243514624,3243514879,DK
-3243514880,3243515391,AT
+3243514880,3243515135,AT
+3243515136,3243515391,CH
3243515392,3243515647,DE
3243515648,3243515903,RU
3243515904,3243520511,CZ
@@ -84836,7 +87023,6 @@
3244855552,3244855807,UA
3244856064,3244856319,IL
3244856320,3244856575,CH
-3244856576,3244856831,RU
3244856832,3244857087,RO
3244857088,3244857343,IT
3244857344,3244857599,GB
@@ -84904,7 +87090,6 @@
3244875008,3244875263,PL
3244875264,3244875519,LI
3244875520,3244875775,IT
-3244875776,3244876799,BZ
3244876800,3244877055,GB
3244877056,3244877311,JO
3244877312,3244877567,RU
@@ -84930,7 +87115,6 @@
3244882432,3244882687,IT
3244882688,3244882943,PL
3244882944,3244883199,NL
-3244883200,3244883455,UA
3244883456,3244883711,CZ
3244883712,3244883967,NL
3244883968,3244884223,DE
@@ -84946,7 +87130,6 @@
3244886528,3244886783,DK
3244887040,3244887295,NL
3244887296,3244887551,GB
-3244887552,3244887807,CZ
3244887808,3244888063,BE
3244888064,3244888319,RU
3244888320,3244888575,DE
@@ -85387,6 +87570,7 @@
3245139968,3245140479,CH
3245140480,3245140991,RO
3245140992,3245141503,UA
+3245141504,3245142015,RO
3245142016,3245143039,UA
3245143040,3245144063,GB
3245144064,3245145087,UA
@@ -85468,6 +87652,7 @@
3245200384,3245200639,PL
3245200640,3245200895,GR
3245200896,3245201151,DE
+3245201152,3245201407,KW
3245201408,3245201663,UA
3245201664,3245201919,NO
3245201920,3245202175,SA
@@ -85745,7 +87930,9 @@
3245909568,3245909631,US
3245909632,3245910831,IE
3245910832,3245910847,GB
-3245910848,3245921279,IE
+3245910848,3245919456,IE
+3245919457,3245919462,IN
+3245919463,3245921279,IE
3245921280,3245921535,BE
3245921536,3245922959,IE
3245922960,3245922975,US
@@ -86162,7 +88349,9 @@
3247335424,3247336447,FI
3247336448,3247337215,NO
3247337216,3247337471,CH
-3247337472,3247338495,PL
+3247337472,3247337983,PL
+3247337984,3247338239,UA
+3247338240,3247338495,PL
3247338496,3247338751,SI
3247338752,3247339519,GB
3247339520,3247340543,FI
@@ -86202,7 +88391,7 @@
3247366144,3247371007,FI
3247371008,3247371263,PL
3247371264,3247371519,SE
-3247371776,3247374335,FI
+3247372032,3247374335,FI
3247374336,3247374591,RU
3247374592,3247394047,FI
3247394048,3247394303,PL
@@ -86220,7 +88409,8 @@
3247438336,3247439871,FI
3247439872,3247702015,ES
3247702016,3247702271,RO
-3247702272,3247704831,ES
+3247702272,3247703551,ES
+3247704064,3247704831,ES
3247704832,3247705087,GB
3247705088,3247705855,ES
3247705856,3247706111,RU
@@ -86256,6 +88446,59 @@
3247825920,3247826943,BE
3247826944,3247828991,CH
3247828992,3247833087,BE
+3247833088,3247833599,RU
+3247833600,3247834111,PL
+3247834112,3247834623,DE
+3247834624,3247835135,UA
+3247835136,3247836159,GB
+3247836160,3247837183,CZ
+3247837184,3247838207,ES
+3247838208,3247838719,CH
+3247838720,3247839231,NO
+3247839232,3247839743,CZ
+3247839744,3247840255,GB
+3247840256,3247841279,UA
+3247841280,3247841791,RU
+3247841792,3247842047,GB
+3247842048,3247842303,CZ
+3247842304,3247842815,PL
+3247842816,3247843327,CZ
+3247843328,3247843583,LT
+3247843584,3247845375,PL
+3247845376,3247845631,CH
+3247845632,3247845887,UA
+3247845888,3247846399,PL
+3247846400,3247847423,RU
+3247847424,3247848447,UA
+3247848448,3247849471,IT
+3247849472,3247849727,DE
+3247849728,3247849983,RU
+3247849984,3247850239,GB
+3247850240,3247850495,BG
+3247850496,3247850751,RU
+3247850752,3247851007,PL
+3247851008,3247851519,RU
+3247851520,3247852543,SK
+3247852544,3247853567,PL
+3247853568,3247854591,RU
+3247854592,3247855615,DK
+3247855616,3247856127,UA
+3247856128,3247856639,ES
+3247856640,3247857663,RU
+3247857664,3247858175,UA
+3247858176,3247858687,EU
+3247858688,3247859711,RU
+3247859712,3247859967,SE
+3247859968,3247861759,RU
+3247861760,3247862015,IT
+3247862016,3247862271,UA
+3247862272,3247864063,RU
+3247864064,3247864319,NO
+3247864320,3247864575,UA
+3247864576,3247864831,PL
+3247864832,3247865343,RU
+3247865344,3247865599,MT
+3247865600,3247865855,IL
3247865856,3247871999,GB
3247872000,3247875327,NL
3247875328,3247875583,PL
@@ -86335,7 +88578,12 @@
3248522240,3248525311,NO
3248525312,3248525567,DE
3248525568,3248525823,DK
-3248525824,3248545791,NO
+3248525824,3248528895,NO
+3248528896,3248529151,RU
+3248529152,3248529407,BG
+3248529408,3248540671,NO
+3248540672,3248541183,RU
+3248541184,3248545791,NO
3248545792,3248546815,UA
3248546816,3248547839,RU
3248547840,3248553727,NO
@@ -86345,7 +88593,10 @@
3248557056,3248558079,UA
3248558080,3248575487,NO
3248575488,3248576511,CZ
-3248576512,3248619263,NO
+3248576512,3248603135,NO
+3248603136,3248603391,BG
+3248603392,3248603647,RU
+3248603648,3248619263,NO
3248619264,3248619519,UA
3248619520,3248638463,DK
3248638464,3248638719,GB
@@ -86385,8 +88636,8 @@
3248790784,3248791039,PL
3248791040,3248791295,BE
3248791296,3248791551,DE
-3248791552,3248792527,GB
-3248792528,3248796607,EU
+3248791552,3248792543,GB
+3248792544,3248796607,EU
3248796608,3248796863,GB
3248796864,3248798975,EU
3248798976,3248799231,GB
@@ -86798,12 +89049,12 @@
3250372608,3250373375,HU
3250373376,3250373631,GB
3250373632,3250374143,DE
+3250374144,3250374655,PL
3250374656,3250374911,SA
3250374912,3250375679,SE
3250375680,3250376703,GB
3250376704,3250380799,AT
-3250380800,3250381055,DK
-3250381056,3250386943,CH
+3250380800,3250386943,CH
3250386944,3250387199,SE
3250387200,3250387455,FR
3250387456,3250387711,DE
@@ -86878,6 +89129,7 @@
3250589440,3250589471,IE
3250589472,3250589503,NL
3250589504,3250589567,HR
+3250589568,3250589631,RU
3250589632,3250589695,NO
3250589696,3250593791,CH
3250593792,3250594815,GB
@@ -86935,7 +89187,13 @@
3250733056,3250741247,DZ
3250741248,3250742783,RU
3250742784,3250743551,AT
-3250743808,3250745343,UA
+3250743552,3250743807,CY
+3250743808,3250746367,UA
+3250746368,3250747391,NL
+3250747392,3250747903,SI
+3250747904,3250748159,SA
+3250748160,3250748415,PL
+3250748416,3250749439,UA
3250749440,3250749695,GH
3250749696,3250749951,IT
3250749952,3250750463,RO
@@ -87201,7 +89459,6 @@
3251201536,3251201791,AT
3251201792,3251202047,FR
3251202048,3251202303,NL
-3251202304,3251202559,PL
3251202560,3251202815,AT
3251202816,3251203327,ES
3251203328,3251203583,SI
@@ -87446,7 +89703,44 @@
3251927992,3251927999,NL
3251928000,3252015687,NO
3252015688,3252015695,SE
-3252015696,3252289535,NO
+3252015696,3252168191,NO
+3252168192,3252174847,SE
+3252174848,3252177151,NO
+3252177152,3252177407,SE
+3252177408,3252178431,NO
+3252178432,3252178943,SE
+3252178944,3252179199,NO
+3252179200,3252189183,SE
+3252189184,3252189695,NO
+3252189696,3252190975,SE
+3252190976,3252191231,NO
+3252191232,3252197119,SE
+3252197120,3252197375,NO
+3252197376,3252205567,SE
+3252205568,3252205823,NO
+3252205824,3252211967,SE
+3252211968,3252212223,NO
+3252212224,3252213759,SE
+3252213760,3252214527,NO
+3252214528,3252218879,SE
+3252218880,3252219135,NO
+3252219136,3252220927,SE
+3252220928,3252221183,NO
+3252221184,3252222463,SE
+3252222464,3252223231,NO
+3252223232,3252223743,SE
+3252223744,3252223999,NO
+3252224000,3252233215,SE
+3252233216,3252240383,NO
+3252240384,3252244479,SE
+3252244480,3252246527,NO
+3252246528,3252276223,SE
+3252276224,3252277759,NO
+3252277760,3252279295,SE
+3252279296,3252279807,NO
+3252279808,3252286463,SE
+3252286464,3252286975,NO
+3252286976,3252289535,SE
3252289536,3252291327,GR
3252291328,3252291583,SK
3252291584,3252293631,FR
@@ -87489,15 +89783,13 @@
3252342528,3252342543,NO
3252342544,3252342591,DE
3252342592,3252342607,IE
-3252342640,3252342655,LV
3252342656,3252342783,IL
3252342784,3252346367,DE
3252346368,3252346623,GB
3252346624,3252355071,GR
3252355072,3252355327,GB
3252355328,3252358911,LT
-3252358912,3252358927,GB
-3252358928,3252359167,DE
+3252358912,3252359167,DE
3252359168,3252362239,DK
3252362240,3252362495,PL
3252362496,3252362751,IT
@@ -87608,9 +89900,7 @@
3252409504,3252409511,GH
3252409512,3252409519,BF
3252409520,3252409527,NG
-3252409528,3252409535,LT
-3252409536,3252409543,BI
-3252409544,3252409599,LT
+3252409528,3252409599,LT
3252409600,3252409615,MA
3252409616,3252409631,LT
3252409632,3252409647,AO
@@ -87640,7 +89930,9 @@
3252411824,3252411839,LT
3252411840,3252411855,MR
3252411856,3252411879,LT
-3252411880,3252411903,CD
+3252411880,3252411887,CD
+3252411888,3252411895,LT
+3252411896,3252411903,CD
3252411904,3252414463,LT
3252414464,3252414479,GH
3252414480,3252414511,LT
@@ -87653,9 +89945,7 @@
3252414640,3252414647,GH
3252414648,3252414655,NE
3252414656,3252414975,LT
-3252414976,3252414999,IQ
-3252415000,3252415015,LT
-3252415016,3252415031,IQ
+3252414976,3252415031,IQ
3252415032,3252415039,LT
3252415040,3252415095,IQ
3252415096,3252415103,LT
@@ -87674,8 +89964,8 @@
3252417280,3252417287,IQ
3252417288,3252417463,AF
3252417464,3252417471,LT
-3252417472,3252417503,AF
-3252417504,3252417791,LT
+3252417472,3252417511,AF
+3252417512,3252417791,LT
3252417792,3252417855,NG
3252417856,3252417919,LT
3252417920,3252417935,MW
@@ -87741,8 +90031,7 @@
3252425552,3252425575,AO
3252425576,3252425727,LT
3252425728,3252425983,A2
-3252425984,3252426239,LT
-3252426240,3252426751,BW
+3252425984,3252426751,LT
3252426752,3252427263,MZ
3252427264,3252427519,NG
3252427520,3252427775,LT
@@ -87757,8 +90046,8 @@
3252430336,3252430463,NE
3252430464,3252430511,LT
3252430512,3252430519,BF
-3252430520,3252430527,LT
-3252430528,3252430543,BF
+3252430520,3252430535,LT
+3252430536,3252430543,BF
3252430544,3252430559,BJ
3252430560,3252430591,LT
3252430592,3252430847,GN
@@ -87779,7 +90068,9 @@
3252434704,3252434711,TZ
3252434712,3252434719,LT
3252434720,3252434743,GH
-3252434744,3252435199,LT
+3252434744,3252434751,ML
+3252434752,3252434759,GN
+3252434760,3252435199,LT
3252435200,3252435231,TZ
3252435232,3252435247,LT
3252435248,3252435263,BW
@@ -87792,8 +90083,7 @@
3252435344,3252435375,BF
3252435376,3252435415,GN
3252435416,3252435423,LT
-3252435424,3252435447,CD
-3252435448,3252435455,LT
+3252435424,3252435455,CD
3252435456,3252435711,TZ
3252435712,3252435855,GH
3252435856,3252435871,MR
@@ -87801,8 +90091,7 @@
3252435888,3252435903,CD
3252435904,3252435919,BW
3252435920,3252435935,BF
-3252435936,3252435951,CF
-3252435952,3252435967,LT
+3252435936,3252435967,LT
3252435968,3252436223,TZ
3252436224,3252436239,GN
3252436240,3252436255,LT
@@ -87906,7 +90195,9 @@
3252457472,3252460799,LT
3252460800,3252460831,AF
3252460832,3252460847,US
-3252460848,3252461055,LT
+3252460848,3252460863,LT
+3252460864,3252460927,IQ
+3252460928,3252461055,LT
3252461056,3252461567,NO
3252461568,3252464383,LT
3252464384,3252465663,NO
@@ -87996,7 +90287,9 @@
3252616704,3252616959,ES
3252616960,3252617215,CH
3252617216,3252617471,PL
-3252617472,3252636671,CH
+3252617472,3252634623,CH
+3252634624,3252634879,RU
+3252634880,3252636671,CH
3252636672,3252636927,TR
3252636928,3252637183,DE
3252637184,3252637695,GB
@@ -88052,6 +90345,7 @@
3252912896,3252913151,PL
3252913152,3252913407,ES
3252913408,3252913663,FR
+3252913664,3252913919,RU
3252913920,3252914175,NO
3252914176,3252916223,FR
3252916224,3252920319,DE
@@ -88129,11 +90423,13 @@
3253403648,3253403903,PL
3253403904,3253409791,SE
3253409792,3253410047,GB
-3253410048,3253412351,SE
+3253410048,3253411327,SE
+3253411328,3253411583,NO
+3253411584,3253412351,SE
3253412352,3253412607,US
3253412608,3253416447,SE
-3253416448,3253416703,GB
-3253416704,3253428223,SE
+3253416448,3253416959,GB
+3253416960,3253428223,SE
3253428224,3253428479,DE
3253428480,3253429759,SE
3253429760,3253430015,ES
@@ -88150,9 +90446,16 @@
3253453312,3253453567,NO
3253453568,3253454079,SE
3253454080,3253454335,GB
-3253454336,3253460735,SE
+3253454336,3253455615,SE
+3253455616,3253455871,US
+3253455872,3253456383,SE
+3253456384,3253456639,US
+3253456640,3253460735,SE
3253460736,3253460991,IT
-3253460992,3253469183,SE
+3253460992,3253461247,US
+3253461248,3253463039,SE
+3253463040,3253464063,GB
+3253464064,3253469183,SE
3253469184,3253471231,AO
3253471232,3253534719,PT
3253534720,3253600255,GB
@@ -88244,7 +90547,6 @@
3253697536,3253698559,PL
3253698560,3253699071,UA
3253699072,3253699583,RO
-3253699584,3253700095,UA
3253700096,3253700607,RO
3253700608,3253701119,PL
3253701120,3253702143,RO
@@ -88313,6 +90615,7 @@
3253888256,3253888511,BE
3253888512,3253888767,GB
3253888768,3253889023,SE
+3253889024,3253889279,RO
3253889280,3253889535,CH
3253889536,3253889791,DE
3253889792,3253890047,DK
@@ -88355,6 +90658,7 @@
3253968896,3253969407,DE
3253969408,3253969919,AT
3253969920,3253970431,NL
+3253970432,3253970687,RU
3253970688,3253970943,UA
3253970944,3253971967,RS
3253971968,3253972991,RU
@@ -88554,6 +90858,7 @@
3254708224,3254708735,UA
3254708736,3254709247,RO
3254709248,3254709759,DE
+3254709760,3254710271,PL
3254710272,3254710783,IT
3254710784,3254711295,RO
3254711296,3254711807,FR
@@ -88586,6 +90891,8 @@
3254787072,3254788095,NL
3254788096,3254788351,BG
3254788352,3254789119,ES
+3254789120,3254789375,FR
+3254789632,3254790655,TK
3254796288,3254797311,SE
3254797312,3254798335,RU
3254798336,3254799359,AT
@@ -88597,6 +90904,7 @@
3254804480,3254806527,PL
3254806528,3254807551,UA
3254807552,3254808575,KZ
+3254808576,3254809599,RU
3254809600,3254810623,UA
3254810624,3254811647,RU
3254811648,3254812671,RO
@@ -88703,6 +91011,7 @@
3254840320,3254840575,DK
3254840576,3254840831,UA
3254840832,3254841343,GB
+3254841344,3254841599,PL
3254841600,3254841855,IE
3254841856,3254842111,LV
3254842112,3254842367,GB
@@ -89116,6 +91425,7 @@
3255366144,3255367167,DK
3255367168,3255367679,RU
3255367680,3255368191,UA
+3255368192,3255368703,FR
3255368704,3255369215,CZ
3255369216,3255369727,GB
3255369728,3255370239,LU
@@ -89152,7 +91462,7 @@
3255385600,3255386111,FR
3255386112,3255386623,KE
3255386624,3255387135,PL
-3255387136,3255388159,UA
+3255387648,3255388159,UA
3255388160,3255388671,DE
3255388672,3255389183,SE
3255389184,3255389695,GB
@@ -89179,7 +91489,6 @@
3255416832,3255417855,FR
3255417856,3255418879,GB
3255418880,3255422975,DE
-3255422976,3255426047,GB
3255426048,3255426559,IT
3255426560,3255426815,FR
3255426816,3255427071,PL
@@ -89278,9 +91587,7 @@
3255558144,3255558399,BE
3255558400,3255564031,CH
3255564032,3255564287,RU
-3255564288,3255565567,CH
-3255565568,3255566079,DE
-3255566080,3255566335,CH
+3255564288,3255566335,CH
3255566336,3255574527,SE
3255574528,3255578623,CZ
3255578624,3255582719,SE
@@ -89293,14 +91600,18 @@
3255660544,3255666431,NL
3255666432,3255666687,DE
3255666688,3255697407,NL
-3255697408,3255710719,SE
+3255697408,3255698687,SE
+3255698688,3255698943,GB
+3255698944,3255710719,SE
3255710720,3255710975,ES
3255710976,3255724543,SE
3255724544,3255725055,US
3255725056,3255725311,ES
3255725312,3255739647,SE
3255739648,3255739903,GB
-3255739904,3255743231,SE
+3255739904,3255742719,SE
+3255742720,3255742975,SG
+3255742976,3255743231,SE
3255743232,3255743487,IT
3255743488,3255743743,DE
3255743744,3255745535,SE
@@ -89335,7 +91646,11 @@
3256075008,3256076287,DK
3256076288,3256076799,SE
3256076800,3256082431,DK
-3256082432,3256090623,LV
+3256082432,3256088063,LV
+3256088064,3256088095,RU
+3256088096,3256088103,LV
+3256088104,3256088319,RU
+3256088320,3256090623,LV
3256090624,3256164863,IT
3256164864,3256165375,SE
3256165376,3256187391,IT
@@ -89481,7 +91796,7 @@
3256699392,3256700415,GB
3256700416,3256700671,NL
3256700672,3256700927,FR
-3256700928,3256701183,EU
+3256700928,3256701183,DE
3256701184,3256701439,BE
3256701440,3256701695,GB
3256701696,3256705279,EU
@@ -90490,9 +92805,7 @@
3257827840,3257829375,GB
3257829376,3257830399,IE
3257830400,3257835519,GB
-3257835520,3257844223,IE
-3257844224,3257851903,GB
-3257851904,3257860095,IE
+3257835520,3257860095,IE
3257860096,3257925631,SE
3257925632,3257925887,AT
3257925888,3257926143,SE
@@ -90833,17 +93146,27 @@
3259236864,3259237119,CH
3259237120,3259237887,SE
3259237888,3259238143,FR
-3259238144,3259248127,SE
+3259238144,3259243519,SE
+3259243520,3259244543,US
+3259244544,3259248127,SE
3259248128,3259248383,GB
3259248384,3259258623,SE
3259258624,3259258879,ES
3259258880,3259262719,SE
3259262720,3259262975,DK
-3259262976,3259269375,SE
+3259262976,3259266047,SE
+3259266048,3259266303,SG
+3259266304,3259269375,SE
3259269376,3259269631,FR
3259269632,3259276287,SE
3259276288,3259276543,ES
-3259276544,3259285759,SE
+3259276544,3259279615,SE
+3259279616,3259279871,JP
+3259279872,3259281407,SE
+3259281408,3259282431,US
+3259282432,3259282687,SE
+3259282688,3259282943,JP
+3259282944,3259285759,SE
3259285760,3259286015,GB
3259286016,3259290879,SE
3259290880,3259291135,US
@@ -90965,7 +93288,9 @@
3259461376,3259461631,GB
3259461632,3259465215,SE
3259465216,3259465471,KH
-3259465472,3259479807,SE
+3259465472,3259470847,SE
+3259470848,3259471871,US
+3259471872,3259479807,SE
3259479808,3259480063,DK
3259480064,3259480831,SE
3259480832,3259481087,ES
@@ -91061,7 +93386,9 @@
3259696640,3259696895,ES
3259696896,3259701759,GB
3259701760,3259702303,DE
-3259702304,3259752191,GB
+3259702304,3259709999,GB
+3259710000,3259710007,JE
+3259710008,3259752191,GB
3259752192,3259752447,FR
3259752448,3259760639,GB
3259760640,3259814399,DE
@@ -91154,6 +93481,7 @@
3260587520,3260588031,PL
3260588032,3260596223,DE
3260596224,3260596735,CH
+3260596736,3260597247,SK
3260597248,3260597759,CH
3260597760,3260598271,DE
3260598272,3260598783,RU
@@ -91210,6 +93538,7 @@
3260901120,3260903423,DE
3260903424,3260906239,CH
3260906240,3260906495,DE
+3260906496,3260907519,PL
3260907520,3260915711,GB
3260915712,3260923903,UA
3260923904,3261071359,DE
@@ -91237,7 +93566,13 @@
3261503936,3261530111,RO
3261530112,3261531903,SE
3261531904,3261532159,GB
-3261532160,3261570303,SE
+3261532160,3261532671,SE
+3261532672,3261532927,US
+3261532928,3261533439,SE
+3261533440,3261533695,US
+3261533696,3261539327,SE
+3261539328,3261540351,SG
+3261540352,3261570303,SE
3261570304,3261570559,IT
3261570560,3261595647,SE
3261595648,3261661183,NL
@@ -91264,8 +93599,7 @@
3261697024,3261698047,RO
3261698048,3261698559,UA
3261698560,3261699071,DE
-3261699072,3261699583,SA
-3261699584,3261700095,NL
+3261699072,3261700095,NL
3261700096,3261700607,FR
3261700608,3261701119,GB
3261701120,3261701631,RU
@@ -91282,7 +93616,6 @@
3261775872,3261776383,PL
3261776384,3261777407,RU
3261777408,3261777663,IR
-3261777664,3261777919,KZ
3261777920,3261778431,PL
3261778432,3261778943,RU
3261778944,3261779455,RO
@@ -91571,7 +93904,7 @@
3262283776,3262284799,RU
3262284800,3262286847,UA
3262286848,3262287871,SE
-3262287872,3262289919,PL
+3262288896,3262289919,PL
3262289920,3262316543,SE
3262316544,3262348799,DE
3262348800,3262349055,NL
@@ -91593,6 +93926,10 @@
3262423040,3262423551,GB
3262423552,3262424063,UA
3262424064,3262424575,IT
+3262424576,3262424831,PL
+3262424832,3262425087,GB
+3262425088,3262425343,GR
+3262425344,3262425599,RU
3262425600,3262426111,UA
3262426112,3262426623,DE
3262426624,3262427135,GB
@@ -91637,7 +93974,6 @@
3262460416,3262460543,UA
3262460544,3262460671,RU
3262460672,3262460927,AE
-3262460928,3262461055,HU
3262461056,3262461183,DK
3262461184,3262461311,SN
3262461312,3262461439,NO
@@ -92393,7 +94729,7 @@
3262476656,3262476667,US
3262476668,3262476671,GB
3262476672,3262476675,SE
-3262476676,3262476679,AT
+3262476676,3262476679,DE
3262476680,3262476683,NL
3262476684,3262476687,IT
3262476688,3262476691,DE
@@ -93575,8 +95911,7 @@
3262479420,3262479420,ES
3262479421,3262479421,DE
3262479422,3262479422,SE
-3262479423,3262479423,AT
-3262479424,3262479426,DE
+3262479423,3262479426,DE
3262479427,3262479427,IT
3262479428,3262479429,FR
3262479430,3262479430,GB
@@ -94375,6 +96710,7 @@
3263072256,3263074303,LB
3263074304,3263074815,CH
3263074816,3263075327,RO
+3263075328,3263075839,IT
3263075840,3263076351,SE
3263076352,3263076863,RO
3263076864,3263077375,IT
@@ -94422,6 +96758,7 @@
3263096064,3263096319,PL
3263096320,3263096575,TR
3263096576,3263096831,SA
+3263096832,3263097087,PL
3263097088,3263097343,FR
3263097344,3263097599,DK
3263097600,3263097855,NL
@@ -94459,12 +96796,20 @@
3263459584,3263459839,FR
3263459840,3263461631,SE
3263461632,3263461887,AE
-3263461888,3263477759,SE
+3263461888,3263469567,SE
+3263469568,3263470591,SG
+3263470592,3263472127,SE
+3263472128,3263472383,SG
+3263472384,3263475711,SE
+3263475712,3263476735,JP
+3263476736,3263477759,SE
3263477760,3263478015,JP
3263478016,3263478271,AU
3263478272,3263478527,SE
3263478528,3263478783,ES
-3263478784,3263496191,SE
+3263478784,3263480831,SE
+3263480832,3263481855,JP
+3263481856,3263496191,SE
3263496192,3263497983,EU
3263497984,3263498239,GB
3263498240,3263498751,EU
@@ -94637,9 +96982,7 @@
3264092288,3264092295,AX
3264092296,3264099839,FI
3264099840,3264100095,GB
-3264100096,3264118595,FI
-3264118596,3264118599,AX
-3264118600,3264124927,FI
+3264100096,3264124927,FI
3264124928,3264125183,DE
3264125184,3264125439,NL
3264125440,3264125695,FI
@@ -94697,6 +97040,7 @@
3264320000,3264320255,DE
3264320256,3264321023,GB
3264321024,3264321535,DE
+3264321536,3264321791,GB
3264321792,3264322047,RS
3264322048,3264322303,FR
3264322304,3264322559,RO
@@ -94761,7 +97105,7 @@
3264378880,3264379135,PL
3264379136,3264379391,BE
3264379392,3264379647,RU
-3264379648,3264380159,DE
+3264379904,3264380159,DE
3264380160,3264380415,RO
3264380416,3264380671,CH
3264380672,3264380927,NL
@@ -94846,17 +97190,28 @@
3264613312,3264613375,GB
3264613376,3264613887,NL
3264613888,3264613895,GB
-3264613896,3264613903,NL
-3264613904,3264614399,GB
+3264613896,3264613919,NL
+3264613920,3264614399,GB
3264614400,3264614655,NL
3264614656,3264614911,SE
3264614912,3264615423,GB
-3264615424,3264615727,CH
-3264615728,3264617215,GB
-3264617216,3264617471,DE
+3264615424,3264615735,CH
+3264615736,3264615743,GB
+3264615744,3264615775,CH
+3264615776,3264616447,GB
+3264616448,3264616463,DE
+3264616464,3264616575,GB
+3264616576,3264616703,DE
+3264616704,3264616959,GB
+3264616960,3264617471,DE
3264617472,3264618239,GB
3264618240,3264618495,US
-3264618496,3264622847,GB
+3264618496,3264618751,PL
+3264618752,3264619007,GB
+3264619008,3264619263,BE
+3264619264,3264620543,GB
+3264620544,3264620575,FR
+3264620576,3264622847,GB
3264622848,3264623103,FR
3264623104,3264626687,GB
3264626688,3264627711,EE
@@ -94877,6 +97232,7 @@
3264652288,3264652799,RU
3264652800,3264653311,PL
3264653312,3264653823,EU
+3264653824,3264654335,PL
3264654336,3264654847,DE
3264654848,3264655359,UA
3264655360,3264655871,GB
@@ -94997,7 +97353,7 @@
3264846592,3264846719,US
3264846720,3264846847,RU
3264846848,3264846911,DK
-3264846976,3264847103,GB
+3264847040,3264847103,GB
3264847104,3264847135,FR
3264847136,3264847167,ES
3264847168,3264847199,IE
@@ -95154,7 +97510,7 @@
3265603328,3265603583,MD
3265603584,3265603839,DE
3265603840,3265604095,PL
-3265604096,3265604351,SA
+3265604096,3265604351,NL
3265604352,3265604607,FR
3265604608,3265604863,CH
3265604864,3265605119,RU
@@ -95164,6 +97520,7 @@
3265605888,3265606143,FR
3265606400,3265606655,NL
3265606656,3265606911,AT
+3265606912,3265607167,RU
3265607168,3265607423,PL
3265607424,3265607935,DK
3265607936,3265608191,CZ
@@ -95712,9 +98069,7 @@
3267662952,3267662959,GB
3267662960,3267662991,IE
3267662992,3267663007,EU
-3267663008,3267663071,IE
-3267663072,3267663087,EU
-3267663088,3267663103,IE
+3267663008,3267663103,IE
3267663104,3267663327,IT
3267663328,3267663359,EU
3267663360,3267663871,GB
@@ -96349,7 +98704,7 @@
3269284864,3269285055,FR
3269285056,3269285087,EU
3269285088,3269285135,DE
-3269285136,3269285151,EU
+3269285136,3269285151,GB
3269285152,3269285215,DE
3269285216,3269285311,EU
3269285312,3269285327,DE
@@ -96670,6 +99025,7 @@
3270653440,3270653695,NL
3270653696,3270653951,GB
3270653952,3270654207,ES
+3270654208,3270654463,RO
3270654464,3270654719,BE
3270654720,3270655231,UA
3270655232,3270655487,IT
@@ -96941,10 +99297,14 @@
3271426304,3271491583,FR
3271491584,3271495679,DK
3271495680,3271495807,SE
-3271495808,3271501663,DK
+3271495808,3271501567,DK
+3271501568,3271501575,SE
+3271501576,3271501663,DK
3271501664,3271501679,DE
3271501680,3271501695,SE
-3271501696,3271557119,DK
+3271501696,3271501783,DK
+3271501784,3271501791,SE
+3271501792,3271557119,DK
3271557120,3271589887,BE
3271589888,3271688191,NO
3271688192,3271691775,EU
@@ -97012,6 +99372,7 @@
3271805952,3271806975,UA
3271806976,3271807999,EU
3271808000,3271810047,DE
+3271810048,3271811071,PL
3271811072,3271812095,UA
3271812096,3271813119,ES
3271813120,3271814143,PL
@@ -97040,8 +99401,8 @@
3271915008,3271915519,SE
3271915520,3271916031,NL
3271916032,3271916543,GB
-3271916544,3271917055,UA
-3271917568,3271925759,RU
+3271916544,3271917311,UA
+3271917312,3271925759,RU
3271925760,3271926015,DE
3271926016,3271926271,MD
3271926272,3271926527,RU
@@ -97154,7 +99515,7 @@
3272111872,3272112383,RO
3272112384,3272113151,DE
3272113152,3272113407,FR
-3272113664,3272113919,GB
+3272113408,3272113919,GB
3272113920,3272114175,AT
3272114176,3272122367,PL
3272122368,3272131071,GB
@@ -97349,14 +99710,16 @@
3272239688,3272239695,IM
3272239696,3272239703,GB
3272239704,3272239711,IM
-3272239712,3272239791,GB
-3272239792,3272239799,IM
+3272239712,3272239775,GB
+3272239776,3272239799,IM
3272239800,3272240127,GB
3272240128,3272240367,IM
3272240368,3272240575,GB
3272240576,3272240639,GH
3272240640,3272241215,GB
-3272241216,3272241295,IM
+3272241216,3272241247,IM
+3272241248,3272241279,GB
+3272241280,3272241295,IM
3272241296,3272241303,GB
3272241304,3272241311,IM
3272241312,3272241335,GB
@@ -97444,8 +99807,8 @@
3272376320,3272376447,SK
3272376448,3272376479,SR
3272376480,3272376495,SK
-3272376496,3272376519,SR
-3272376520,3272376535,SK
+3272376496,3272376527,SR
+3272376528,3272376535,SK
3272376536,3272376543,SR
3272376544,3272376607,SK
3272376608,3272376639,SR
@@ -97453,11 +99816,13 @@
3272376736,3272376751,SR
3272376752,3272376767,SK
3272376768,3272376831,SR
-3272376832,3272384511,SK
+3272376832,3272378183,SK
+3272378184,3272378201,SR
+3272378202,3272384511,SK
3272384512,3272392703,LT
3272392704,3272400895,AT
-3272400896,3272400903,EU
-3272400904,3272400927,GB
+3272400896,3272400911,EU
+3272400912,3272400927,GB
3272400928,3272401023,EU
3272401024,3272401087,GB
3272401088,3272401279,EU
@@ -97750,9 +100115,7 @@
3272931152,3272933375,DE
3272933376,3272940287,GB
3272940288,3272940543,DE
-3272940544,3272964351,GB
-3272964352,3272964607,DE
-3272964608,3272998911,GB
+3272940544,3272998911,GB
3272998912,3273007103,PT
3273007104,3273015295,CZ
3273015296,3273023487,SE
@@ -97855,7 +100218,7 @@
3273264640,3273265151,AT
3273265152,3273266175,UA
3273266176,3273266687,LV
-3273266688,3273267711,PL
+3273266688,3273267455,PL
3273267712,3273268223,GB
3273268224,3273268735,SE
3273268736,3273269247,RU
@@ -97885,7 +100248,8 @@
3273327424,3273327511,GB
3273327512,3273327519,EU
3273327520,3273327551,IE
-3273327552,3273328511,EU
+3273327552,3273327583,GB
+3273327584,3273328511,EU
3273328512,3273328639,DE
3273328640,3273329199,GB
3273329200,3273329215,DE
@@ -98124,14 +100488,13 @@
3273437184,3273437695,RO
3273437696,3273438207,PL
3273438208,3273438719,IL
-3273438720,3273439231,PL
3273439232,3273439743,RO
3273439744,3273440255,DE
3273440256,3273440767,RO
3273440768,3273441279,AT
3273441280,3273443327,GB
-3273443328,3273443839,FR
-3273443840,3273449471,GB
+3273443328,3273444095,FR
+3273444096,3273449471,GB
3273449472,3273457663,CH
3273457664,3273523199,HR
3273523200,3273588735,DE
@@ -98221,9 +100584,8 @@
3273878016,3273878271,FR
3273878272,3273878527,LV
3273878528,3273879039,DE
-3273879040,3273879551,EU
+3273879040,3273879551,BE
3273879552,3273880063,GB
-3273880064,3273880575,LV
3273880576,3273881087,RU
3273881088,3273881343,RO
3273881344,3273881599,CH
@@ -98280,6 +100642,8 @@
3274172416,3274172927,UA
3274172928,3274173439,DE
3274173440,3274173951,GR
+3274173952,3274174207,GB
+3274174208,3274174463,CZ
3274174464,3274175487,UA
3274175488,3274175999,BE
3274176000,3274176511,DE
@@ -98359,7 +100723,6 @@
3274398208,3274399231,RU
3274399232,3274399743,SC
3274399744,3274407935,LU
-3274407936,3274408191,ES
3274408192,3274408447,IT
3274408448,3274408703,NL
3274408704,3274408959,SI
@@ -98386,6 +100749,7 @@
3274414336,3274414591,CH
3274414592,3274414847,NL
3274414848,3274415103,IE
+3274415104,3274415359,PL
3274415360,3274415615,GB
3274415616,3274415871,NL
3274415872,3274416127,SI
@@ -98635,6 +100999,7 @@
3274701056,3274701311,DE
3274701312,3274701567,TJ
3274701568,3274701823,IT
+3274701824,3274702079,IL
3274702080,3274702335,UA
3274702336,3274702591,SE
3274702592,3274702847,KZ
@@ -98901,15 +101266,9 @@
3275423752,3275423775,EU
3275423776,3275423807,GB
3275423808,3275423871,EU
-3275423872,3275425067,GB
-3275425068,3275425071,EU
-3275425072,3275425087,GB
-3275425088,3275425791,EU
-3275425792,3275427639,GB
-3275427640,3275427647,EU
-3275427648,3275427759,GB
-3275427760,3275427775,EU
-3275427776,3275428399,GB
+3275423872,3275425159,GB
+3275425160,3275425791,EU
+3275425792,3275428399,GB
3275428400,3275428415,EU
3275428416,3275428447,GB
3275428448,3275429887,EU
@@ -98923,20 +101282,16 @@
3275430912,3275431935,EU
3275431936,3275432831,GB
3275432832,3275433983,EU
-3275433984,3275438647,GB
-3275438648,3275438655,EU
-3275438656,3275438671,GB
-3275438672,3275438687,EU
-3275438688,3275439103,GB
-3275439104,3275440127,EU
+3275433984,3275439423,GB
+3275439424,3275440127,EU
3275440128,3275440639,GB
3275440640,3275442175,EU
3275442176,3275442719,GB
3275442720,3275444223,EU
3275444224,3275444735,GB
3275444736,3275446271,EU
-3275446272,3275447135,GB
-3275447136,3275448319,EU
+3275446272,3275447151,GB
+3275447152,3275448319,EU
3275448320,3275449519,GB
3275449520,3275449527,FR
3275449528,3275450879,GB
@@ -98945,13 +101300,12 @@
3275451264,3275452415,EU
3275452416,3275454127,GB
3275454128,3275454143,EU
-3275454144,3275456383,GB
-3275456384,3275456391,EU
-3275456392,3275457023,GB
+3275454144,3275457023,GB
3275457024,3275457791,FK
3275457792,3275458559,GB
3275458560,3275460095,IE
-3275460096,3275460607,EU
+3275460096,3275460223,GB
+3275460224,3275460607,EU
3275460608,3275460863,HK
3275460864,3275463523,GB
3275463524,3275463527,EU
@@ -98965,8 +101319,18 @@
3275468768,3275468799,IE
3275468800,3275469071,GB
3275469072,3275469087,IE
-3275469088,3275473215,GB
-3275473216,3275489279,EU
+3275469088,3275473519,GB
+3275473520,3275473535,EU
+3275473536,3275473599,GB
+3275473600,3275474943,EU
+3275474944,3275474975,GB
+3275474976,3275475071,EU
+3275475072,3275475199,GB
+3275475200,3275476991,EU
+3275476992,3275477055,GB
+3275477056,3275477503,EU
+3275477504,3275477567,GB
+3275477568,3275489279,EU
3275489280,3275497471,GB
3275497472,3275505663,DE
3275505664,3275506175,PL
@@ -98988,7 +101352,6 @@
3275510464,3275510527,GB
3275510528,3275510559,PL
3275510560,3275510591,DE
-3275510592,3275510623,FR
3275510624,3275510655,EE
3275510656,3275510687,FR
3275510720,3275510751,GB
@@ -99010,7 +101373,7 @@
3275512832,3275512895,SE
3275512896,3275512959,AT
3275512960,3275513023,PL
-3275513024,3275513151,UA
+3275513024,3275513087,UA
3275513152,3275513215,ES
3275513216,3275513279,CH
3275513280,3275513343,DK
@@ -99026,7 +101389,6 @@
3275530752,3275531263,AT
3275531264,3275531775,GB
3275531776,3275532287,IE
-3275532288,3275532799,CH
3275532800,3275533823,GB
3275533824,3275534335,UA
3275534336,3275534847,IL
@@ -99043,6 +101405,7 @@
3275542528,3275543551,DE
3275543552,3275544575,NL
3275544576,3275545599,PL
+3275545600,3275546623,RU
3275546624,3275547647,UA
3275548672,3275549695,IL
3275549696,3275550719,SY
@@ -99343,6 +101706,7 @@
3275909888,3275910143,SI
3275910144,3275910399,RU
3275910400,3275910655,DK
+3275910656,3275910911,UA
3275910912,3275911167,DE
3275911168,3275911423,FR
3275911424,3275911679,RO
@@ -99427,11 +101791,15 @@
3276014472,3276014495,GB
3276014496,3276014775,FR
3276014776,3276014783,GB
-3276014784,3276014887,FR
+3276014784,3276014815,FR
+3276014816,3276014823,GB
+3276014824,3276014887,FR
3276014888,3276014895,IE
3276014896,3276014943,FR
3276014944,3276014951,GB
-3276014952,3276015103,FR
+3276014952,3276015031,FR
+3276015032,3276015039,GB
+3276015040,3276015103,FR
3276015104,3276015119,GB
3276015120,3276015199,FR
3276015200,3276015231,GB
@@ -99493,8 +101861,8 @@
3276018240,3276018271,GB
3276018272,3276018375,FR
3276018376,3276018383,GB
-3276018384,3276018431,FR
-3276018432,3276018447,GB
+3276018384,3276018423,FR
+3276018424,3276018447,GB
3276018448,3276018495,FR
3276018496,3276018527,GB
3276018528,3276018543,FR
@@ -99507,9 +101875,7 @@
3276019024,3276019071,GB
3276019072,3276019135,FR
3276019136,3276019151,GB
-3276019152,3276019463,FR
-3276019464,3276019471,GB
-3276019472,3276019479,FR
+3276019152,3276019479,FR
3276019480,3276019487,GB
3276019488,3276019503,FR
3276019504,3276019511,GB
@@ -99549,11 +101915,17 @@
3276020880,3276020887,GB
3276020888,3276020943,FR
3276020944,3276020991,GB
-3276020992,3276021591,FR
+3276020992,3276021103,FR
+3276021104,3276021111,GB
+3276021112,3276021591,FR
3276021592,3276021599,GB
3276021600,3276021815,FR
3276021816,3276021823,GB
-3276021824,3276022127,FR
+3276021824,3276021847,FR
+3276021848,3276021855,GB
+3276021856,3276022031,FR
+3276022032,3276022039,GB
+3276022040,3276022127,FR
3276022128,3276022143,GB
3276022144,3276022215,FR
3276022216,3276022223,GB
@@ -99611,9 +101983,7 @@
3276025248,3276025279,GB
3276025280,3276025295,FR
3276025296,3276025327,GB
-3276025328,3276026143,FR
-3276026144,3276026159,GB
-3276026160,3276026167,FR
+3276025328,3276026167,FR
3276026168,3276026175,GB
3276026176,3276026191,FR
3276026192,3276026199,GB
@@ -99785,7 +102155,9 @@
3276036384,3276036415,GB
3276036416,3276036591,FR
3276036592,3276036607,GB
-3276036608,3276037127,FR
+3276036608,3276036639,FR
+3276036640,3276036863,GB
+3276036864,3276037127,FR
3276037128,3276037135,GB
3276037136,3276037199,FR
3276037200,3276037215,GB
@@ -99827,9 +102199,7 @@
3276040064,3276040095,GB
3276040096,3276040159,FR
3276040160,3276040175,GB
-3276040176,3276040191,FR
-3276040192,3276040215,GB
-3276040216,3276040231,FR
+3276040176,3276040231,FR
3276040232,3276040239,GB
3276040240,3276040319,FR
3276040320,3276040327,GB
@@ -99847,8 +102217,8 @@
3276040640,3276040671,GB
3276040672,3276040879,FR
3276040880,3276040895,GB
-3276040896,3276040991,FR
-3276040992,3276041007,GB
+3276040896,3276040975,FR
+3276040976,3276041007,GB
3276041008,3276041071,FR
3276041072,3276041087,GB
3276041088,3276041199,FR
@@ -99909,9 +102279,7 @@
3276044992,3276044999,GB
3276045000,3276045023,FR
3276045024,3276045039,GB
-3276045040,3276045063,FR
-3276045064,3276045071,GB
-3276045072,3276045111,FR
+3276045040,3276045111,FR
3276045112,3276045151,GB
3276045152,3276045191,FR
3276045192,3276045199,GB
@@ -99968,6 +102336,8 @@
3276074496,3276075007,GB
3276075008,3276075519,RU
3276075520,3276076031,DE
+3276076032,3276076287,NL
+3276076288,3276076543,RU
3276076544,3276077055,DE
3276077056,3276077567,UA
3276077568,3276078079,FR
@@ -100007,7 +102377,6 @@
3276127232,3276128255,UZ
3276128256,3276129279,AT
3276129280,3276131327,UA
-3276131328,3276132351,DK
3276132352,3276133375,PL
3276133376,3276134399,GB
3276134400,3276135423,RU
@@ -100015,6 +102384,7 @@
3276136448,3276137471,NL
3276137472,3276138495,PL
3276138496,3276139519,NL
+3276139520,3276140543,RU
3276140544,3276141567,DE
3276141568,3276143615,UA
3276143616,3276144639,GB
@@ -100026,11 +102396,7 @@
3276185600,3276193791,NO
3276193792,3276201983,RU
3276201984,3276210175,AT
-3276210176,3276233791,DE
-3276233792,3276233799,RO
-3276233800,3276233807,DE
-3276233808,3276233823,RO
-3276233824,3276234303,DE
+3276210176,3276234303,DE
3276234304,3276234367,GB
3276234368,3276241759,DE
3276241760,3276241767,FR
@@ -100045,7 +102411,9 @@
3276250096,3276275711,DE
3276275712,3276283903,SK
3276283904,3276292095,GB
-3276292096,3276300287,BE
+3276292096,3276294655,BE
+3276294656,3276294663,LU
+3276294664,3276300287,BE
3276300288,3276304383,DE
3276304384,3276304639,BG
3276304640,3276305407,GB
@@ -102146,7 +104514,8 @@
3276474368,3276474623,EU
3276474624,3276474879,GB
3276474880,3276475015,EU
-3276475016,3276475039,IT
+3276475016,3276475023,IT
+3276475024,3276475039,FR
3276475040,3276475055,EU
3276475056,3276475071,IT
3276475072,3276475903,EU
@@ -102451,7 +104820,9 @@
3276528448,3276528503,BE
3276528504,3276528511,EU
3276528512,3276528519,BE
-3276528520,3276528559,EU
+3276528520,3276528527,EU
+3276528528,3276528543,BE
+3276528544,3276528559,EU
3276528560,3276528567,BE
3276528568,3276528575,EU
3276528576,3276528719,BE
@@ -102531,8 +104902,8 @@
3276535344,3276535351,EU
3276535352,3276535359,FI
3276535360,3276535375,EU
-3276535376,3276535423,FI
-3276535424,3276535551,EU
+3276535376,3276535455,FI
+3276535456,3276535551,EU
3276535552,3276535807,PK
3276535808,3276536063,FI
3276536064,3276536319,EU
@@ -103033,7 +105404,9 @@
3276872480,3276872511,GB
3276872512,3276872703,DE
3276872704,3276873727,GB
-3276873728,3276874559,ES
+3276873728,3276874367,ES
+3276874368,3276874495,GB
+3276874496,3276874559,ES
3276874560,3276874751,GB
3276874752,3276875007,NL
3276875008,3276875263,CH
@@ -103062,9 +105435,11 @@
3276881152,3276881279,GB
3276881280,3276881407,DE
3276881408,3276881919,FR
-3276881920,3276883967,IT
-3276883968,3276884487,PL
-3276884488,3276884735,GB
+3276881920,3276883327,IT
+3276883328,3276883391,GB
+3276883392,3276883967,IT
+3276883968,3276884495,PL
+3276884496,3276884735,GB
3276884736,3276884991,PL
3276884992,3276886015,GB
3276886016,3276886271,RO
@@ -103076,8 +105451,8 @@
3276887056,3276887071,GB
3276887072,3276888063,DE
3276888064,3276888575,GB
-3276888576,3276888831,IT
-3276888832,3276890111,GB
+3276888576,3276889087,IT
+3276889088,3276890111,GB
3276890112,3276890135,US
3276890136,3276890143,GB
3276890144,3276890207,US
@@ -103097,13 +105472,17 @@
3276896896,3276896927,BE
3276896928,3276897023,GB
3276897024,3276897663,BE
-3276897664,3276898047,GB
-3276898048,3276898303,CZ
-3276898304,3276898655,CH
+3276897664,3276897919,GB
+3276897920,3276898303,CZ
+3276898304,3276898399,CH
+3276898400,3276898407,GB
+3276898408,3276898655,CH
3276898656,3276898671,GB
3276898672,3276898775,CH
3276898776,3276898783,GB
-3276898784,3276900039,CH
+3276898784,3276899071,CH
+3276899072,3276899087,GB
+3276899088,3276900039,CH
3276900040,3276900047,GB
3276900048,3276900351,CH
3276900352,3276900607,GB
@@ -103115,11 +105494,11 @@
3276901624,3276901631,GB
3276901632,3276902151,CH
3276902152,3276902159,GB
-3276902160,3276902199,CH
-3276902200,3276902207,GB
-3276902208,3276902335,CH
+3276902160,3276902335,CH
3276902336,3276902399,GB
-3276902400,3276902583,SE
+3276902400,3276902559,SE
+3276902560,3276902575,GB
+3276902576,3276902583,SE
3276902584,3276902615,GB
3276902616,3276902639,SE
3276902640,3276902655,GB
@@ -103127,7 +105506,11 @@
3276903320,3276903327,GB
3276903328,3276903359,NO
3276903360,3276903935,SE
-3276903936,3276904191,GB
+3276903936,3276903999,GB
+3276904000,3276904079,SE
+3276904080,3276904095,GB
+3276904096,3276904127,SE
+3276904128,3276904191,GB
3276904192,3276904447,SE
3276904448,3276905311,GB
3276905312,3276905319,ES
@@ -103145,7 +105528,9 @@
3276906624,3276906751,GB
3276906752,3276906823,NL
3276906824,3276906831,CH
-3276906832,3276907551,NL
+3276906832,3276907339,NL
+3276907340,3276907343,GB
+3276907344,3276907551,NL
3276907552,3276907567,BE
3276907568,3276907643,NL
3276907644,3276907647,GB
@@ -103164,7 +105549,9 @@
3276912624,3276913183,IT
3276913184,3276913215,GB
3276913216,3276913359,IT
-3276913360,3276913375,GB
+3276913360,3276913360,GB
+3276913361,3276913374,IT
+3276913375,3276913375,GB
3276913376,3276913919,IT
3276913920,3276913983,US
3276913984,3276914079,IT
@@ -103174,7 +105561,8 @@
3276914160,3276914687,IT
3276914688,3276915567,ES
3276915568,3276915583,NL
-3276915584,3276916087,ES
+3276915584,3276915711,GB
+3276915712,3276916087,ES
3276916088,3276916095,GB
3276916096,3276916175,ES
3276916176,3276916183,GB
@@ -103266,6 +105654,7 @@
3277187072,3277187327,GB
3277187328,3277187583,UA
3277187584,3277188351,RU
+3277188352,3277188607,DE
3277188608,3277188863,RU
3277188864,3277189119,RO
3277189120,3277189375,DE
@@ -103352,7 +105741,6 @@
3277359616,3277360127,UA
3277360128,3277360639,BG
3277360640,3277361151,CZ
-3277361152,3277361663,UA
3277361664,3277362175,RU
3277362176,3277362687,ES
3277362688,3277363199,IE
@@ -103369,7 +105757,6 @@
3277368320,3277369343,RO
3277369344,3277369855,CY
3277369856,3277370367,RU
-3277370368,3277370879,SE
3277370880,3277371391,RO
3277371392,3277371903,RU
3277371904,3277372415,PL
@@ -103541,6 +105928,7 @@
3277822208,3277822463,ES
3277822464,3277822719,PL
3277822720,3277822975,RU
+3277822976,3277823231,ES
3277823232,3277823487,UA
3277823488,3277823743,SI
3277823744,3277823999,UA
@@ -103580,7 +105968,8 @@
3277835776,3277836287,UA
3277836288,3277836799,FI
3277836800,3277837311,UA
-3277837312,3277838847,RU
+3277837312,3277839103,RU
+3277839104,3277839359,CH
3277839360,3277839871,DE
3277839872,3277840383,UA
3277840384,3277840895,FR
@@ -103599,21 +105988,23 @@
3277856768,3277864959,DE
3277864960,3277873151,RU
3277873152,3277881343,NL
-3277881344,3277884175,IT
+3277881344,3277881375,A2
+3277881376,3277881407,IT
+3277881408,3277884175,A2
3277884176,3277884191,IR
-3277884192,3277885439,IT
+3277884192,3277885439,A2
3277885440,3277885695,IQ
3277885696,3277885727,LB
-3277885728,3277885951,IT
+3277885728,3277885951,A2
3277885952,3277886463,LB
3277886464,3277886719,IQ
3277886720,3277886975,IR
3277886976,3277887487,IQ
-3277887488,3277888255,IT
+3277887488,3277888255,A2
3277888256,3277888319,LB
-3277888320,3277889023,IT
+3277888320,3277889023,A2
3277889024,3277889279,IQ
-3277889280,3277889535,IT
+3277889280,3277889535,A2
3277889536,3277897727,RU
3277897728,3277905919,IT
3277905920,3277914111,BG
@@ -105449,7 +107840,7 @@
3278943912,3278943913,IT
3278943914,3278943914,DE
3278943915,3278943915,PL
-3278943916,3278943916,IT
+3278943916,3278943916,DE
3278943917,3278943917,FR
3278943918,3278943918,ES
3278943919,3278943920,FR
@@ -106171,6 +108562,7 @@
3279053312,3279053823,DE
3279053824,3279054335,NL
3279054336,3279054847,GB
+3279054848,3279055359,RU
3279055360,3279055871,SA
3279055872,3279056383,TR
3279056384,3279056895,GB
@@ -106188,7 +108580,8 @@
3279078656,3279078911,FR
3279078912,3279084543,ES
3279084544,3279085567,IT
-3279085568,3279093759,NL
+3279085568,3279093503,NL
+3279093504,3279093759,DE
3279093760,3279103103,FR
3279103104,3279103135,GB
3279103136,3279119295,FR
@@ -106602,7 +108995,9 @@
3280390720,3280390751,FR
3280390752,3280392703,GB
3280392704,3280392831,FR
-3280392832,3280396287,GB
+3280392832,3280395263,GB
+3280395264,3280395519,FR
+3280395520,3280396287,GB
3280396288,3280404479,FI
3280404480,3280437247,IT
3280437248,3280453631,DE
@@ -106614,8 +109009,10 @@
3280458752,3280459775,RU
3280459776,3280460799,DK
3280460800,3280462847,DE
+3280462848,3280463871,PL
3280463872,3280466943,RU
3280466944,3280467967,UA
+3280467968,3280468991,ES
3280468992,3280470015,CY
3280470016,3280535551,PL
3280535552,3280568319,GB
@@ -106663,6 +109060,7 @@
3280589312,3280590335,DE
3280590336,3280590847,NL
3280590848,3280591359,DE
+3280591360,3280591871,UA
3280591872,3280592383,GB
3280592384,3280592895,TR
3280592896,3280593407,DE
@@ -107456,7 +109854,9 @@
3280963312,3280963327,GB
3280963328,3280963343,DE
3280963344,3280963359,GB
-3280963360,3280963495,DE
+3280963360,3280963423,DE
+3280963424,3280963487,GB
+3280963488,3280963495,DE
3280963496,3280963511,GB
3280963512,3280963515,DE
3280963516,3280963519,GB
@@ -107558,7 +109958,9 @@
3280976720,3280976831,GB
3280976832,3280976847,DE
3280976848,3280976895,GB
-3280976896,3280977119,DE
+3280976896,3280977023,DE
+3280977024,3280977031,GB
+3280977032,3280977119,DE
3280977120,3280977135,GB
3280977136,3280977407,DE
3280977408,3280977439,GB
@@ -108233,6 +110635,7 @@
3281339392,3281339647,PL
3281339648,3281339903,GB
3281339904,3281340159,UA
+3281340160,3281340415,BG
3281340416,3281340927,RO
3281340928,3281341183,DE
3281341184,3281341439,AT
@@ -108246,7 +110649,7 @@
3281344000,3281344255,FR
3281344256,3281344511,RU
3281344512,3281344767,UA
-3281344768,3281345023,RU
+3281344768,3281345279,RU
3281345280,3281345535,SA
3281345536,3281345791,CH
3281345792,3281346047,RU
@@ -109341,6 +111744,7 @@
3284047104,3284047359,DK
3284047360,3284047615,DE
3284047616,3284047871,NL
+3284047872,3284048127,UA
3284048128,3284048383,DK
3284048384,3284048639,GB
3284048640,3284049151,FR
@@ -109480,7 +111884,6 @@
3284598784,3284664319,HU
3284664320,3284672511,GB
3284672512,3284680703,DE
-3284680704,3284681215,UA
3284681216,3284681727,RO
3284681728,3284682239,FI
3284682240,3284682751,DE
@@ -109489,8 +111892,7 @@
3284683776,3284684287,GB
3284684288,3284684799,FR
3284684800,3284685311,DE
-3284685312,3284685823,NL
-3284685824,3284686335,US
+3284685312,3284686335,NL
3284686336,3284686847,RO
3284686848,3284687359,PL
3284687360,3284687871,UA
@@ -109781,8 +112183,8 @@
3285462952,3285462959,AT
3285462960,3285463007,EU
3285463008,3285463039,AT
-3285463040,3285463079,LU
-3285463080,3285463103,EU
+3285463040,3285463087,LU
+3285463088,3285463103,EU
3285463104,3285463135,LU
3285463136,3285463295,EU
3285463296,3285463311,FR
@@ -109881,8 +112283,7 @@
3285472512,3285473327,EU
3285473328,3285473343,DE
3285473344,3285473439,EU
-3285473440,3285473567,DE
-3285473568,3285473583,EU
+3285473440,3285473583,DE
3285473584,3285473591,GB
3285473592,3285473599,DE
3285473600,3285473631,EU
@@ -109929,9 +112330,7 @@
3285476896,3285477023,EU
3285477024,3285477087,AT
3285477088,3285477151,EU
-3285477152,3285477319,IT
-3285477320,3285477327,EU
-3285477328,3285477343,IT
+3285477152,3285477343,IT
3285477344,3285477359,EU
3285477360,3285477375,IT
3285477376,3285477631,FR
@@ -110831,7 +113230,8 @@
3285571904,3285571967,SE
3285571968,3285572095,BE
3285572096,3285572223,DE
-3285572224,3285572351,FI
+3285572224,3285572335,BE
+3285572336,3285572351,ES
3285572352,3285572367,IR
3285572368,3285572383,ES
3285572384,3285572447,BE
@@ -110986,8 +113386,7 @@
3285860352,3285868543,FI
3285868544,3285876735,IE
3285876736,3285909503,RU
-3285909504,3285910015,GB
-3285910016,3285910271,EU
+3285909504,3285910271,GB
3285910272,3285910303,ES
3285910304,3285910335,GB
3285910336,3285910399,ES
@@ -110999,9 +113398,7 @@
3285911552,3285912575,EU
3285912576,3285913087,GB
3285913088,3285913215,ES
-3285913216,3285913231,GB
-3285913232,3285913247,EU
-3285913248,3285913279,GB
+3285913216,3285913279,GB
3285913280,3285913343,ES
3285913344,3285913599,GB
3285913600,3285915647,EU
@@ -111013,8 +113410,8 @@
3285916704,3285916711,DE
3285916712,3285916719,CY
3285916720,3285916735,ES
-3285916736,3285916799,GB
-3285916800,3285916927,EU
+3285916736,3285916831,GB
+3285916832,3285916927,EU
3285916928,3285917183,GB
3285917184,3285917439,ES
3285917440,3285917695,YE
@@ -111046,12 +113443,11 @@
3285926408,3285926415,ES
3285926416,3285926431,GB
3285926432,3285926463,CH
-3285926464,3285926511,GB
-3285926512,3285926623,EU
+3285926464,3285926527,GB
+3285926528,3285926623,EU
3285926624,3285926631,US
3285926632,3285926639,EU
-3285926640,3285926671,GB
-3285926672,3285926687,EU
+3285926640,3285926687,GB
3285926688,3285926719,IN
3285926720,3285926783,EU
3285926784,3285926815,GB
@@ -111060,19 +113456,19 @@
3285926912,3285927423,DE
3285927424,3285927679,GB
3285927680,3285927935,IR
-3285927936,3285928063,EU
+3285927936,3285927951,GB
+3285927952,3285928063,EU
3285928064,3285928191,ES
3285928192,3285928207,PL
3285928208,3285928223,GB
3285928224,3285928255,DE
3285928256,3285928271,GB
3285928272,3285928287,DE
-3285928288,3285928319,GB
-3285928320,3285928447,EU
+3285928288,3285928335,GB
+3285928336,3285928447,EU
3285928448,3285928959,ES
3285928960,3285929983,EU
-3285929984,3285930511,GB
-3285930512,3285930559,EU
+3285929984,3285930559,GB
3285930560,3285930575,ES
3285930576,3285930623,GB
3285930624,3285930631,BE
@@ -111081,9 +113477,7 @@
3285930656,3285930671,NL
3285930672,3285930679,BE
3285930680,3285930687,DE
-3285930688,3285930719,GB
-3285930720,3285930751,EU
-3285930752,3285931007,GB
+3285930688,3285931007,GB
3285931008,3285932031,EU
3285932032,3285932287,NL
3285932288,3285932799,GB
@@ -111096,7 +113490,8 @@
3285934848,3285935615,GB
3285935616,3285938175,EU
3285938176,3285938431,ES
-3285938432,3285938559,EU
+3285938432,3285938447,GB
+3285938448,3285938559,EU
3285938560,3285938607,GB
3285938608,3285938623,FR
3285938624,3285938631,NG
@@ -111108,7 +113503,9 @@
3285938952,3285938959,NL
3285938960,3285938975,US
3285938976,3285939071,ES
-3285939072,3285939199,EU
+3285939072,3285939087,EU
+3285939088,3285939103,FR
+3285939104,3285939199,EU
3285939200,3285939711,ES
3285939712,3285940223,EU
3285940224,3285940479,ES
@@ -111121,14 +113518,16 @@
3285943552,3285943567,GB
3285943568,3285943575,ES
3285943576,3285943583,DE
-3285943584,3285943631,GB
-3285943632,3285943679,EU
+3285943584,3285943647,GB
+3285943648,3285943679,NG
3285943680,3285943807,GB
3285943808,3285944319,EU
3285944320,3285944831,US
3285944832,3285945343,DK
3285945344,3285945599,ES
-3285945600,3285945663,EU
+3285945600,3285945615,EU
+3285945616,3285945631,GB
+3285945632,3285945663,EU
3285945664,3285945695,FR
3285945696,3285945743,GB
3285945744,3285945855,EU
@@ -111147,18 +113546,18 @@
3285949696,3285949823,ES
3285949824,3285949855,EU
3285949856,3285949887,ES
-3285949888,3285949903,GB
-3285949904,3285949951,EU
+3285949888,3285949919,GB
+3285949920,3285949951,EU
3285949952,3285950463,ES
3285950464,3285950719,GB
3285950720,3285950783,US
-3285950784,3285950799,GB
-3285950800,3285950959,EU
-3285950960,3285950975,GB
+3285950784,3285950815,GB
+3285950816,3285950943,EU
+3285950944,3285950975,GB
3285950976,3285951231,NL
3285951232,3285951487,IT
-3285951488,3285951503,GB
-3285951504,3285951615,EU
+3285951488,3285951519,GB
+3285951520,3285951615,EU
3285951616,3285951647,GB
3285951648,3285951679,ES
3285951680,3285951695,GB
@@ -111177,8 +113576,8 @@
3285957632,3285957887,PL
3285957888,3285958143,GB
3285958144,3285958655,EU
-3285958656,3285958671,GB
-3285958672,3285958783,EU
+3285958656,3285958687,GB
+3285958688,3285958783,EU
3285958784,3285958799,GB
3285958800,3285958847,EU
3285958848,3285958895,NL
@@ -111202,8 +113601,8 @@
3285968384,3285968639,ES
3285968640,3285968895,PL
3285968896,3285971007,EU
-3285971008,3285971023,GB
-3285971024,3285971183,EU
+3285971008,3285971039,GB
+3285971040,3285971183,EU
3285971184,3285971199,GB
3285971200,3285971455,FR
3285971456,3285971711,DE
@@ -111246,9 +113645,7 @@
3286264880,3286264895,NL
3286264896,3286279423,GB
3286279424,3286279679,US
-3286279680,3286289919,GB
-3286289920,3286290175,US
-3286290176,3286291807,GB
+3286279680,3286291807,GB
3286291808,3286291823,US
3286291824,3286302719,GB
3286302720,3286310911,NO
@@ -111315,7 +113712,9 @@
3286367232,3286368255,BG
3286368256,3286376447,CH
3286376448,3286384639,GB
-3286384640,3286401023,DE
+3286384640,3286397607,DE
+3286397608,3286397615,A2
+3286397616,3286401023,DE
3286401024,3286409215,GB
3286409216,3286417407,DE
3286417408,3286417663,UA
@@ -111449,74 +113848,7 @@
3286790912,3286791679,GB
3286791680,3286791935,AT
3286791936,3286794239,GB
-3286794240,3286795263,DE
-3286795264,3286795519,LR
-3286795520,3286795775,DE
-3286795776,3286796031,LR
-3286796032,3286796287,DE
-3286796288,3286796543,LR
-3286796544,3286796799,DE
-3286796800,3286797055,RO
-3286797056,3286797311,DE
-3286797312,3286797567,HU
-3286797568,3286798847,DE
-3286798848,3286799359,IT
-3286799360,3286801407,DE
-3286801408,3286801663,NL
-3286801664,3286802943,DE
-3286802944,3286803199,AU
-3286803200,3286805503,DE
-3286805504,3286806527,GB
-3286806528,3286808063,DE
-3286808064,3286808575,GR
-3286808576,3286809087,EG
-3286809088,3286809599,DE
-3286809600,3286809855,GB
-3286809856,3286810111,PT
-3286810112,3286812927,DE
-3286812928,3286813183,PT
-3286813184,3286813695,EG
-3286813696,3286813951,DE
-3286813952,3286814207,AU
-3286814208,3286814719,HU
-3286814720,3286819839,DE
-3286819840,3286820863,NZ
-3286820864,3286826751,DE
-3286826752,3286827007,IT
-3286827008,3286827263,DE
-3286827264,3286827519,GB
-3286827520,3286832127,DE
-3286832128,3286832895,GB
-3286832896,3286835711,DE
-3286835712,3286836223,ES
-3286836224,3286836479,IT
-3286836480,3286836735,DE
-3286836736,3286836991,IT
-3286836992,3286837247,DE
-3286837248,3286839295,GB
-3286839296,3286839807,DE
-3286839808,3286840319,ES
-3286840320,3286841087,DE
-3286841088,3286841343,IT
-3286841344,3286842623,DE
-3286842624,3286843391,IT
-3286843392,3286844415,IE
-3286844416,3286844671,IT
-3286844672,3286847487,DE
-3286847488,3286848511,GB
-3286848512,3286849535,DE
-3286849536,3286849791,IT
-3286849792,3286851583,DE
-3286851584,3286852607,IE
-3286852608,3286855679,DE
-3286855680,3286857727,IE
-3286857728,3286864895,DE
-3286864896,3286865151,IT
-3286865152,3286872063,DE
-3286872064,3286879231,IE
-3286879232,3286882303,DE
-3286882304,3286883327,IE
-3286883328,3286888447,DE
+3286794240,3286888447,DE
3286888448,3286889471,IE
3286889472,3286892543,DE
3286892544,3286893055,LI
@@ -111558,7 +113890,6 @@
3286907392,3286907647,AT
3286907648,3286907903,ES
3286907904,3286908159,CH
-3286908160,3286908415,UA
3286908416,3286908671,FR
3286908672,3286908927,PL
3286908928,3286909951,CH
@@ -111745,7 +114076,8 @@
3287443968,3287444479,BG
3287444480,3287444991,PL
3287444992,3287445503,DE
-3287445504,3287446527,UA
+3287445504,3287446015,GB
+3287446016,3287446527,UA
3287446528,3287447039,PL
3287447040,3287447551,IL
3287447552,3287448063,DK
@@ -111820,9 +114152,7 @@
3287515376,3287515383,CZ
3287515384,3287523303,DE
3287523304,3287523311,US
-3287523312,3287526303,DE
-3287526304,3287526311,LU
-3287526312,3287534807,DE
+3287523312,3287534807,DE
3287534808,3287534815,IT
3287534816,3287541087,DE
3287541088,3287541095,CZ
@@ -111860,7 +114190,7 @@
3287632384,3287632895,SE
3287632896,3287633407,RU
3287633408,3287633919,SK
-3287633920,3287634431,UA
+3287633920,3287634431,GB
3287634432,3287634943,RO
3287634944,3287635455,PL
3287635456,3287635967,DE
@@ -111872,7 +114202,6 @@
3287638528,3287639039,DE
3287639040,3287639551,GB
3287639552,3287640063,RU
-3287640064,3287640575,DE
3287640576,3287641087,SI
3287641088,3287641599,A2
3287641600,3287642111,FI
@@ -112195,7 +114524,6 @@
3288444928,3288449023,NG
3288449024,3288465407,SD
3288465408,3288465919,JM
-3288465920,3288466175,BW
3288466176,3288466431,MU
3288466432,3288467455,SY
3288467456,3288469503,BI
@@ -112374,7 +114702,7 @@
3290497024,3290955775,ZA
3290955776,3290980351,CR
3290980352,3290984447,ZA
-3291000832,3291004927,KE
+3290988544,3290992639,KE
3291004928,3291021311,NG
3291021312,3291029503,ZA
3291029504,3291033343,TZ
@@ -112413,6 +114741,9 @@
3291208960,3291209215,TZ
3291209216,3291209471,KE
3291209472,3291209727,AO
+3291209728,3291209983,NG
+3291209984,3291210239,GH
+3291216896,3291217919,MU
3291217920,3291230207,ZA
3291230208,3291234303,GH
3291234304,3291242495,ZA
@@ -112437,7 +114768,9 @@
3291326464,3291330559,ZA
3291330560,3291331583,TZ
3291331584,3291332607,MW
-3291332608,3291348991,NG
+3291332608,3291332615,ZA
+3291332616,3291332863,NG
+3291332864,3291348991,ZA
3291348992,3291353087,MZ
3291353088,3291353343,KE
3291353344,3291353599,EG
@@ -112594,7 +114927,7 @@
3302805504,3302809599,MW
3302813696,3302817791,NG
3302817792,3302883327,EG
-3302883328,3302948863,MA
+3302883328,3302948863,RW
3302948864,3302949119,MU
3302949120,3302949375,AO
3302949376,3302949631,ZM
@@ -112617,6 +114950,7 @@
3302955008,3302955263,LS
3302955264,3302955519,UG
3302955520,3302955775,ZW
+3302955776,3302956031,MW
3305111552,3307208703,TN
3307208704,3309305855,EG
3309305856,3312451583,ZA
@@ -112628,8 +114962,11 @@
3314286592,3314548735,DZ
3315335168,3315351551,ZA
3315351552,3315367935,ET
+3315367936,3315384319,KE
3315564544,3315568639,GH
+3315572736,3315580927,ST
3315580928,3315589119,CI
+3315589120,3315597311,CM
3315597312,3316121599,EG
3316121600,3316645887,ZA
3316645888,3317170175,KE
@@ -112657,10 +114994,13 @@
3320709120,3320840191,ZA
3321102336,3321167871,NG
3321167872,3321233407,ZA
+3321233408,3321298943,EG
+3321298944,3321364479,MA
3321364480,3321430015,KE
3321430016,3321495551,MZ
3321495552,3321561087,TZ
3321561088,3321593855,SD
+3321593856,3321626623,GH
3321626624,3321692159,SD
3321692160,3321708543,NG
3321708544,3321724927,GH
@@ -112766,7 +115106,11 @@
3323662336,3323674623,US
3323723776,3324011007,US
3324011008,3324011263,KN
-3324011264,3324036351,US
+3324011264,3324030463,US
+3324030464,3324030719,KN
+3324030720,3324035583,US
+3324035584,3324035839,KN
+3324035840,3324036351,US
3324036352,3324047615,KN
3324047616,3324051455,US
3324051456,3324182527,CA
@@ -113035,7 +115379,9 @@
3328235520,3328241663,CA
3328241664,3328243199,US
3328243200,3328245759,CA
-3328245760,3328414719,US
+3328245760,3328394239,US
+3328394240,3328394495,GB
+3328394496,3328414719,US
3328414720,3328414975,CH
3328414976,3328420351,US
3328420352,3328420607,CA
@@ -113379,7 +115725,7 @@
3338916352,3338916479,CN
3338916480,3339075583,US
3339075584,3339076863,GB
-3339076864,3339077631,NO
+3339076864,3339077631,JP
3339077632,3339077887,SG
3339077888,3339079167,US
3339079168,3339079423,DK
@@ -113401,8 +115747,9 @@
3339146496,3339147007,US
3339147008,3339147775,CA
3339147776,3339148031,MS
-3339148032,3339149311,US
-3339157504,3339159551,US
+3339148032,3339153407,US
+3339153408,3339155455,BB
+3339155456,3339159551,US
3339159552,3339160575,CA
3339160576,3339164671,US
3339164672,3339165695,CA
@@ -113418,10 +115765,15 @@
3339184128,3339184639,CA
3339184640,3339184895,US
3339184896,3339186175,CA
-3339186176,3339669503,US
+3339186176,3339327999,US
+3339328512,3339329535,CA
+3339329536,3339669503,US
3339669504,3339671807,CA
-3339672576,3339673599,US
-3339681792,3339747327,US
+3339672576,3339728895,US
+3339728896,3339729919,AG
+3339729920,3339743231,US
+3339743232,3339744255,CA
+3339744256,3339747327,US
3339747328,3339747583,CA
3339747584,3339747839,FR
3339747840,3339748351,CA
@@ -113437,14 +115789,19 @@
3339778480,3339778495,CY
3339778496,3339923455,US
3339923456,3339927551,CA
-3339943936,3339952127,US
+3339927552,3339934719,US
+3339934720,3339935743,CA
+3339935744,3339952127,US
3339952128,3339956223,CA
3339956224,3339965439,US
3339965440,3339969311,CA
3339969312,3339969327,AU
3339969328,3339969375,CA
-3339969376,3340058623,US
-3340075008,3340080127,US
+3339969376,3340071007,US
+3340071008,3340071055,GB
+3340071056,3340071063,US
+3340071064,3340071071,ES
+3340071072,3340080127,US
3340080128,3340081151,CA
3340081152,3340084223,US
3340084224,3340085247,KN
@@ -113457,16 +115814,20 @@
3340369920,3340386559,US
3340387328,3340388351,CA
3340388352,3340390399,US
-3340394496,3340429823,US
+3340390400,3340391423,CA
+3340391424,3340429823,US
3340429824,3340430079,PA
-3340430080,3340451839,US
-3340468224,3340481535,US
+3340430080,3340460031,US
+3340460032,3340462079,PR
+3340462080,3340466175,US
+3340466176,3340467199,A2
+3340467200,3340481535,US
3340481536,3340482559,CA
3340482560,3340490751,US
3340490752,3340492799,CA
3340492800,3340584703,US
3340584704,3340584959,KW
-3340584960,3340648447,US
+3340584960,3340664831,US
3340664832,3340665855,CA
3340665856,3340677119,US
3340677120,3340679167,CA
@@ -113563,8 +115924,7 @@
3340926928,3340926935,ES
3340926936,3340926951,US
3340926952,3340926959,BR
-3340926960,3341041663,US
-3341058048,3341082623,US
+3340926960,3341082623,US
3341082624,3341084671,CA
3341084672,3341444863,US
3341444864,3341445631,DE
@@ -113771,7 +116131,11 @@
3345008640,3345010687,US
3345010688,3345011711,CA
3345011712,3345301503,US
-3345317888,3345327103,US
+3345317888,3345318943,US
+3345318944,3345318975,HK
+3345318976,3345321471,US
+3345321472,3345321727,CA
+3345321728,3345327103,US
3345327104,3345328127,CA
3345328128,3345333247,US
3345333248,3345334271,MF
@@ -113781,7 +116145,11 @@
3345383424,3345384447,CA
3345384448,3345390591,US
3345390592,3345391615,CA
-3345391616,3345398783,US
+3345391616,3345393151,US
+3345393152,3345393279,AU
+3345393280,3345393407,US
+3345393408,3345393535,AU
+3345393536,3345398783,US
3345398784,3345399807,BS
3345399808,3345401855,PR
3345401856,3345403903,CA
@@ -113834,7 +116202,9 @@
3345408698,3345408701,GB
3345408702,3345408784,US
3345408785,3345408788,CA
-3345408789,3345408903,US
+3345408789,3345408888,US
+3345408889,3345408892,MX
+3345408893,3345408903,US
3345408904,3345408907,GB
3345408908,3345408949,US
3345408950,3345408993,IN
@@ -113859,11 +116229,17 @@
3345409559,3345409562,CA
3345409563,3345409576,US
3345409577,3345409580,GB
-3345409581,3345409722,US
+3345409581,3345409706,US
+3345409707,3345409718,IN
+3345409719,3345409722,US
3345409723,3345409727,GB
3345409728,3345409782,US
3345409783,3345409786,SG
-3345409787,3345409895,US
+3345409787,3345409816,US
+3345409817,3345409820,GB
+3345409821,3345409887,US
+3345409888,3345409891,GB
+3345409892,3345409895,US
3345409896,3345409899,PR
3345409900,3345409903,CA
3345409904,3345409911,US
@@ -113873,7 +116249,9 @@
3345409946,3345409949,SG
3345409950,3345409957,US
3345409958,3345409961,CA
-3345409962,3345418239,US
+3345409962,3345410032,US
+3345410033,3345410036,GB
+3345410037,3345418239,US
3345418240,3345419519,NL
3345419520,3345422847,US
3345423360,3345424383,TC
@@ -113930,7 +116308,8 @@
3346499584,3346501631,VI
3346501632,3346506039,US
3346506040,3346506055,CA
-3346506056,3346506119,US
+3346506056,3346506111,US
+3346506112,3346506119,JM
3346506120,3346506127,MX
3346506128,3346510271,US
3346510272,3346510335,IL
@@ -113940,7 +116319,9 @@
3346522348,3346522350,BD
3346522351,3346522401,US
3346522402,3346522404,IN
-3346522405,3346522691,US
+3346522405,3346522411,US
+3346522412,3346522413,AE
+3346522414,3346522691,US
3346522692,3346522704,PT
3346522705,3346522773,US
3346522774,3346522783,PT
@@ -113982,18 +116363,32 @@
3349608448,3349609215,US
3349609216,3349610495,CA
3349610496,3349614591,US
-3349643264,3349644287,CA
-3349644288,3349645311,US
+3349643264,3349643487,CA
+3349643488,3349643503,US
+3349643504,3349644287,CA
+3349644288,3349644656,US
+3349644657,3349644672,GB
+3349644673,3349645215,US
+3349645216,3349645231,ID
+3349645232,3349645311,US
3349645312,3349647359,CA
3349647360,3349649407,US
3349649408,3349653503,CA
3349653504,3349692415,US
-3349708800,3349723996,US
+3349708800,3349723260,US
+3349723261,3349723265,CA
+3349723266,3349723360,US
+3349723361,3349723367,CA
+3349723368,3349723996,US
3349723997,3349724000,LK
-3349724001,3349731327,US
+3349724001,3349724985,US
+3349724986,3349724999,PK
+3349725000,3349731327,US
3349731328,3349733375,CA
3349733376,3349739519,US
-3349739520,3349740543,CA
+3349739520,3349739551,CA
+3349739552,3349739559,US
+3349739560,3349740543,CA
3349740544,3349987327,US
3349987328,3349996543,BM
3349996544,3349997055,KY
@@ -114011,15 +116406,25 @@
3350470656,3350475775,US
3350475776,3350476799,CA
3350476800,3350478847,US
-3350495232,3350495602,US
+3350495232,3350495577,US
+3350495578,3350495585,GB
+3350495586,3350495602,US
3350495603,3350495604,BD
-3350495605,3350495873,US
+3350495605,3350495645,US
+3350495646,3350495652,RO
+3350495653,3350495873,US
3350495874,3350495874,IN
3350495875,3350495881,US
3350495882,3350495882,IN
-3350495883,3350496532,US
+3350495883,3350496305,US
+3350496306,3350496317,PT
+3350496318,3350496447,US
+3350496448,3350496455,PT
+3350496456,3350496532,US
3350496533,3350496533,IN
-3350496534,3350496721,US
+3350496534,3350496659,US
+3350496660,3350496675,BR
+3350496676,3350496721,US
3350496722,3350496723,IN
3350496724,3350593535,US
3350593536,3350609919,CA
@@ -114044,7 +116449,8 @@
3351035904,3351036927,US
3351036928,3351037951,CA
3351037952,3351043071,US
-3351043072,3351044095,CA
+3351043072,3351043079,FR
+3351043080,3351044095,CA
3351044096,3351068671,US
3351085056,3351086079,US
3351086080,3351087103,CA
@@ -114063,9 +116469,16 @@
3351303168,3351304191,CA
3351304192,3351306239,US
3351306240,3351307263,VC
-3351307264,3351308287,US
+3351307264,3351307519,US
+3351307520,3351307775,CA
+3351307776,3351308287,US
3351308288,3351310335,CA
-3351310336,3351380223,US
+3351310336,3351330815,US
+3351347200,3351357439,US
+3351357440,3351359487,CA
+3351359488,3351372799,US
+3351372800,3351373823,BM
+3351373824,3351380223,US
3351380224,3351380479,CA
3351380480,3351380735,US
3351380736,3351381759,CA
@@ -114171,7 +116584,9 @@
3351441152,3351441407,CA
3351441408,3351441919,US
3351441920,3351442175,CA
-3351442176,3351478271,US
+3351442176,3351483391,US
+3351483392,3351484415,CA
+3351484416,3351485439,US
3351511040,3351524095,US
3351524096,3351524351,GB
3351524352,3351642111,US
@@ -114179,7 +116594,9 @@
3351698432,3351904255,US
3351912448,3351927551,CA
3351927552,3351927807,US
-3351927808,3351969791,CA
+3351927808,3351959551,CA
+3351959552,3351961599,US
+3351961600,3351969791,CA
3351969792,3352035327,IL
3352035328,3352036351,CA
3352036352,3352046591,US
@@ -114209,7 +116626,37 @@
3353722624,3353729023,US
3353729024,3353729279,HK
3353729280,3353730047,US
-3353739264,3353979647,US
+3353739264,3353752581,US
+3353752582,3353752585,FR
+3353752586,3353752589,BE
+3353752590,3353752606,US
+3353752607,3353752610,AU
+3353752611,3353752630,US
+3353752631,3353752634,CA
+3353752635,3353752650,US
+3353752651,3353752654,AU
+3353752655,3353752677,US
+3353752678,3353752681,ES
+3353752682,3353752716,US
+3353752717,3353752720,IT
+3353752721,3353752740,US
+3353752741,3353752744,CA
+3353752745,3353752748,US
+3353752749,3353752752,CA
+3353752753,3353752769,US
+3353752770,3353752773,AU
+3353752774,3353752811,US
+3353752812,3353752815,CA
+3353752816,3353752828,US
+3353752829,3353752830,FR
+3353752831,3353752936,US
+3353752937,3353752940,SE
+3353752941,3353752987,US
+3353752988,3353752991,GB
+3353752992,3353753055,US
+3353753056,3353753059,BR
+3353753060,3353753067,GB
+3353753068,3353979647,US
3353979648,3353979903,CA
3353979904,3353982719,US
3353982720,3353983231,CA
@@ -114239,7 +116686,7 @@
3355260928,3355262719,CA
3355262720,3355310591,US
3355310592,3355311103,CA
-3355312128,3355319295,US
+3355311104,3355319295,US
3355319296,3355320319,CA
3355320320,3355324415,US
3355324416,3355328511,CA
@@ -114709,8 +117156,8 @@
3356341808,3356341863,SV
3356341864,3356341871,HN
3356341872,3356343295,SV
-3356343296,3356343423,HN
-3356343424,3356344319,SV
+3356343296,3356343551,HN
+3356343552,3356344319,SV
3356344320,3356360703,CO
3356360704,3356362751,CL
3356362752,3356364799,VE
@@ -114728,7 +117175,7 @@
3356380928,3356381183,DO
3356381184,3356381439,CL
3356381440,3356381695,PA
-3356381696,3356381951,UY
+3356381696,3356381951,CL
3356381952,3356382207,EC
3356382208,3356389375,CL
3356389376,3356389887,CO
@@ -114902,8 +117349,8 @@
3358064640,3358130175,UY
3358130176,3358131199,EC
3358131200,3358131391,CO
-3358131392,3358131415,GT
-3358131416,3358131983,CO
+3358131392,3358131407,GT
+3358131408,3358131983,CO
3358131984,3358131991,GT
3358131992,3358132223,CO
3358132224,3358132479,AR
@@ -114925,7 +117372,9 @@
3358150656,3358151167,EC
3358151168,3358151423,PY
3358151424,3358151679,CO
-3358151680,3358152703,GT
+3358151680,3358151935,GT
+3358151936,3358152063,PE
+3358152064,3358152703,GT
3358152704,3358152735,AR
3358152736,3358152767,VE
3358152768,3358152831,US
@@ -115021,8 +117470,7 @@
3358723328,3358723583,AN
3358723584,3358724095,PR
3358724096,3358725119,DO
-3358725120,3358725375,AN
-3358725376,3358728191,PR
+3358725120,3358728191,PR
3358728192,3358736383,CL
3358736384,3358737111,BB
3358737112,3358737119,CA
@@ -115150,7 +117598,9 @@
3359475520,3359475551,AR
3359475552,3359475615,CO
3359475616,3359475623,AR
-3359475624,3359478687,CO
+3359475624,3359477247,CO
+3359477248,3359477759,AR
+3359477760,3359478687,CO
3359478688,3359478719,AR
3359478720,3359479295,CO
3359479296,3359479303,AR
@@ -115182,6 +117632,8 @@
3359501312,3359502335,SR
3359502336,3359505407,AR
3359505408,3359505663,VE
+3359505664,3359505919,AN
+3359505920,3359506431,AR
3359506432,3359508479,US
3359508480,3359514623,VE
3359514624,3359516671,GT
@@ -115247,7 +117699,9 @@
3360231680,3360234751,CL
3360234752,3360235263,CO
3360235264,3360235271,CL
-3360235272,3360235519,CO
+3360235272,3360235487,CO
+3360235488,3360235495,CL
+3360235496,3360235519,CO
3360235520,3360236287,CL
3360236288,3360236303,CO
3360236304,3360236311,CL
@@ -115345,7 +117799,9 @@
3360763904,3360765951,GT
3360765952,3360767999,CO
3360768000,3360770047,PY
-3360770048,3360771327,EC
+3360770048,3360771071,EC
+3360771072,3360771199,AR
+3360771200,3360771327,EC
3360771328,3360771839,AR
3360771840,3360772095,EC
3360772096,3360772351,AR
@@ -115413,7 +117869,9 @@
3362328576,3362330623,CO
3362330624,3362332671,MX
3362332672,3362336767,PA
-3362336768,3362338815,CO
+3362336768,3362337279,CO
+3362337280,3362337535,US
+3362337536,3362338815,CO
3362338816,3362339839,AR
3362339840,3362341887,CO
3362341888,3362342143,GT
@@ -115438,6 +117896,10 @@
3362430976,3362447359,CO
3362447360,3362451455,SV
3362451456,3362452479,AR
+3362452480,3362452991,BO
+3362452992,3362453247,HN
+3362453248,3362453503,NI
+3362453504,3362455551,AR
3362455552,3362471935,EC
3362471936,3362476031,CL
3362476032,3362476287,HN
@@ -115545,12 +118007,13 @@
3363504128,3363512319,PE
3363512320,3363553791,AR
3363553792,3363554047,PE
-3363554048,3363557375,AR
+3363554048,3363554175,US
+3363554176,3363557375,AR
3363561472,3363565567,CO
3363569664,3363577855,PA
3363577856,3363586047,CL
3363586048,3363594239,BZ
-3363594240,3363598335,AR
+3363594240,3363602431,AR
3363602432,3363610623,AN
3363610624,3363614719,CO
3363618816,3363622911,UY
@@ -115562,8 +118025,9 @@
3363678208,3363680255,NI
3363680256,3363682303,GT
3363682304,3363684351,VE
-3363684352,3363700735,EC
-3363700736,3363708927,CU
+3363684352,3363700991,EC
+3363700992,3363701247,CU
+3363701248,3363708927,EC
3363708928,3363713023,CL
3363717120,3363733503,CL
3363733504,3363831807,AR
@@ -115575,7 +118039,9 @@
3384410112,3384672255,CL
3384672256,3384688639,HN
3384688640,3384705023,CO
-3384705024,3384737791,PA
+3384705024,3384721407,PA
+3384721408,3384725503,US
+3384725504,3384737791,PA
3384737792,3385851903,CR
3385851904,3386114047,VE
3386114048,3386245119,AR
@@ -116114,9 +118580,7 @@
3390414336,3390414847,SG
3390414848,3390418943,JP
3390418944,3390423039,MV
-3390423040,3390429439,SG
-3390429440,3390429951,HK
-3390429952,3390439423,SG
+3390423040,3390439423,SG
3390439424,3390441471,NZ
3390441472,3390443519,TH
3390443520,3390447359,NZ
@@ -116250,7 +118714,8 @@
3391879168,3391881215,ID
3391881216,3391895551,TH
3391895552,3391896575,IN
-3391896576,3391900415,TH
+3391896576,3391897599,NZ
+3391897600,3391900415,TH
3391900416,3391901695,AU
3391901696,3391905791,PK
3391905792,3391906047,TH
@@ -116409,7 +118874,6 @@
3392440832,3392441343,BD
3392441344,3392441855,ID
3392441856,3392442111,AU
-3392442112,3392442367,IN
3392442368,3392442623,HK
3392442624,3392442879,AU
3392442880,3392443391,ID
@@ -117789,19 +120253,7 @@
3399515648,3399524351,AU
3399524352,3399528447,IN
3399528448,3399532543,CN
-3399532544,3399544575,SG
-3399544576,3399544831,IN
-3399544832,3399546879,SG
-3399546880,3399547135,US
-3399547136,3399547903,SG
-3399547904,3399547911,PK
-3399547912,3399547935,SG
-3399547936,3399547951,PK
-3399547952,3399547967,SG
-3399547968,3399547999,PK
-3399548000,3399548415,SG
-3399548416,3399548671,ID
-3399548672,3399548927,SG
+3399532544,3399548927,SG
3399548928,3399557119,AU
3399557120,3399565311,SG
3399565312,3399581695,AU
@@ -118118,8 +120570,8 @@
3400438112,3400438143,HK
3400438144,3400438175,BD
3400438176,3400438399,HK
-3400438400,3400438591,BD
-3400438592,3400438783,HK
+3400438400,3400438527,BD
+3400438528,3400438783,AF
3400438784,3400438815,KZ
3400438816,3400438831,PK
3400438832,3400438839,AF
@@ -118552,7 +121004,7 @@
3407326464,3407328767,AU
3407328768,3407329023,CN
3407329024,3407329791,AU
-3407330048,3407330303,CN
+3407329792,3407330303,CN
3407330304,3407360511,AU
3407360512,3407361023,ID
3407361024,3407362047,AU
@@ -118745,9 +121197,7 @@
3409491712,3409491967,SG
3409491968,3409498111,AU
3409498112,3409498879,CN
-3409498880,3409503999,AU
-3409504000,3409504255,HK
-3409504256,3409505023,AU
+3409498880,3409505023,AU
3409505024,3409505279,US
3409505280,3409506559,AU
3409506560,3409506815,IN
@@ -118769,9 +121219,7 @@
3409567232,3409567487,CN
3409567488,3409574143,AU
3409574144,3409574399,CN
-3409574400,3409802831,AU
-3409802832,3409802847,MT
-3409802848,3409838335,AU
+3409574400,3409838335,AU
3409838336,3409838591,MY
3409838592,3409838847,CN
3409838848,3409876991,AU
@@ -119065,6 +121513,7 @@
3411644928,3411645951,ID
3411645952,3411646207,SG
3411646208,3411647487,IN
+3411647488,3411648511,AU
3411648512,3411656703,NZ
3411656704,3411673087,AU
3411673088,3411674111,CN
@@ -119423,9 +121872,7 @@
3413852160,3413868543,AU
3413868544,3413884927,IN
3413884928,3413893119,KR
-3413893120,3413899199,ID
-3413899200,3413899203,IN
-3413899204,3413901311,ID
+3413893120,3413901311,ID
3413901312,3413902847,SG
3413902848,3413903359,JP
3413903360,3413905407,HK
@@ -120348,10 +122795,7 @@
3418513408,3418517503,IN
3418517504,3418519551,MN
3418519552,3418521599,CN
-3418521600,3418524574,HK
-3418524575,3418524606,CN
-3418524607,3418524638,TH
-3418524639,3418554367,HK
+3418521600,3418554367,HK
3418554368,3418570751,VN
3418570752,3418578943,CN
3418578944,3418583039,TH
@@ -120466,7 +122910,9 @@
3419456912,3419456927,JP
3419456928,3419459007,SG
3419459008,3419459071,AF
-3419459072,3419471871,SG
+3419459072,3419459407,SG
+3419459408,3419459423,GB
+3419459424,3419471871,SG
3419471872,3419504639,TH
3419504640,3419508735,HK
3419508736,3419512831,JP
@@ -120550,7 +122996,7 @@
3420033024,3420034047,IN
3420034048,3420036095,AU
3420036096,3420037119,JP
-3420037120,3420039167,AU
+3420037120,3420038143,AU
3420039168,3420040191,KH
3420040192,3420040703,ID
3420040704,3420040959,IN
@@ -120674,8 +123120,8 @@
3420368896,3420368935,HK
3420368936,3420368943,TW
3420368944,3420368991,HK
-3420368992,3420369023,AU
-3420369024,3420369055,HK
+3420368992,3420369007,AU
+3420369008,3420369055,HK
3420369056,3420369087,AU
3420369088,3420369139,HK
3420369140,3420369223,CN
@@ -121280,9 +123726,7 @@
3425830816,3425830831,US
3425830832,3425850519,CA
3425850520,3425850527,US
-3425850528,3425855231,CA
-3425855232,3425855487,US
-3425855488,3425864711,CA
+3425850528,3425864711,CA
3425864712,3425864719,US
3425864720,3425869167,CA
3425869168,3425869183,US
@@ -121301,9 +123745,13 @@
3425916480,3425916543,DK
3425916544,3426013183,US
3426013184,3426013439,IL
-3426013440,3426387967,US
+3426013440,3426369023,US
+3426369024,3426369535,CA
+3426369536,3426387967,US
3426387968,3426388991,MX
-3426388992,3426617855,US
+3426388992,3426400255,US
+3426400256,3426400511,CA
+3426400512,3426617855,US
3426618368,3426618687,US
3426618688,3426618703,NZ
3426618704,3426618735,US
@@ -121329,9 +123777,11 @@
3427127552,3427127807,US
3427128064,3427618303,US
3427618304,3427618559,CA
-3427618560,3427647743,US
+3427618560,3427647999,US
3427648000,3427648511,CA
-3427648512,3427729407,US
+3427648512,3427651071,US
+3427651072,3427651327,CA
+3427651328,3427729407,US
3427729408,3427729663,CA
3427729664,3427730431,US
3427730432,3427730687,BE
@@ -121486,11 +123936,19 @@
3428286720,3428286975,CA
3428286976,3428296959,US
3428296960,3428297215,CL
-3428297472,3428299519,US
+3428297216,3428299519,US
3428299520,3428299775,ZA
-3428299776,3428306175,US
+3428299776,3428302079,US
+3428302080,3428302335,CA
+3428302336,3428306175,US
3428306176,3428306431,MX
-3428306432,3428437503,US
+3428306432,3428318975,US
+3428318976,3428319231,CA
+3428319232,3428399359,US
+3428399360,3428399615,CA
+3428400128,3428433919,US
+3428433920,3428434175,CA
+3428434176,3428437503,US
3428437504,3428437759,MX
3428437760,3428496639,US
3428496640,3428497151,NL
@@ -121859,7 +124317,8 @@
3431752704,3431753215,US
3431753216,3431753471,SG
3431753472,3431755007,CA
-3431755008,3431759615,NL
+3431755008,3431755775,NL
+3431755776,3431759615,CA
3431759616,3431759871,DE
3431759872,3431783431,US
3431783432,3431783435,NL
@@ -121943,7 +124402,9 @@
3434133760,3434133791,IL
3434133792,3434134015,US
3434134016,3434134079,CA
-3434134080,3434423295,US
+3434134080,3434299391,US
+3434299392,3434303487,VE
+3434303488,3434423295,US
3434423296,3434423303,CA
3434423304,3434427391,US
3434427392,3434428415,HR
@@ -121960,7 +124421,27 @@
3434584064,3434807551,US
3434807552,3434810111,CA
3434810112,3434810367,US
-3434810368,3434831359,CA
+3434810368,3434810879,CA
+3434810880,3434810895,GB
+3434810896,3434810911,US
+3434810912,3434810943,CA
+3434810944,3434810959,US
+3434810960,3434810975,AE
+3434810976,3434811007,CA
+3434811008,3434811023,US
+3434811024,3434811039,ZA
+3434811040,3434811071,US
+3434811072,3434811135,CA
+3434811136,3434811151,US
+3434811152,3434811167,CA
+3434811168,3434811199,US
+3434811200,3434811215,AU
+3434811216,3434811311,US
+3434811312,3434811327,GB
+3434811328,3434811359,US
+3434811360,3434811375,CA
+3434811376,3434811383,US
+3434811384,3434831359,CA
3434831360,3434831615,US
3434831616,3434872575,CA
3434872576,3434907647,US
@@ -122346,7 +124827,9 @@
3438552272,3438552287,US
3438552288,3438559647,CA
3438559648,3438559679,US
-3438559680,3438570031,CA
+3438559680,3438569215,CA
+3438569216,3438569343,US
+3438569344,3438570031,CA
3438570032,3438570039,MY
3438570040,3438570495,CA
3438570496,3438570527,US
@@ -122522,7 +125005,10 @@
3448569056,3448569087,MX
3448569088,3448569735,US
3448569736,3448569743,GB
-3448569744,3449001245,US
+3448569744,3448983807,US
+3448983808,3448983871,GB
+3448983872,3448985599,US
+3448987648,3449001245,US
3449001246,3449001246,MC
3449001247,3449159679,US
3449159680,3449160703,CA
@@ -122721,7 +125207,12 @@
3450272768,3450345231,US
3450345232,3450345247,FR
3450345248,3450345263,IT
-3450345264,3450345439,US
+3450345264,3450345279,US
+3450345280,3450345311,NE
+3450345312,3450345343,GE
+3450345344,3450345391,US
+3450345392,3450345399,BG
+3450345400,3450345439,US
3450345440,3450345471,GE
3450345472,3450731519,US
3450731520,3450732543,CA
@@ -122746,7 +125237,11 @@
3451236608,3451371519,US
3451371520,3451371775,GB
3451371776,3451482111,US
-3451482112,3451486207,CA
+3451482112,3451482439,CA
+3451482440,3451482447,AR
+3451482448,3451483423,CA
+3451483424,3451483431,US
+3451483432,3451486207,CA
3451486208,3451506687,US
3451506688,3451507711,BR
3451507712,3451715583,US
@@ -122985,8 +125480,8 @@
3453375144,3453375167,US
3453375168,3453375191,SA
3453375192,3453375215,US
-3453375216,3453375239,GB
-3453375240,3453375255,US
+3453375216,3453375231,GB
+3453375232,3453375255,US
3453375256,3453375263,IN
3453375264,3453375279,GB
3453375280,3453375319,TK
@@ -123109,8 +125604,12 @@
3453554880,3453555711,US
3453555712,3453555767,GB
3453555768,3453583615,US
-3453583616,3453583679,SG
-3453583680,3453599999,US
+3453583616,3453583695,SG
+3453583696,3453595527,US
+3453595528,3453595551,CA
+3453595552,3453595583,US
+3453595584,3453595623,CA
+3453595624,3453599999,US
3453600000,3453600767,GB
3453600768,3453601863,US
3453601864,3453601871,GB
@@ -123133,7 +125632,9 @@
3453615104,3453615359,AG
3453615360,3453615615,KN
3453615616,3453616127,AG
-3453616128,3454003013,US
+3453616128,3453681943,US
+3453681944,3453681951,IN
+3453681952,3454003013,US
3454003014,3454003014,ES
3454003015,3454004997,US
3454004998,3454004998,GB
@@ -123173,9 +125674,24 @@
3454703256,3454703263,CA
3454703264,3454703647,US
3454703648,3454703663,CA
-3454703664,3454705151,US
+3454703664,3454703951,US
+3454703952,3454703959,AF
+3454703960,3454704007,US
+3454704008,3454704015,ID
+3454704016,3454704047,US
+3454704048,3454704055,CA
+3454704056,3454704063,US
+3454704064,3454704079,CA
+3454704080,3454704087,AE
+3454704088,3454704103,US
+3454704104,3454704111,GB
+3454704112,3454705151,US
3454705152,3454705215,GB
-3454705216,3454708927,US
+3454705216,3454705439,US
+3454705440,3454705447,GB
+3454705448,3454705511,US
+3454705512,3454705519,CA
+3454705520,3454708927,US
3454708928,3454708991,IN
3454708992,3454710551,US
3454710552,3454710559,SO
@@ -123342,7 +125858,9 @@
3455647488,3455647743,IT
3455647744,3455713279,US
3455713280,3455778815,CA
-3455778816,3455871999,US
+3455778816,3455797375,US
+3455797376,3455797407,FR
+3455797408,3455871999,US
3455872000,3455872255,ZM
3455872256,3456303103,US
3456303104,3456311295,JP
@@ -124292,7 +126810,8 @@
3464341504,3464341759,US
3464341760,3464341775,JP
3464341776,3464341783,AU
-3464341784,3464341807,US
+3464341784,3464341799,US
+3464341800,3464341807,CA
3464341808,3464341815,JP
3464341816,3464341823,US
3464341824,3464341831,PT
@@ -124302,7 +126821,9 @@
3464341896,3464341903,GB
3464341904,3464341927,US
3464341928,3464341935,CV
-3464341936,3464342543,US
+3464341936,3464341983,US
+3464341984,3464341991,PR
+3464341992,3464342543,US
3464342544,3464342559,SE
3464342560,3464342567,US
3464342568,3464342575,PT
@@ -124322,43 +126843,16 @@
3464384512,3464388607,CA
3464388608,3464394751,US
3464394752,3464396799,VC
-3464396800,3464548367,US
-3464548368,3464548375,AG
-3464548376,3464548391,US
-3464548392,3464548399,AG
-3464548400,3464548415,US
-3464548416,3464548431,AG
-3464548432,3464548479,US
-3464548480,3464548599,AG
-3464548600,3464548607,US
+3464396800,3464548351,US
+3464548352,3464548607,AG
3464548608,3464548863,LC
3464548864,3464549119,KN
3464549120,3464549375,VG
-3464549376,3464549391,US
-3464549392,3464549399,AG
-3464549400,3464549415,US
-3464549416,3464549439,AG
+3464549376,3464549439,AG
3464549440,3464549503,MS
-3464549504,3464549519,AG
-3464549520,3464549551,US
-3464549552,3464549567,AG
-3464549568,3464549639,US
-3464549640,3464549679,AG
-3464549680,3464549687,US
-3464549688,3464549727,AG
+3464549504,3464549727,AG
3464549728,3464549759,KN
-3464549760,3464549855,AG
-3464549856,3464549863,US
-3464549864,3464549871,AG
-3464549872,3464549919,US
-3464549920,3464549927,AG
-3464549928,3464549935,US
-3464549936,3464549943,AG
-3464549944,3464549951,US
-3464549952,3464550015,AG
-3464550016,3464550047,US
-3464550048,3464550127,AG
-3464550128,3464550143,US
+3464549760,3464550143,AG
3464550144,3464550399,LC
3464550400,3464626175,US
3464626432,3464626687,CA
@@ -124409,7 +126903,9 @@
3465468880,3465468911,SG
3465468912,3465468935,US
3465468936,3465468943,SG
-3465468944,3465510911,US
+3465468944,3465469183,US
+3465469184,3465469215,GB
+3465469216,3465510911,US
3465510912,3465543679,JP
3465543680,3465953503,US
3465953504,3465953535,CA
@@ -124447,7 +126943,9 @@
3466286104,3466286111,DE
3466286112,3466290687,US
3466290688,3466290943,CH
-3466290944,3466313727,US
+3466290944,3466294271,US
+3466294272,3466294319,CA
+3466294320,3466313727,US
3466313728,3466317823,CA
3466317824,3466489855,US
3466489856,3466490111,CA
@@ -125397,9 +127895,19 @@
3470360688,3470360695,AF
3470360696,3470360799,US
3470360800,3470360807,CA
-3470360808,3470361039,US
+3470360808,3470360895,US
+3470360896,3470360911,CA
+3470360912,3470360927,US
+3470360928,3470360935,CA
+3470360936,3470361039,US
3470361040,3470361055,CA
-3470361056,3470361487,US
+3470361056,3470361231,US
+3470361232,3470361247,IN
+3470361248,3470361295,US
+3470361296,3470361311,IN
+3470361312,3470361471,US
+3470361472,3470361479,JP
+3470361480,3470361487,US
3470361488,3470361495,SG
3470361496,3470361663,US
3470361664,3470361671,CA
@@ -125424,9 +127932,7 @@
3470362320,3470362335,AF
3470362336,3470362455,US
3470362456,3470362471,CA
-3470362472,3470362487,US
-3470362488,3470362495,ES
-3470362496,3470362543,US
+3470362472,3470362543,US
3470362544,3470362559,SE
3470362560,3470362623,CA
3470362624,3470362731,US
@@ -125444,7 +127950,11 @@
3470363544,3470363555,AF
3470363556,3470363559,US
3470363560,3470363567,CA
-3470363568,3470363903,US
+3470363568,3470363615,US
+3470363616,3470363631,ES
+3470363632,3470363671,US
+3470363672,3470363679,SE
+3470363680,3470363903,US
3470363904,3470363919,CA
3470363920,3470363967,US
3470363968,3470363983,CA
@@ -125488,7 +127998,9 @@
3470645744,3470645747,ES
3470645748,3470645751,US
3470645752,3470645759,BR
-3470645760,3470646015,US
+3470645760,3470645791,US
+3470645792,3470645799,CN
+3470645800,3470646015,US
3470646016,3470646019,BR
3470646020,3470646035,US
3470646036,3470646039,VI
@@ -125899,7 +128411,9 @@
3476722240,3476722255,SA
3476722256,3476722287,US
3476722288,3476722319,IT
-3476722320,3476722527,US
+3476722320,3476722495,US
+3476722496,3476722511,AU
+3476722512,3476722527,US
3476722528,3476722543,AU
3476722544,3476722591,US
3476722592,3476722607,GB
@@ -125969,7 +128483,9 @@
3478261904,3478261935,SG
3478261936,3478262271,US
3478262272,3478262279,SG
-3478262280,3478294527,US
+3478262280,3478262655,US
+3478262656,3478262671,SG
+3478262672,3478294527,US
3478294528,3478294543,GB
3478294544,3478323391,US
3478323392,3478323399,CA
@@ -126058,7 +128574,9 @@
3479294224,3479294231,TH
3479294232,3479294419,US
3479294420,3479294423,CA
-3479294424,3479294487,US
+3479294424,3479294425,US
+3479294426,3479294427,CA
+3479294428,3479294487,US
3479294488,3479294495,MX
3479294496,3479294527,US
3479294528,3479294543,BD
@@ -126068,9 +128586,7 @@
3479294664,3479294671,AU
3479294672,3479294775,US
3479294776,3479294783,CA
-3479294784,3479294911,US
-3479294912,3479294919,CA
-3479294920,3479295015,US
+3479294784,3479295015,US
3479295016,3479295023,MY
3479295024,3479295071,US
3479295072,3479295079,CR
@@ -126351,9 +128867,7 @@
3480907264,3480907775,FR
3480907776,3480968191,US
3480968192,3480968447,AU
-3480968448,3481169151,US
-3481169152,3481169407,NZ
-3481169408,3481182503,US
+3480968448,3481182503,US
3481182504,3481182511,CA
3481182512,3481665535,US
3481665536,3481731071,CA
@@ -126572,7 +129086,9 @@
3484777696,3484778495,CA
3484778496,3484884991,US
3484884992,3484893183,CA
-3484893184,3485220863,US
+3484893184,3484937103,US
+3484937104,3484937111,SE
+3484937112,3485220863,US
3485220864,3485229055,CA
3485229056,3485290463,US
3485290464,3485290479,GB
@@ -126860,7 +129376,9 @@
3486700440,3486700447,IT
3486700448,3486701311,US
3486701312,3486701567,CA
-3486701568,3486711551,US
+3486701568,3486707559,US
+3486707560,3486707567,HN
+3486707568,3486711551,US
3486711552,3486711807,CA
3486711808,3487039487,US
3487039488,3487105023,CA
@@ -126884,9 +129402,13 @@
3487507376,3487507391,CA
3487507392,3487559711,US
3487559712,3487559743,AU
-3487559744,3487559855,US
-3487559856,3487559871,AU
-3487559872,3487766527,US
+3487559744,3487559839,US
+3487559840,3487559871,AU
+3487559872,3487560167,US
+3487560168,3487560175,AU
+3487560176,3487561471,US
+3487561472,3487561727,AU
+3487561728,3487766527,US
3487766528,3487768575,CA
3487768576,3487842303,US
3487842304,3487858687,CA
@@ -127126,11 +129648,7 @@
3493081600,3493082623,PY
3493082624,3493089023,US
3493089024,3493089279,A2
-3493089280,3493137151,US
-3493137152,3493137215,DE
-3493137216,3493137247,US
-3493137248,3493137407,DE
-3493137408,3493138207,US
+3493089280,3493138207,US
3493138208,3493138239,DE
3493138240,3493140223,US
3493140224,3493140479,DE
@@ -127157,7 +129675,9 @@
3493901760,3493901767,AE
3493901768,3493901791,US
3493901792,3493901823,AE
-3493901824,3493901951,US
+3493901824,3493901847,US
+3493901848,3493901851,CA
+3493901852,3493901951,US
3493901952,3493901983,CA
3493901984,3493902215,US
3493902216,3493902223,CA
@@ -127247,9 +129767,7 @@
3494122496,3494135807,US
3494135808,3494136831,CA
3494136832,3494139903,US
-3494139904,3494141735,CA
-3494141736,3494141743,US
-3494141744,3494141951,CA
+3494139904,3494141951,CA
3494141952,3494143999,US
3494144000,3494145023,CA
3494145024,3494159039,US
@@ -127442,8 +129960,7 @@
3494438144,3494438399,DM
3494438400,3494438655,KN
3494438656,3494438911,DM
-3494438912,3494439935,CA
-3494439936,3494449287,US
+3494438912,3494449287,US
3494449288,3494449311,CA
3494449312,3494449439,US
3494449440,3494449663,CA
@@ -127556,8 +130073,8 @@
3494701056,3494705319,US
3494705320,3494705327,MX
3494705328,3494712319,US
-3494712320,3494713343,CA
-3494713344,3494727679,US
+3494712320,3494712575,CA
+3494712576,3494727679,US
3494727680,3494729727,CA
3494729728,3494730751,US
3494730752,3494731775,CA
@@ -127573,9 +130090,7 @@
3494745304,3494745311,AU
3494745312,3494745879,US
3494745880,3494745887,GB
-3494745888,3494745919,US
-3494745920,3494745927,CN
-3494745928,3494745951,US
+3494745888,3494745951,US
3494745952,3494745959,GB
3494745960,3494746019,US
3494746020,3494746023,AU
@@ -127621,11 +130136,19 @@
3494852608,3494854655,CA
3494854656,3494861087,US
3494861088,3494861095,CA
-3494861096,3494861615,US
+3494861096,3494861575,US
+3494861576,3494861583,CH
+3494861584,3494861615,US
3494861616,3494861623,AU
3494861624,3494861839,US
3494861840,3494861855,AU
-3494861856,3494862639,US
+3494861856,3494861935,US
+3494861936,3494861943,AU
+3494861944,3494861999,US
+3494862000,3494862007,CA
+3494862008,3494862255,US
+3494862256,3494862263,CZ
+3494862264,3494862639,US
3494862640,3494862647,JP
3494862648,3494862847,US
3494862848,3494863871,DM
@@ -127709,21 +130232,24 @@
3495153664,3495155711,CA
3495155712,3495157039,US
3495157040,3495157047,SE
-3495157048,3495159807,US
-3495159808,3495159815,ES
-3495159816,3495159839,US
+3495157048,3495159839,US
3495159840,3495159847,BR
3495159848,3495159871,US
3495159872,3495159879,AE
-3495159880,3495159895,US
+3495159880,3495159887,BD
+3495159888,3495159895,GB
3495159896,3495159903,IN
-3495159904,3495160111,US
+3495159904,3495159927,US
+3495159928,3495159935,IN
+3495159936,3495160071,US
+3495160072,3495160079,HK
+3495160080,3495160111,US
3495160112,3495160119,NZ
3495160120,3495160303,US
3495160304,3495160319,TR
-3495160320,3495160367,US
-3495160368,3495160383,ZA
-3495160384,3495160447,US
+3495160320,3495160359,US
+3495160360,3495160367,GB
+3495160368,3495160447,US
3495160448,3495160455,BR
3495160456,3495160463,US
3495160464,3495160479,TR
@@ -127758,9 +130284,7 @@
3495235904,3495235911,CA
3495235912,3495235975,US
3495235976,3495235983,VN
-3495235984,3495235999,US
-3495236000,3495236007,HK
-3495236008,3495236015,US
+3495235984,3495236015,US
3495236016,3495236031,GB
3495236032,3495236247,US
3495236248,3495236255,AZ
@@ -127993,7 +130517,9 @@
3495749736,3495749745,US
3495749746,3495749785,CA
3495749786,3495749829,GB
-3495749830,3495749908,CA
+3495749830,3495749846,CA
+3495749847,3495749856,US
+3495749857,3495749908,CA
3495749909,3495749933,GB
3495749934,3495749959,CA
3495749960,3495749990,GB
@@ -128493,7 +131019,11 @@
3500809992,3500809999,CA
3500810000,3500810247,US
3500810248,3500810255,CA
-3500810256,3500812175,US
+3500810256,3500811567,US
+3500811568,3500811583,AU
+3500811584,3500811591,US
+3500811592,3500811631,AU
+3500811632,3500812175,US
3500812176,3500812183,GB
3500812184,3500921279,US
3500921280,3500921311,AU
@@ -128590,10 +131120,7 @@
3503250432,3503250943,PK
3503250944,3503323135,US
3503323136,3503323647,KE
-3503323648,3503323903,A2
-3503323904,3503372031,US
-3503372032,3503372287,A2
-3503372288,3503386111,US
+3503323648,3503386111,US
3503386112,3503386367,CH
3503386368,3503413871,US
3503413872,3503413887,PR
@@ -128674,9 +131201,7 @@
3506135264,3506135295,GB
3506135296,3506161975,US
3506161976,3506161983,AF
-3506161984,3506177967,US
-3506177968,3506177983,DE
-3506177984,3506192639,US
+3506161984,3506192639,US
3506192640,3506192895,A2
3506192896,3506194535,US
3506194536,3506194543,AU
@@ -129476,7 +132001,9 @@
3509777450,3509777545,ID
3509777546,3509777584,US
3509777585,3509777648,ID
-3509777649,3509778399,US
+3509777649,3509778239,US
+3509778240,3509778271,IN
+3509778272,3509778399,US
3509778400,3509778431,NL
3509778432,3509778703,US
3509778704,3509778711,CA
@@ -129556,15 +132083,17 @@
3510242560,3510245375,CA
3510245376,3510245631,BD
3510245632,3510246735,CA
-3510246736,3510246767,US
-3510246768,3510249471,CA
+3510246736,3510246775,US
+3510246776,3510249471,CA
3510249472,3510249983,QA
3510249984,3510251519,CA
3510251520,3510252799,DO
3510252800,3510253311,CA
3510253312,3510253567,NC
3510253568,3510253631,US
-3510253632,3510255439,CA
+3510253632,3510253759,CA
+3510253760,3510253775,US
+3510253776,3510255439,CA
3510255440,3510255447,US
3510255448,3510261503,CA
3510261504,3510261759,ZM
@@ -130226,7 +132755,9 @@
3512377232,3512377239,US
3512377240,3512378435,CA
3512378436,3512378436,US
-3512378437,3512385535,CA
+3512378437,3512378983,CA
+3512378984,3512378991,US
+3512378992,3512385535,CA
3512385536,3512397823,US
3512397824,3512399375,CA
3512399376,3512399383,US
@@ -130750,10 +133281,11 @@
3515688192,3515695103,CA
3515695104,3515711487,US
3515711488,3515731967,CA
-3515731968,3515736063,US
-3515744256,3515793351,US
+3515731968,3515793351,US
3515793352,3515793359,MO
-3515793360,3515867151,US
+3515793360,3515860351,US
+3515860352,3515860431,IN
+3515860432,3515867151,US
3515867152,3515867167,AU
3515867168,3515867391,US
3515867392,3515867519,AU
@@ -130784,7 +133316,9 @@
3516139264,3516153855,US
3516153856,3516162047,CA
3516162048,3516170239,US
-3516170240,3516203007,CA
+3516170240,3516193943,CA
+3516193944,3516193951,US
+3516193952,3516203007,CA
3516203008,3516334079,US
3516334080,3516342271,CA
3516342272,3516351055,US
@@ -130899,9 +133433,7 @@
3517396144,3517396175,US
3517396176,3517396911,CA
3517396912,3517396927,US
-3517396928,3517396943,CA
-3517396944,3517396959,US
-3517396960,3517397503,CA
+3517396928,3517397503,CA
3517397504,3517397759,US
3517397760,3517398015,CA
3517398016,3517398527,US
@@ -131074,8 +133606,8 @@
3517437000,3517437007,CA
3517437008,3517437015,US
3517437016,3517437039,CA
-3517437040,3517437063,US
-3517437064,3517437071,CA
+3517437040,3517437055,US
+3517437056,3517437071,CA
3517437072,3517437079,US
3517437080,3517437087,CA
3517437088,3517437095,NO
@@ -131095,9 +133627,7 @@
3517438880,3517438911,KW
3517438912,3517439487,CA
3517439488,3517439615,US
-3517439616,3517440255,CA
-3517440256,3517440511,US
-3517440512,3517442239,CA
+3517439616,3517442239,CA
3517442240,3517442303,US
3517442304,3517442319,CA
3517442320,3517442335,US
@@ -131160,7 +133690,9 @@
3517601280,3517602047,SE
3517602048,3517602303,DE
3517602304,3517602559,US
-3517602560,3517602623,SE
+3517602560,3517602575,SE
+3517602576,3517602591,US
+3517602592,3517602623,SE
3517602624,3517602815,US
3517602816,3517603071,SE
3517603072,3517603615,US
@@ -131276,11 +133808,7 @@
3518897120,3518897127,IT
3518897128,3518903191,US
3518903192,3518903199,JP
-3518903200,3518903927,US
-3518903928,3518903935,RU
-3518903936,3518904015,US
-3518904016,3518904031,EG
-3518904032,3518905599,US
+3518903200,3518905599,US
3518905600,3518905855,GB
3518905856,3518911743,US
3518911744,3518911999,GB
@@ -131384,7 +133912,10 @@
3519420768,3519420775,HK
3519420776,3519422495,US
3519422496,3519422527,CA
-3519422528,3519475711,US
+3519422528,3519466895,US
+3519466896,3519466911,SZ
+3519466912,3519467519,US
+3519469568,3519475711,US
3519475712,3519476223,BH
3519476224,3519477759,A2
3519477760,3519578367,US
@@ -131429,8 +133960,7 @@
3519723520,3519724031,CA
3519724032,3519741951,US
3519741952,3519758335,ZA
-3519758336,3519791103,US
-3519799296,3519799871,US
+3519758336,3519799871,US
3519799872,3519799903,IN
3519799904,3519805119,US
3519805120,3519805183,GB
@@ -131722,7 +134252,9 @@
3520086272,3520086527,CA
3520086528,3520086959,US
3520086960,3520086975,CA
-3520086976,3520088447,US
+3520086976,3520087327,US
+3520087328,3520087359,DE
+3520087360,3520088447,US
3520088448,3520088463,ES
3520088464,3520095455,US
3520095456,3520095471,NL
@@ -131790,11 +134322,19 @@
3520999424,3521003519,CA
3521003520,3521003583,US
3521003584,3521003647,IL
-3521003648,3521005311,US
+3521003648,3521004031,US
+3521004032,3521004039,MY
+3521004040,3521004063,US
+3521004064,3521004071,RO
+3521004072,3521004159,US
+3521004160,3521004175,FR
+3521004176,3521005311,US
3521005312,3521005319,MY
3521005320,3521005327,GB
3521005328,3521005335,DE
-3521005336,3521011719,US
+3521005336,3521009679,US
+3521009680,3521009687,MY
+3521009688,3521011719,US
3521011720,3521011727,BR
3521011728,3521011735,AU
3521011736,3521011743,US
@@ -131943,8 +134483,8 @@
3521934769,3521934776,MA
3521934777,3521935310,US
3521935311,3521935318,EG
-3521935319,3521935717,US
-3521935718,3521935725,IN
+3521935319,3521935709,US
+3521935710,3521935725,IN
3521935726,3521935993,US
3521935994,3521936025,EG
3521936026,3521936049,US
@@ -131959,7 +134499,8 @@
3521936670,3521936677,PK
3521936678,3521936739,US
3521936740,3521936747,ID
-3521936748,3521936766,US
+3521936748,3521936758,US
+3521936759,3521936766,IN
3521936767,3521936774,PE
3521936775,3521936827,US
3521936828,3521936860,EG
@@ -132299,9 +134840,7 @@
3524781792,3524781823,SG
3524781824,3524788223,PH
3524788224,3524853759,SG
-3524853760,3525300739,CN
-3525300740,3525300743,US
-3525300744,3526361087,CN
+3524853760,3526361087,CN
3526361088,3526393855,NZ
3526393856,3526395903,JP
3526395904,3526397951,KH
@@ -132445,9 +134984,7 @@
3546808320,3547856895,KR
3547856896,3548905471,JP
3548905472,3551002623,CN
-3551002624,3554544607,KR
-3554544608,3554544639,DE
-3554544640,3556769791,KR
+3551002624,3556769791,KR
3556769792,3556774399,DE
3556774400,3556786175,EU
3556786176,3556794367,RU
@@ -132471,6 +135008,9 @@
3556868096,3556876287,GB
3556876288,3556884479,NL
3556884480,3556886527,IR
+3556886528,3556888575,GB
+3556888576,3556890623,US
+3556890624,3556892671,GB
3556892672,3556900863,RU
3556900864,3556909055,GB
3556909056,3556925439,DE
@@ -132554,25 +135094,28 @@
3557138432,3557146623,RU
3557146624,3557154815,SK
3557154816,3557171199,RU
-3557171200,3557172479,IT
+3557171200,3557172479,A2
3557172480,3557172991,IR
3557172992,3557173503,IQ
3557173504,3557173631,IR
3557173632,3557173695,IQ
3557173696,3557173703,AE
-3557173704,3557173759,IT
+3557173704,3557173759,A2
3557173760,3557174015,IR
-3557174016,3557174527,IT
+3557174016,3557174527,A2
3557174528,3557174783,IR
3557174784,3557175039,AE
3557175040,3557176063,IR
-3557176064,3557176575,IT
+3557176064,3557176575,A2
3557176576,3557176619,NE
-3557176620,3557176831,IT
+3557176620,3557176831,A2
3557176832,3557177023,IQ
-3557177024,3557177199,IT
+3557177024,3557177199,A2
3557177200,3557177215,IR
-3557177216,3557179391,IT
+3557177216,3557177343,A2
+3557177344,3557177599,IT
+3557177600,3557179135,A2
+3557179136,3557179391,IT
3557179392,3557213351,DE
3557213352,3557213359,US
3557213360,3557228543,DE
@@ -132603,16 +135146,16 @@
3557336192,3557336255,EU
3557336256,3557336319,BE
3557336320,3557336575,EU
-3557336576,3557336671,BE
-3557336672,3557336703,EU
-3557336704,3557336831,BE
+3557336576,3557336831,BE
3557336832,3557338111,EU
3557338112,3557338367,BE
3557338368,3557338495,EU
-3557338496,3557339175,BE
+3557338496,3557338615,BE
+3557338616,3557338623,EU
+3557338624,3557339175,BE
3557339176,3557339183,EU
-3557339184,3557339199,BE
-3557339200,3557339215,EU
+3557339184,3557339191,BE
+3557339192,3557339215,EU
3557339216,3557339223,BE
3557339224,3557339239,EU
3557339240,3557339247,BE
@@ -132678,10 +135221,8 @@
3557361376,3557361391,JE
3557361392,3557361415,GB
3557361416,3557361423,JE
-3557361424,3557361455,GB
-3557361456,3557361463,JE
-3557361464,3557361599,GB
-3557361600,3557361615,JE
+3557361424,3557361607,GB
+3557361608,3557361615,JE
3557361616,3557361663,GB
3557361664,3557361983,JE
3557361984,3557362047,GB
@@ -132696,11 +135237,9 @@
3557363672,3557363679,JE
3557363680,3557364103,GB
3557364104,3557364107,JE
-3557364108,3557364147,GB
-3557364148,3557364151,JE
-3557364152,3557364167,GB
-3557364168,3557364223,JE
-3557364224,3557364479,GB
+3557364108,3557364195,GB
+3557364196,3557364199,JE
+3557364200,3557364479,GB
3557364480,3557364495,JE
3557364496,3557364527,GB
3557364528,3557364559,JE
@@ -132744,17 +135283,9 @@
3557365912,3557365919,JE
3557365920,3557365935,GB
3557365936,3557366015,JE
-3557366016,3557366023,GB
-3557366024,3557366031,JE
-3557366032,3557366055,GB
+3557366016,3557366055,GB
3557366056,3557366063,JE
-3557366064,3557366095,GB
-3557366096,3557366103,JE
-3557366104,3557366111,GB
-3557366112,3557366119,JE
-3557366120,3557366167,GB
-3557366168,3557366175,JE
-3557366176,3557366263,GB
+3557366064,3557366263,GB
3557366264,3557366271,JE
3557366272,3557366279,GB
3557366280,3557366287,JE
@@ -132841,7 +135372,18 @@
3557860832,3557860847,FI
3557860848,3557860863,SE
3557860864,3557861119,NO
-3557861120,3557863887,SE
+3557861120,3557862015,SE
+3557862016,3557862031,BE
+3557862032,3557862399,SE
+3557862400,3557862911,FI
+3557862912,3557863351,SE
+3557863352,3557863359,FI
+3557863360,3557863391,SE
+3557863392,3557863399,FI
+3557863400,3557863487,SE
+3557863488,3557863503,NO
+3557863504,3557863519,DK
+3557863520,3557863887,SE
3557863888,3557863903,NO
3557863904,3557863919,FI
3557863920,3557864287,SE
@@ -133041,11 +135583,13 @@
3558288640,3558288671,BE
3558288672,3558288687,DE
3558288688,3558288895,BE
-3558288896,3558289111,FR
-3558289112,3558289119,GB
+3558288896,3558289103,FR
+3558289104,3558289119,GB
3558289120,3558289151,FR
3558289152,3558289407,GB
-3558289408,3558289663,NL
+3558289408,3558289503,NL
+3558289504,3558289535,GB
+3558289536,3558289663,NL
3558289664,3558289747,IT
3558289748,3558289751,GB
3558289752,3558289775,IT
@@ -133058,8 +135602,8 @@
3558290592,3558290599,BE
3558290600,3558290615,GB
3558290616,3558290663,BE
-3558290664,3558290671,GB
-3558290672,3558290687,BE
+3558290664,3558290679,GB
+3558290680,3558290687,BE
3558290688,3558290871,ES
3558290872,3558290879,GB
3558290880,3558290911,ES
@@ -133090,7 +135634,8 @@
3558292608,3558292735,NL
3558292736,3558292863,GB
3558292864,3558292871,CH
-3558292872,3558293119,NL
+3558292872,3558292879,GB
+3558292880,3558293119,NL
3558293120,3558293143,CH
3558293144,3558293151,GB
3558293152,3558293247,NL
@@ -133435,7 +135980,9 @@
3559088368,3559088371,GB
3559088372,3559088375,BE
3559088376,3559088379,GB
-3559088380,3559089023,BE
+3559088380,3559088631,BE
+3559088632,3559088639,DE
+3559088640,3559089023,BE
3559089024,3559089027,GB
3559089028,3559089079,BE
3559089080,3559089087,GB
@@ -133447,8 +135994,8 @@
3559089440,3559089443,GB
3559089444,3559089447,BE
3559089448,3559089451,GB
-3559089452,3559089459,BE
-3559089460,3559089467,GB
+3559089452,3559089463,BE
+3559089464,3559089467,GB
3559089468,3559089547,BE
3559089548,3559089551,GB
3559089552,3559089607,BE
@@ -133513,11 +136060,17 @@
3559091632,3559091639,LU
3559091640,3559091815,BE
3559091816,3559091823,GB
-3559091824,3559092159,BE
+3559091824,3559091887,BE
+3559091888,3559091903,GB
+3559091904,3559092159,BE
3559092160,3559092160,GB
3559092161,3559092222,BE
3559092223,3559092223,GB
-3559092224,3559092735,BE
+3559092224,3559092239,BE
+3559092240,3559092247,GB
+3559092248,3559092359,BE
+3559092360,3559092367,GB
+3559092368,3559092735,BE
3559092736,3559092739,GB
3559092740,3559092799,BE
3559092800,3559092803,GB
@@ -133534,7 +136087,9 @@
3559093000,3559093007,BE
3559093008,3559093015,GB
3559093016,3559093023,FR
-3559093024,3559093047,BE
+3559093024,3559093031,BE
+3559093032,3559093039,GB
+3559093040,3559093047,BE
3559093048,3559093055,GB
3559093056,3559093063,BE
3559093064,3559093071,FR
@@ -133846,19 +136401,13 @@
3559900424,3559900432,EE
3559900433,3559900439,UA
3559900440,3559900447,EE
-3559900448,3559900471,UA
-3559900472,3559900479,EE
-3559900480,3559900483,UA
+3559900448,3559900483,UA
3559900484,3559900487,EE
3559900488,3559900492,UA
3559900493,3559900493,EE
-3559900494,3559900494,UA
-3559900495,3559900495,EE
-3559900496,3559900503,UA
+3559900494,3559900503,UA
3559900504,3559900511,EE
-3559900512,3559900519,UA
-3559900520,3559900523,EE
-3559900524,3559900611,UA
+3559900512,3559900611,UA
3559900612,3559900624,EE
3559900625,3559900927,UA
3559900928,3559900951,EE
@@ -133884,17 +136433,13 @@
3559902240,3559902431,UA
3559902432,3559902463,EE
3559902464,3559902975,UA
-3559902976,3559903487,EE
-3559903488,3559903551,UA
-3559903552,3559903631,EE
+3559902976,3559903631,EE
3559903632,3559903679,UA
3559903680,3559904003,EE
3559904004,3559904015,UA
3559904016,3559904043,EE
3559904044,3559904127,UA
-3559904128,3559904383,EE
-3559904384,3559904511,UA
-3559904512,3559904767,EE
+3559904128,3559904767,EE
3559904768,3559904799,UA
3559904800,3559904815,EE
3559904816,3559905019,UA
@@ -133926,9 +136471,15 @@
3559905616,3559905631,UA
3559905632,3559905903,EE
3559905904,3559905911,UA
-3559905912,3559906257,EE
+3559905912,3559906239,EE
+3559906240,3559906247,UA
+3559906248,3559906257,EE
3559906258,3559906263,UA
-3559906264,3559906975,EE
+3559906264,3559906267,EE
+3559906268,3559906271,UA
+3559906272,3559906287,EE
+3559906288,3559906303,UA
+3559906304,3559906975,EE
3559906976,3559907071,UA
3559907072,3559907327,EE
3559907328,3559915519,FR
@@ -133977,7 +136528,9 @@
3560235008,3560243199,DE
3560243200,3560247295,BE
3560247296,3560251391,NL
-3560251392,3560253439,RU
+3560251392,3560252351,RU
+3560252352,3560252367,CZ
+3560252368,3560253439,RU
3560253440,3560253695,CZ
3560253696,3560259583,RU
3560259584,3560267775,GB
@@ -134749,9 +137302,7 @@
3560942952,3560942955,ES
3560942956,3560942959,DE
3560942960,3560942963,GB
-3560942964,3560942975,DE
-3560942976,3560942979,IT
-3560942980,3560942983,DE
+3560942964,3560942983,DE
3560942984,3560942987,BE
3560942988,3560942999,IT
3560943000,3560943003,PL
@@ -135373,7 +137924,7 @@
3560943861,3560943865,DE
3560943866,3560943866,BE
3560943867,3560943867,ES
-3560943868,3560943868,FR
+3560943868,3560943868,DE
3560943869,3560943869,LU
3560943870,3560943871,DE
3560943872,3560943875,BR
@@ -136420,7 +138971,9 @@
3561924720,3561924895,GB
3561924896,3561924903,FR
3561924904,3561924911,GB
-3561924912,3561925039,NL
+3561924912,3561924927,NL
+3561924928,3561924943,GB
+3561924944,3561925039,NL
3561925040,3561925087,GB
3561925088,3561925119,NL
3561925120,3561926943,GB
@@ -136462,7 +139015,9 @@
3561939833,3561939835,GB
3561939836,3561940991,IE
3561940992,3561942015,GB
-3561942016,3561947135,IE
+3561942016,3561942847,IE
+3561942848,3561942911,GB
+3561942912,3561947135,IE
3561947136,3561963519,DE
3561963520,3561971711,BE
3561971712,3561975807,CZ
@@ -136558,6 +139113,10 @@
3562258432,3562263975,NL
3562263976,3562263983,BE
3562263984,3562283007,NL
+3562283008,3562285055,IT
+3562285056,3562287103,IE
+3562287104,3562289151,IT
+3562289152,3562291199,FR
3562291200,3562307583,GB
3562307584,3562315775,NL
3562315776,3562321231,GB
@@ -136579,7 +139138,8 @@
3562373120,3562381311,FR
3562381312,3562389503,SI
3562389504,3562395647,GH
-3562395648,3562396159,TZ
+3562395648,3562395903,BR
+3562395904,3562396159,TZ
3562396160,3562397695,SZ
3562397696,3562405887,GB
3562405888,3562414079,FI
@@ -136600,9 +139160,7 @@
3562545152,3562553343,GB
3562553344,3562561535,DK
3562561536,3562569727,UG
-3562569728,3562572143,DE
-3562572144,3562572159,LU
-3562572160,3562572223,DE
+3562569728,3562572223,DE
3562572224,3562572239,US
3562572240,3562572543,DE
3562572544,3562572799,LU
@@ -136669,9 +139227,7 @@
3563005952,3563006463,TR
3563006464,3563006591,DE
3563006592,3563006719,CA
-3563006720,3563006847,DE
-3563006848,3563006911,US
-3563006912,3563007487,DE
+3563006720,3563007487,DE
3563007488,3563007999,TR
3563008000,3563008255,DE
3563008256,3563008511,PL
@@ -136700,7 +139256,7 @@
3563068416,3563069183,NG
3563069184,3563069439,GH
3563069440,3563077631,HU
-3563077632,3563085823,SE
+3563077632,3563085823,KZ
3563085824,3563094015,RU
3563094016,3563096255,DE
3563096256,3563096287,GB
@@ -136916,9 +139472,7 @@
3563850048,3563850111,NL
3563850112,3563850239,ES
3563850240,3563850751,GB
-3563850752,3563850767,NL
-3563850768,3563850783,ES
-3563850784,3563850815,NL
+3563850752,3563850815,NL
3563850816,3563850831,ES
3563850832,3563850847,NL
3563850848,3563850879,ES
@@ -136944,8 +139498,8 @@
3563853568,3563854079,ES
3563854080,3563854095,NL
3563854096,3563854103,ES
-3563854104,3563854175,NL
-3563854176,3563854239,ES
+3563854104,3563854191,NL
+3563854192,3563854239,ES
3563854240,3563854259,NL
3563854260,3563854591,ES
3563854592,3563854847,NL
@@ -137067,9 +139621,7 @@
3564339992,3564339999,NL
3564340000,3564344031,GB
3564344032,3564344047,NL
-3564344048,3564344207,GB
-3564344208,3564344215,NL
-3564344216,3564345143,GB
+3564344048,3564345143,GB
3564345144,3564345151,NL
3564345152,3564349615,GB
3564349616,3564349631,NL
@@ -137376,9 +139928,7 @@
3564881664,3564881727,NL
3564881728,3564881935,GB
3564881936,3564881939,NL
-3564881940,3564881983,GB
-3564881984,3564881991,NL
-3564881992,3564881999,GB
+3564881940,3564881999,GB
3564882000,3564882079,NL
3564882080,3564882095,GB
3564882096,3564882119,NL
@@ -137386,9 +139936,7 @@
3564882128,3564882135,NL
3564882136,3564882143,GB
3564882144,3564882239,NL
-3564882240,3564882431,GB
-3564882432,3564882943,NL
-3564882944,3564883007,GB
+3564882240,3564883007,GB
3564883008,3564883039,NL
3564883040,3564883071,GB
3564883072,3564883087,NL
@@ -137402,8 +139950,8 @@
3564884336,3564884343,NL
3564884344,3564884359,GB
3564884360,3564884367,NL
-3564884368,3564884375,GB
-3564884376,3564884399,NL
+3564884368,3564884383,GB
+3564884384,3564884399,NL
3564884400,3564884407,GB
3564884408,3564884415,NL
3564884416,3564884431,GB
@@ -137788,8 +140336,8 @@
3565038664,3565038687,GB
3565038688,3565038719,IE
3565038720,3565038727,GB
-3565038728,3565038775,IE
-3565038776,3565039615,GB
+3565038728,3565038823,IE
+3565038824,3565039615,GB
3565039616,3565042175,IE
3565042176,3565043711,GB
3565043712,3565047807,AT
@@ -137957,9 +140505,7 @@
3565752464,3565752471,EU
3565752472,3565752479,GB
3565752480,3565752487,EU
-3565752488,3565752535,GB
-3565752536,3565752543,EU
-3565752544,3565752839,GB
+3565752488,3565752839,GB
3565752840,3565752855,EU
3565752856,3565752879,GB
3565752880,3565752887,EU
@@ -138158,9 +140704,7 @@
3566993408,3567058943,TR
3567058944,3567103047,FR
3567103048,3567103055,IT
-3567103056,3567108255,FR
-3567108256,3567108263,SE
-3567108264,3567124479,FR
+3567103056,3567124479,FR
3567124480,3567124991,EU
3567124992,3567125023,GB
3567125024,3567125247,EU
@@ -138621,7 +141165,9 @@
3569068544,3569068671,BG
3569068672,3569068951,GB
3569068952,3569068991,DE
-3569068992,3569075711,GB
+3569068992,3569074879,GB
+3569074880,3569074887,IE
+3569074888,3569075711,GB
3569075712,3569075839,FR
3569075840,3569083903,GB
3569083904,3569084159,US
@@ -139171,7 +141717,9 @@
3571415040,3571415295,GB
3571415296,3571415311,DE
3571415312,3571415327,AT
-3571415328,3571425695,DE
+3571415328,3571423743,DE
+3571423744,3571423999,US
+3571424000,3571425695,DE
3571425696,3571425727,ES
3571425728,3571426895,DE
3571426896,3571426899,ES
@@ -139188,9 +141736,7 @@
3571485196,3571515391,BE
3571515392,3571548159,GB
3571548160,3571580927,ES
-3571580928,3571595727,FI
-3571595728,3571595743,AX
-3571595744,3571646463,FI
+3571580928,3571646463,FI
3571646464,3571655560,DE
3571655561,3571655561,RO
3571655562,3571675679,DE
@@ -139442,7 +141988,11 @@
3575367112,3575367119,DE
3575367120,3575372239,ES
3575372240,3575372247,PT
-3575372248,3575382015,ES
+3575372248,3575373183,ES
+3575373184,3575373191,GB
+3575373192,3575374319,ES
+3575374320,3575374327,GB
+3575374328,3575382015,ES
3575382016,3575412991,FI
3575412992,3575413119,RU
3575413120,3575419903,FI
@@ -139718,7 +142268,7 @@
3575635704,3575635775,BE
3575635776,3575635839,CH
3575635840,3575635847,GB
-3575635848,3575635855,FR
+3575635848,3575635855,BE
3575635856,3575635871,TR
3575635872,3575635983,BE
3575635984,3575635999,DE
@@ -140273,10 +142823,8 @@
3576238152,3576238159,GB
3576238160,3576238305,FR
3576238306,3576238335,GB
-3576238336,3576238511,FR
-3576238512,3576238527,GB
-3576238528,3576238559,FR
-3576238560,3576238575,GB
+3576238336,3576238567,FR
+3576238568,3576238575,GB
3576238576,3576238863,FR
3576238864,3576238879,GB
3576238880,3576238895,FR
@@ -140289,12 +142837,9 @@
3576239040,3576239071,GB
3576239072,3576239087,FR
3576239088,3576239103,GB
-3576239104,3576239615,FR
-3576239616,3576239623,GB
+3576239104,3576239623,FR
3576239624,3576239631,IT
-3576239632,3576239663,FR
-3576239664,3576239671,GB
-3576239672,3576240039,FR
+3576239632,3576240039,FR
3576240040,3576240047,GB
3576240048,3576240111,FR
3576240112,3576240127,GB
@@ -140364,7 +142909,9 @@
3576252416,3576252671,GB
3576252672,3576254543,FR
3576254544,3576254551,GB
-3576254552,3576254607,FR
+3576254552,3576254567,FR
+3576254568,3576254575,GB
+3576254576,3576254607,FR
3576254608,3576254615,GB
3576254616,3576254623,FR
3576254624,3576254647,GB
@@ -140430,7 +142977,9 @@
3576256896,3576256959,GB
3576256960,3576256991,FR
3576256992,3576257007,GB
-3576257008,3576257135,FR
+3576257008,3576257103,FR
+3576257104,3576257119,GB
+3576257120,3576257135,FR
3576257136,3576257151,GB
3576257152,3576257159,FR
3576257160,3576257167,GB
@@ -140476,8 +143025,8 @@
3576258672,3576258687,GB
3576258688,3576258703,FR
3576258704,3576258783,GB
-3576258784,3576258823,FR
-3576258824,3576258847,GB
+3576258784,3576258831,FR
+3576258832,3576258847,GB
3576258848,3576258863,FR
3576258864,3576258895,GB
3576258896,3576258943,FR
@@ -140555,9 +143104,7 @@
3576263528,3576263567,FR
3576263568,3576263575,GB
3576263576,3576263583,FR
-3576263584,3576263599,GB
-3576263600,3576263615,FR
-3576263616,3576263623,GB
+3576263584,3576263623,GB
3576263624,3576263679,FR
3576263680,3576263743,GB
3576263744,3576263751,FR
@@ -140580,15 +143127,9 @@
3576264640,3576264687,GB
3576264688,3576265319,FR
3576265320,3576265327,GB
-3576265328,3576265359,FR
-3576265360,3576265367,GB
-3576265368,3576265375,FR
-3576265376,3576265383,GB
-3576265384,3576265399,FR
-3576265400,3576265431,GB
-3576265432,3576265439,FR
-3576265440,3576265455,GB
-3576265456,3576265463,FR
+3576265328,3576265423,FR
+3576265424,3576265431,GB
+3576265432,3576265463,FR
3576265464,3576265471,GB
3576265472,3576265759,FR
3576265760,3576265775,GB
@@ -140644,11 +143185,9 @@
3576987648,3577000959,GB
3577000960,3577001343,NL
3577001344,3577001983,GB
-3577001984,3577003647,NL
-3577003648,3577003711,GB
-3577003712,3577003767,NL
-3577003768,3577003771,GB
-3577003772,3577004031,NL
+3577001984,3577003643,NL
+3577003644,3577003711,GB
+3577003712,3577004031,NL
3577004032,3577020415,GB
3577020416,3577085951,NL
3577085952,3577151487,DE
@@ -140670,8 +143209,8 @@
3577545984,3577546111,SE
3577546112,3577546239,DE
3577546240,3577546367,US
-3577546368,3577547455,DE
-3577547456,3577547519,FR
+3577546368,3577547487,DE
+3577547488,3577547519,FR
3577547520,3577550983,DE
3577550984,3577550991,CH
3577550992,3577551407,DE
@@ -140784,8 +143323,8 @@
3577638960,3577638967,EU
3577638968,3577639239,FR
3577639240,3577639247,EU
-3577639248,3577639679,FR
-3577639680,3577639767,EU
+3577639248,3577639743,FR
+3577639744,3577639767,EU
3577639768,3577639783,FR
3577639784,3577639799,EU
3577639800,3577639807,FR
@@ -140808,9 +143347,7 @@
3577642056,3577642063,EU
3577642064,3577642239,GB
3577642240,3577642495,EU
-3577642496,3577642623,FR
-3577642624,3577642751,EU
-3577642752,3577643007,FR
+3577642496,3577643007,FR
3577643008,3577643231,NL
3577643232,3577643247,GB
3577643248,3577643263,NL
@@ -141214,20 +143751,28 @@
3580199936,3580200447,EE
3580200448,3580200959,SE
3580200960,3580201983,LT
-3580201984,3580203519,SE
+3580201984,3580203007,SE
+3580203008,3580203135,HR
+3580203136,3580203519,SE
3580203520,3580204543,RU
3580204544,3580205055,NL
3580205056,3580207103,HR
3580207104,3580208127,SE
3580208128,3580209151,EE
-3580209152,3580213247,SE
+3580209152,3580211199,SE
+3580211200,3580213247,HR
3580213248,3580214271,CH
3580214272,3580214783,LV
-3580214784,3580215295,SE
+3580214784,3580215295,HR
3580215296,3580216319,EE
3580216320,3580216831,SE
3580216832,3580217087,EE
-3580217088,3580223487,SE
+3580217088,3580221439,SE
+3580221440,3580221951,HR
+3580221952,3580222335,SE
+3580222336,3580222719,HR
+3580222720,3580222975,SE
+3580222976,3580223487,HR
3580223488,3580231679,DE
3580231680,3580231935,LT
3580231936,3580232447,LV
@@ -141403,11 +143948,12 @@
3582077112,3582077439,GB
3582077440,3582077471,DE
3582077472,3582077503,GB
-3582077504,3582077695,DE
-3582077696,3582078631,GB
+3582077504,3582077759,DE
+3582077760,3582078631,GB
3582078632,3582078639,DE
-3582078640,3582081023,GB
-3582081024,3582081535,ES
+3582078640,3582081055,GB
+3582081056,3582081087,ES
+3582081088,3582081535,GB
3582081536,3582081791,DE
3582081792,3582083071,GB
3582083072,3582091263,BG
@@ -141450,9 +143996,7 @@
3582222864,3582222879,NO
3582222880,3582223087,SE
3582223088,3582223095,NL
-3582223096,3582223967,SE
-3582223968,3582223975,NO
-3582223976,3582224375,SE
+3582223096,3582224375,SE
3582224376,3582224379,FI
3582224380,3582225719,SE
3582225720,3582225727,FI
@@ -141771,7 +144315,9 @@
3582571488,3582571647,EU
3582571648,3582571687,IE
3582571688,3582571691,EU
-3582571692,3582571719,IE
+3582571692,3582571695,IE
+3582571696,3582571707,EU
+3582571708,3582571719,IE
3582571720,3582571751,EU
3582571752,3582571839,IE
3582571840,3582571999,EU
@@ -141847,8 +144393,7 @@
3582722048,3582730239,IT
3582730240,3582736383,ES
3582736384,3582737407,DZ
-3582737408,3582737919,MA
-3582737920,3582738431,ES
+3582737408,3582738431,ES
3582738432,3582746623,DK
3582746624,3582754815,RU
3582754816,3582763007,GR
@@ -141936,14 +144481,12 @@
3583157280,3583157439,GB
3583157440,3583157471,IE
3583157472,3583157487,GB
-3583157488,3583157503,IE
-3583157504,3583158511,GB
+3583157488,3583157759,IE
+3583157760,3583158511,GB
3583158512,3583158527,IE
3583158528,3583158783,GB
3583158784,3583159039,DE
-3583159040,3583159359,GB
-3583159360,3583159375,DE
-3583159376,3583160319,GB
+3583159040,3583160319,GB
3583160320,3583161343,DE
3583161344,3583162271,GB
3583162272,3583162303,IE
@@ -142066,9 +144609,7 @@
3583706056,3583706063,RU
3583706064,3583706103,UA
3583706104,3583706107,NA
-3583706108,3583706151,UA
-3583706152,3583706159,NA
-3583706160,3583706191,UA
+3583706108,3583706191,UA
3583706192,3583706199,NA
3583706200,3583706295,UA
3583706296,3583706319,NA
@@ -142086,9 +144627,7 @@
3583706592,3583706607,NA
3583706608,3583706615,UA
3583706616,3583706623,NA
-3583706624,3583706679,UA
-3583706680,3583706687,NA
-3583706688,3583706695,UA
+3583706624,3583706695,UA
3583706696,3583706711,NA
3583706712,3583706743,UA
3583706744,3583706767,NA
@@ -142120,13 +144659,9 @@
3583707216,3583707223,NA
3583707224,3583707519,UA
3583707520,3583707535,NA
-3583707536,3583707663,UA
-3583707664,3583707671,NA
-3583707672,3583707751,UA
+3583707536,3583707751,UA
3583707752,3583707759,NA
-3583707760,3583707775,UA
-3583707776,3583707791,NA
-3583707792,3583707807,UA
+3583707760,3583707807,UA
3583707808,3583707815,NA
3583707816,3583707839,UA
3583707840,3583707855,NA
@@ -142161,8 +144696,7 @@
3583709768,3583709847,UA
3583709848,3583709863,NA
3583709864,3583709871,RU
-3583709872,3583709879,NA
-3583709880,3583709887,UA
+3583709872,3583709887,UA
3583709888,3583709911,NA
3583709912,3583709927,UA
3583709928,3583709943,NA
@@ -142193,8 +144727,7 @@
3583710744,3583710751,BE
3583710752,3583710887,UA
3583710888,3583710895,NA
-3583710896,3583711007,UA
-3583711008,3583711015,RU
+3583710896,3583711015,UA
3583711016,3583711023,NA
3583711024,3583711247,UA
3583711248,3583711255,NA
@@ -142210,9 +144743,7 @@
3583711784,3583711799,NA
3583711800,3583711815,UA
3583711816,3583711823,NA
-3583711824,3583711871,UA
-3583711872,3583711879,NA
-3583711880,3583712015,UA
+3583711824,3583712015,UA
3583712016,3583712023,NA
3583712024,3583712119,UA
3583712120,3583712127,NA
@@ -142226,14 +144757,11 @@
3583712528,3583712535,IN
3583712536,3583712775,UA
3583712776,3583712783,NA
-3583712784,3583712927,UA
-3583712928,3583712935,IN
+3583712784,3583712935,UA
3583712936,3583712943,NA
3583712944,3583713007,UA
3583713008,3583713015,RU
-3583713016,3583713079,UA
-3583713080,3583713087,IN
-3583713088,3583713279,UA
+3583713016,3583713279,UA
3583713280,3583721471,CZ
3583721472,3583729663,DE
3583729664,3583737855,TR
@@ -142262,8 +144790,7 @@
3583744104,3583744111,GB
3583744112,3583744287,EU
3583744288,3583744303,GB
-3583744304,3583744311,EU
-3583744312,3583744319,DE
+3583744304,3583744319,EU
3583744320,3583744447,GB
3583744448,3583744511,EU
3583744512,3583744767,GB
@@ -142320,8 +144847,10 @@
3583855248,3583855311,FI
3583855312,3583855327,US
3583855328,3583856383,FI
-3583856384,3583856463,SG
-3583856464,3583856615,FI
+3583856384,3583856510,SG
+3583856511,3583856511,FI
+3583856512,3583856543,SG
+3583856544,3583856615,FI
3583856616,3583856639,SG
3583856640,3583860735,FI
3583860736,3583868927,HU
@@ -142534,7 +145063,9 @@
3584929600,3584929727,DE
3584929728,3584931375,CH
3584931376,3584931391,ES
-3584931392,3584933887,CH
+3584931392,3584932295,CH
+3584932296,3584932303,DE
+3584932304,3584933887,CH
3584933888,3584942079,NO
3584942080,3584950271,DK
3584950272,3584958463,UA
@@ -142565,9 +145096,7 @@
3585048576,3585050623,IQ
3585050624,3585056767,GB
3585056768,3585064959,LB
-3585064960,3585071405,GB
-3585071406,3585071409,IN
-3585071410,3585081343,GB
+3585064960,3585081343,GB
3585081344,3585114111,IR
3585114112,3585122303,IS
3585122304,3585130495,ES
@@ -142942,9 +145471,7 @@
3586476032,3586476063,TR
3586476064,3586476287,HU
3586476288,3586476295,SK
-3586476296,3586476311,HU
-3586476312,3586476319,AT
-3586476320,3586476351,HU
+3586476296,3586476351,HU
3586476352,3586476383,AT
3586476384,3586476407,UA
3586476408,3586476415,BG
@@ -142967,11 +145494,21 @@
3586543760,3586543791,GB
3586543792,3586544703,DE
3586544704,3586544719,AE
-3586544720,3586545679,DE
+3586544720,3586545119,DE
+3586545120,3586545127,GB
+3586545128,3586545679,DE
3586545680,3586545703,GB
-3586545704,3586546375,DE
+3586545704,3586546287,DE
+3586546288,3586546303,GB
+3586546304,3586546311,DE
+3586546312,3586546319,GB
+3586546320,3586546375,DE
3586546376,3586546383,GB
-3586546384,3586555903,DE
+3586546384,3586546415,DE
+3586546416,3586546423,GB
+3586546424,3586547087,DE
+3586547088,3586547095,GB
+3586547096,3586555903,DE
3586555904,3586572287,IT
3586572288,3586588671,RS
3586588672,3586596863,IT
@@ -143035,6 +145572,7 @@
3586703360,3586719743,CH
3586719744,3586752511,ES
3586752512,3586785279,NL
+3586785280,3586793471,OM
3586793472,3586801663,CH
3586801664,3586804751,HR
3586804752,3586804767,HU
@@ -143048,7 +145586,9 @@
3586883584,3586899967,IT
3586899968,3586900287,DE
3586900288,3586900351,NL
-3586900352,3586904831,DE
+3586900352,3586901311,DE
+3586901312,3586901375,ES
+3586901376,3586904831,DE
3586904832,3586904839,VG
3586904840,3586905199,DE
3586905200,3586905215,GB
@@ -143153,9 +145693,7 @@
3587178796,3587178799,US
3587178800,3587179439,AT
3587179440,3587179455,GB
-3587179456,3587179463,AT
-3587179464,3587179471,CH
-3587179472,3587186687,AT
+3587179456,3587186687,AT
3587186688,3587186815,DE
3587186816,3587187199,A2
3587187200,3587187455,GB
@@ -143213,9 +145751,7 @@
3587230528,3587230543,NL
3587230544,3587230607,GB
3587230608,3587230623,NL
-3587230624,3587230687,GB
-3587230688,3587230719,NL
-3587230720,3587230791,GB
+3587230624,3587230791,GB
3587230792,3587230799,NL
3587230800,3587230847,GB
3587230848,3587230911,NL
@@ -143228,7 +145764,9 @@
3587232536,3587232711,GB
3587232712,3587232719,NL
3587232720,3587232767,GB
-3587232768,3587233103,NL
+3587232768,3587232911,NL
+3587232912,3587232927,GB
+3587232928,3587233103,NL
3587233104,3587233119,GB
3587233120,3587233295,NL
3587233296,3587233319,GB
@@ -143252,12 +145790,14 @@
3587234000,3587234047,GB
3587234048,3587234079,NL
3587234080,3587234095,GB
-3587234096,3587234143,NL
+3587234096,3587234111,NL
+3587234112,3587234127,GB
+3587234128,3587234143,NL
3587234144,3587234159,GB
3587234160,3587234207,NL
3587234208,3587234815,GB
-3587234816,3587236367,NL
-3587236368,3587236383,GB
+3587234816,3587236351,NL
+3587236352,3587236383,GB
3587236384,3587236447,NL
3587236448,3587236479,GB
3587236480,3587236511,NL
@@ -143284,11 +145824,17 @@
3587238568,3587238583,GB
3587238584,3587238607,NL
3587238608,3587238911,GB
-3587238912,3587239303,NL
+3587238912,3587239279,NL
+3587239280,3587239287,GB
+3587239288,3587239303,NL
3587239304,3587239311,GB
-3587239312,3587239911,NL
+3587239312,3587239359,NL
+3587239360,3587239423,GB
+3587239424,3587239911,NL
3587239912,3587239919,GB
-3587239920,3587240063,NL
+3587239920,3587239999,NL
+3587240000,3587240007,GB
+3587240008,3587240063,NL
3587240064,3587240071,BE
3587240072,3587240103,NL
3587240104,3587240107,GB
@@ -143296,13 +145842,17 @@
3587240272,3587240279,GB
3587240280,3587240359,NL
3587240360,3587240367,GB
-3587240368,3587240439,NL
-3587240440,3587240447,GB
-3587240448,3587240511,NL
-3587240512,3587240575,GB
-3587240576,3587240615,NL
-3587240616,3587240623,GB
-3587240624,3587241071,NL
+3587240368,3587240519,NL
+3587240520,3587240527,GB
+3587240528,3587240543,NL
+3587240544,3587240559,IE
+3587240560,3587240567,BE
+3587240568,3587240575,GB
+3587240576,3587240607,NL
+3587240608,3587240623,GB
+3587240624,3587241039,NL
+3587241040,3587241047,GB
+3587241048,3587241071,NL
3587241072,3587241087,GB
3587241088,3587241143,NL
3587241144,3587241151,GB
@@ -143312,13 +145862,17 @@
3587241264,3587241271,GB
3587241272,3587241343,NL
3587241344,3587241471,GB
-3587241472,3587242095,NL
+3587241472,3587242047,NL
+3587242048,3587242055,GB
+3587242056,3587242071,NL
+3587242072,3587242079,IE
+3587242080,3587242095,NL
3587242096,3587242111,GB
3587242112,3587242271,NL
3587242272,3587242287,GB
3587242288,3587242463,NL
-3587242464,3587242471,GB
-3587242472,3587243407,NL
+3587242464,3587242495,GB
+3587242496,3587243407,NL
3587243408,3587243415,GB
3587243416,3587243935,NL
3587243936,3587243951,GB
@@ -143326,7 +145880,8 @@
3587243968,3587243975,GB
3587243976,3587243983,NL
3587243984,3587243991,GB
-3587243992,3587244031,NL
+3587243992,3587244023,NL
+3587244024,3587244031,GB
3587244032,3587260415,IT
3587260416,3587284991,DE
3587284992,3587285135,A2
@@ -143458,7 +146013,7 @@
3587391488,3587407871,KZ
3587407872,3587408383,NL
3587408384,3587408895,BE
-3587408896,3587409407,NL
+3587408896,3587409407,RU
3587409408,3587410431,BE
3587410432,3587410687,NL
3587410688,3587412223,BE
@@ -143496,7 +146051,9 @@
3587699560,3587699567,GB
3587699568,3587700031,IT
3587700032,3587700039,GB
-3587700040,3587701295,IT
+3587700040,3587701271,IT
+3587701272,3587701279,DE
+3587701280,3587701295,IT
3587701296,3587701303,FR
3587701304,3587702783,IT
3587702784,3587710975,DE
@@ -143571,9 +146128,7 @@
3588521984,3588538367,PT
3588538368,3588544383,GB
3588544384,3588544391,IE
-3588544392,3588550447,GB
-3588550448,3588550463,IE
-3588550464,3588553983,GB
+3588544392,3588553983,GB
3588553984,3588554239,IE
3588554240,3588554687,GB
3588554688,3588554751,IE
@@ -143778,7 +146333,9 @@
3589582656,3589583359,NL
3589583360,3589583647,GB
3589583648,3589583663,NL
-3589583664,3589584255,GB
+3589583664,3589583743,GB
+3589583744,3589583871,NL
+3589583872,3589584255,GB
3589584256,3589584271,NL
3589584272,3589584639,GB
3589584640,3589585279,NL
@@ -144031,9 +146588,7 @@
3589891616,3589891631,BE
3589891632,3589931007,GB
3589931008,3589947391,SI
-3589947392,3589951863,FI
-3589951864,3589951871,AX
-3589951872,3589963775,FI
+3589947392,3589963775,FI
3589963776,3589971231,ES
3589971232,3589971247,CA
3589971248,3589980159,ES
@@ -144089,8 +146644,8 @@
3590157568,3590157631,SI
3590157632,3590157679,RS
3590157680,3590157687,SI
-3590157688,3590157711,RS
-3590157712,3590157743,SI
+3590157688,3590157719,RS
+3590157720,3590157743,SI
3590157744,3590157751,RS
3590157752,3590157759,SI
3590157760,3590157767,RS
@@ -144106,10 +146661,10 @@
3590158360,3590158367,RS
3590158368,3590158407,SI
3590158408,3590158415,RS
-3590158416,3590158431,SI
+3590158416,3590158431,ME
3590158432,3590158439,RS
-3590158440,3590158455,SI
-3590158456,3590158479,RS
+3590158440,3590158447,SI
+3590158448,3590158479,RS
3590158480,3590158527,SI
3590158528,3590158535,RS
3590158536,3590158591,SI
@@ -144125,11 +146680,13 @@
3590225920,3590234111,TR
3590234112,3590242303,GB
3590242304,3590244351,US
-3590244352,3590244863,DE
+3590244352,3590244607,DE
+3590244608,3590244863,IT
3590244864,3590245119,FR
-3590245120,3590245183,BE
-3590245184,3590245279,FR
-3590245280,3590245311,BE
+3590245120,3590245135,BE
+3590245136,3590245143,FR
+3590245144,3590245183,BE
+3590245184,3590245311,FR
3590245312,3590245439,US
3590245440,3590245503,FR
3590245504,3590245567,GB
@@ -144166,10 +146723,9 @@
3590251520,3590251583,FR
3590251584,3590251647,US
3590251648,3590251775,NL
-3590251776,3590251839,FR
-3590251840,3590251903,ES
-3590251904,3590251967,FR
-3590251968,3590252543,ES
+3590251776,3590251967,FR
+3590251968,3590252287,ES
+3590252288,3590252543,FR
3590252544,3590253055,GB
3590253056,3590253311,DE
3590253312,3590253375,FR
@@ -144182,17 +146738,14 @@
3590254144,3590254271,US
3590254272,3590254463,FR
3590254464,3590254591,ES
-3590254592,3590254847,FR
-3590254848,3590254879,ES
-3590254880,3590254911,FR
+3590254592,3590254911,FR
3590254912,3590254975,ES
3590254976,3590255039,DE
3590255040,3590255047,FR
3590255048,3590255071,ES
3590255072,3590255103,FR
3590255104,3590255359,ES
-3590255360,3590255615,FR
-3590255616,3590255871,BE
+3590255360,3590255871,FR
3590255872,3590256127,US
3590256128,3590256383,ES
3590256384,3590256639,FR
@@ -144217,10 +146770,13 @@
3590307904,3590307935,UA
3590307936,3590307951,A2
3590307952,3590307967,NG
-3590307968,3590308031,A2
+3590307968,3590307991,A2
+3590307992,3590307995,SO
+3590307996,3590308031,A2
3590308032,3590308047,UG
3590308048,3590308055,NG
-3590308056,3590308071,A2
+3590308056,3590308063,A2
+3590308064,3590308071,SO
3590308072,3590308079,RW
3590308080,3590308087,IQ
3590308088,3590308095,A2
@@ -144237,9 +146793,11 @@
3590308248,3590308287,IQ
3590308288,3590308303,A2
3590308304,3590308311,SO
-3590308312,3590308343,IQ
-3590308344,3590308359,A2
-3590308360,3590308367,IQ
+3590308312,3590308319,IQ
+3590308320,3590308327,A2
+3590308328,3590308343,IQ
+3590308344,3590308351,A2
+3590308352,3590308367,IQ
3590308368,3590308375,A2
3590308376,3590308391,IQ
3590308392,3590308399,A2
@@ -144260,14 +146818,17 @@
3590308568,3590308583,IQ
3590308584,3590308607,A2
3590308608,3590308735,NG
-3590308736,3590308767,A2
+3590308736,3590308743,A2
+3590308744,3590308747,SO
+3590308748,3590308767,A2
3590308768,3590308775,RW
3590308776,3590308783,ZA
3590308784,3590308799,ZW
3590308800,3590308807,GB
3590308808,3590308815,ZM
3590308816,3590308823,KE
-3590308824,3590308855,A2
+3590308824,3590308831,SO
+3590308832,3590308855,A2
3590308856,3590308863,NG
3590308864,3590308951,A2
3590308952,3590308959,GH
@@ -144280,7 +146841,9 @@
3590309072,3590309079,MW
3590309080,3590309103,NG
3590309104,3590309111,ZW
-3590309112,3590309511,A2
+3590309112,3590309251,A2
+3590309252,3590309255,SO
+3590309256,3590309511,A2
3590309512,3590309519,AO
3590309520,3590309527,NG
3590309528,3590309535,CM
@@ -144311,7 +146874,8 @@
3590309888,3590310143,A2
3590310144,3590310175,IQ
3590310176,3590310183,LR
-3590310184,3590310215,IQ
+3590310184,3590310191,A2
+3590310192,3590310215,IQ
3590310216,3590310223,A2
3590310224,3590310255,IQ
3590310256,3590310271,A2
@@ -144333,16 +146897,14 @@
3590310952,3590310959,IQ
3590310960,3590310967,A2
3590310968,3590311007,IQ
-3590311008,3590311015,A2
-3590311016,3590311023,IQ
-3590311024,3590311031,A2
+3590311008,3590311031,A2
3590311032,3590311039,IQ
3590311040,3590311055,A2
3590311056,3590311063,IQ
3590311064,3590311079,A2
3590311080,3590311087,IQ
-3590311088,3590311095,A2
-3590311096,3590311111,IQ
+3590311088,3590311103,A2
+3590311104,3590311111,IQ
3590311112,3590311119,A2
3590311120,3590311135,IQ
3590311136,3590311143,A2
@@ -144352,7 +146914,7 @@
3590311184,3590311199,A2
3590311200,3590311207,SD
3590311208,3590311215,CD
-3590311216,3590311223,AO
+3590311216,3590311223,A2
3590311224,3590311231,CD
3590311232,3590311255,A2
3590311256,3590311263,ZW
@@ -144441,9 +147003,7 @@
3590317496,3590317503,LB
3590317504,3590317527,A2
3590317528,3590317543,IQ
-3590317544,3590317567,A2
-3590317568,3590317695,IQ
-3590317696,3590317951,A2
+3590317544,3590317951,A2
3590317952,3590318047,UA
3590318048,3590319167,A2
3590319168,3590319231,AE
@@ -144743,7 +147303,47 @@
3624549616,3624550143,A2
3624550144,3624587263,US
3624587264,3624591359,JM
-3624591360,3624730623,US
+3624591360,3624714239,US
+3624714240,3624714623,SG
+3624714624,3624714639,US
+3624714640,3624714655,SG
+3624714656,3624714679,US
+3624714680,3624714687,SG
+3624714688,3624714719,US
+3624714720,3624714743,SG
+3624714744,3624714751,US
+3624714752,3624715023,SG
+3624715024,3624715071,US
+3624715072,3624715103,SG
+3624715104,3624715167,US
+3624715168,3624715183,SG
+3624715184,3624715263,US
+3624715264,3624715647,SG
+3624715648,3624715655,US
+3624715656,3624715743,SG
+3624715744,3624715775,US
+3624715776,3624716031,SG
+3624716032,3624716223,US
+3624716224,3624716255,AU
+3624716256,3624718335,US
+3624718336,3624718591,SG
+3624718592,3624718863,US
+3624718864,3624718879,AU
+3624718880,3624718951,US
+3624718952,3624718959,SG
+3624718960,3624719103,US
+3624719104,3624719359,SG
+3624719360,3624719535,US
+3624719536,3624719543,AU
+3624719544,3624719615,US
+3624719616,3624719743,SG
+3624719744,3624719751,US
+3624719752,3624719871,SG
+3624719872,3624720895,US
+3624720896,3624721151,SG
+3624721152,3624721727,US
+3624721728,3624721759,SG
+3624721760,3624730623,US
3624730624,3624796159,CA
3624796160,3624817679,US
3624817680,3624817687,CA
@@ -144917,7 +147517,9 @@
3624912680,3624912687,IN
3624912688,3624912727,US
3624912728,3624912735,TT
-3624912736,3624912959,US
+3624912736,3624912759,US
+3624912760,3624912767,MY
+3624912768,3624912959,US
3624912960,3624913087,IN
3624913088,3624913247,US
3624913248,3624913279,CA
@@ -145009,7 +147611,8 @@
3624924896,3624924927,CA
3624924928,3624925054,US
3624925055,3624925695,CA
-3624925696,3624926463,US
+3624925696,3624926335,US
+3624926336,3624926463,TZ
3624926464,3624926527,CA
3624926528,3624926591,US
3624926592,3624926655,IN
@@ -145178,8 +147781,8 @@
3625512960,3625528541,US
3625528542,3625528551,AU
3625528552,3625574399,US
-3625574400,3625578495,A2
-3625578496,3625581631,US
+3625574400,3625578239,A2
+3625578240,3625581631,US
3625581632,3625581647,NL
3625581648,3625631743,US
3625631744,3625639935,CA
@@ -145530,7 +148133,9 @@
3626383299,3626383375,US
3626383376,3626383383,RU
3626383384,3626383391,CA
-3626383392,3626383423,US
+3626383392,3626383399,US
+3626383400,3626383407,IN
+3626383408,3626383423,US
3626383424,3626383431,GB
3626383432,3626383439,AU
3626383440,3626383447,GR
@@ -145543,8 +148148,7 @@
3626383544,3626383551,GB
3626383552,3626383583,US
3626383584,3626383599,CA
-3626383600,3626383607,GB
-3626383608,3626383615,IN
+3626383600,3626383615,IN
3626383616,3626383647,US
3626383648,3626383679,CH
3626383680,3626383727,US
@@ -145583,7 +148187,9 @@
3626385038,3626385041,US
3626385042,3626385045,MX
3626385046,3626385049,CA
-3626385050,3626385073,US
+3626385050,3626385057,US
+3626385058,3626385061,IN
+3626385062,3626385073,US
3626385074,3626385077,IE
3626385078,3626385097,US
3626385098,3626385101,IN
@@ -145592,7 +148198,7 @@
3626385118,3626385121,US
3626385122,3626385125,IN
3626385126,3626385129,ID
-3626385130,3626385133,GR
+3626385130,3626385133,IN
3626385134,3626385137,CA
3626385138,3626385141,GB
3626385142,3626385145,IN
@@ -145616,13 +148222,15 @@
3626385250,3626385253,CN
3626385254,3626385261,US
3626385262,3626385265,GR
-3626385266,3626385321,US
+3626385266,3626385285,US
+3626385286,3626385289,IN
+3626385290,3626385321,US
3626385322,3626385325,FR
3626385326,3626385329,CA
3626385330,3626385333,US
3626385334,3626385337,CA
3626385338,3626385349,US
-3626385350,3626385353,CA
+3626385350,3626385353,IN
3626385354,3626385357,MX
3626385358,3626385361,CA
3626385362,3626385365,US
@@ -145787,8 +148395,7 @@
3626896184,3626905599,CA
3626905600,3626926079,US
3626926080,3626934271,CA
-3626934272,3626942463,US
-3626950656,3627044863,US
+3626934272,3627044863,US
3627044864,3627048959,CA
3627048960,3627065343,US
3627065344,3627069439,CA
@@ -145796,7 +148403,9 @@
3627288576,3627288607,GB
3627288608,3627309455,US
3627309456,3627309471,IL
-3627309472,3627310471,US
+3627309472,3627309695,US
+3627309696,3627309823,AE
+3627309824,3627310471,US
3627310472,3627310479,BM
3627310480,3627317087,US
3627317088,3627317119,GB
@@ -145857,9 +148466,7 @@
3627746400,3627746431,CA
3627746432,3627747159,US
3627747160,3627747167,IN
-3627747168,3627747583,US
-3627747584,3627747615,FR
-3627747616,3627753471,US
+3627747168,3627753471,US
3627753472,3627753727,AR
3627753728,3627755007,US
3627755008,3627755135,IE
@@ -146105,14 +148712,14 @@
3629202016,3629202047,CA
3629202048,3629202175,US
3629202176,3629202203,CA
-3629202204,3629202219,US
-3629202220,3629202239,CA
+3629202204,3629202223,US
+3629202224,3629202239,CA
3629202240,3629202263,US
3629202264,3629202271,CA
-3629202272,3629202311,US
-3629202312,3629202367,CA
-3629202368,3629202427,US
-3629202428,3629203199,CA
+3629202272,3629202319,US
+3629202320,3629202367,CA
+3629202368,3629202431,US
+3629202432,3629203199,CA
3629203200,3629318143,US
3629318144,3629326335,CA
3629326336,3629327527,US
@@ -146853,9 +149460,9 @@
3632480496,3632480503,US
3632480504,3632480511,RU
3632480512,3632480543,TK
-3632480544,3632480567,US
-3632480568,3632480575,GB
-3632480576,3632480599,US
+3632480544,3632480559,US
+3632480560,3632480567,DE
+3632480568,3632480599,US
3632480600,3632480607,CA
3632480608,3632480615,GB
3632480616,3632480647,US
@@ -146871,9 +149478,7 @@
3632481280,3632481287,GB
3632481288,3632481295,US
3632481296,3632481311,TH
-3632481312,3632481391,US
-3632481392,3632481399,GB
-3632481400,3632481415,US
+3632481312,3632481415,US
3632481416,3632481423,TH
3632481424,3632481431,US
3632481432,3632481439,CA
@@ -146893,11 +149498,10 @@
3632481768,3632481775,US
3632481776,3632481783,CA
3632481784,3632481791,GB
-3632481792,3632481815,US
-3632481816,3632481823,GB
-3632481824,3632481999,US
+3632481792,3632481999,US
3632482000,3632482007,BZ
-3632482008,3632482039,US
+3632482008,3632482015,CA
+3632482016,3632482039,US
3632482040,3632482047,TK
3632482048,3632482239,US
3632482240,3632482247,GB
@@ -146911,8 +149515,7 @@
3632483152,3632483159,GB
3632483160,3632483327,US
3632483328,3632483335,CA
-3632483336,3632483351,US
-3632483352,3632483359,CN
+3632483336,3632483359,US
3632483360,3632483367,NL
3632483368,3632483375,GI
3632483376,3632483391,GB
@@ -146925,9 +149528,7 @@
3632483584,3632483599,US
3632483600,3632483607,AU
3632483608,3632483615,PL
-3632483616,3632483623,GB
-3632483624,3632483663,US
-3632483664,3632483671,PH
+3632483616,3632483671,US
3632483672,3632483679,CA
3632483680,3632483759,US
3632483760,3632483775,TH
@@ -146969,8 +149570,7 @@
3632484816,3632484823,US
3632484824,3632484831,CA
3632484832,3632484839,HK
-3632484840,3632484847,BZ
-3632484848,3632484855,US
+3632484840,3632484855,US
3632484856,3632484863,GB
3632484864,3632485055,US
3632485056,3632485087,TW
@@ -146989,15 +149589,16 @@
3632485280,3632485311,TH
3632485312,3632485391,US
3632485392,3632485399,SR
-3632485400,3632485431,US
+3632485400,3632485407,US
+3632485408,3632485415,CA
+3632485416,3632485431,US
3632485432,3632485439,CA
3632485440,3632485471,US
3632485472,3632485487,NC
-3632485488,3632485551,US
+3632485488,3632485535,US
+3632485536,3632485551,CA
3632485552,3632485559,GB
-3632485560,3632485567,US
-3632485568,3632485575,GB
-3632485576,3632485615,US
+3632485560,3632485615,US
3632485616,3632485623,TH
3632485624,3632485631,CA
3632485632,3632485639,US
@@ -147011,7 +149612,7 @@
3632485728,3632485735,CA
3632485736,3632485751,US
3632485752,3632485759,CA
-3632485760,3632485767,CZ
+3632485760,3632485767,US
3632485768,3632485775,KW
3632485776,3632485847,US
3632485848,3632485855,CA
@@ -147027,7 +149628,9 @@
3632486112,3632486143,US
3632486144,3632486151,TK
3632486152,3632486159,GB
-3632486160,3632486263,US
+3632486160,3632486191,US
+3632486192,3632486199,GB
+3632486200,3632486263,US
3632486264,3632486271,GB
3632486272,3632486287,FR
3632486288,3632486319,US
@@ -147037,11 +149640,10 @@
3632486344,3632486351,FR
3632486352,3632486407,US
3632486408,3632486415,TH
-3632486416,3632486423,US
-3632486424,3632486431,CA
-3632486432,3632486479,US
+3632486416,3632486479,US
3632486480,3632486495,GB
-3632486496,3632486519,US
+3632486496,3632486511,US
+3632486512,3632486519,HU
3632486520,3632486527,GB
3632486528,3632486543,US
3632486544,3632486551,DE
@@ -147058,8 +149660,7 @@
3632486784,3632486815,DE
3632486816,3632486879,US
3632486880,3632486895,TH
-3632486896,3632486903,GB
-3632486904,3632487023,US
+3632486896,3632487023,US
3632487024,3632487031,TH
3632487032,3632487039,CZ
3632487040,3632487135,US
@@ -147073,8 +149674,9 @@
3632487816,3632487823,IL
3632487824,3632487855,US
3632487856,3632487863,GB
-3632487864,3632487871,CA
-3632487872,3632489087,US
+3632487864,3632487895,US
+3632487896,3632487903,GB
+3632487904,3632489087,US
3632489088,3632489119,SR
3632489120,3632489127,US
3632489128,3632489135,AU
@@ -147170,7 +149772,8 @@
3632493088,3632493119,IO
3632493120,3632493151,US
3632493152,3632493159,GR
-3632493160,3632493191,US
+3632493160,3632493183,US
+3632493184,3632493191,BZ
3632493192,3632493199,CA
3632493200,3632493215,US
3632493216,3632493223,DE
@@ -147604,7 +150207,27 @@
3635533000,3635533007,NO
3635533008,3635533535,US
3635533536,3635533551,IN
-3635533552,3635650559,US
+3635533552,3635643391,US
+3635643392,3635643647,JP
+3635643648,3635643679,US
+3635643680,3635643681,JP
+3635643682,3635643710,US
+3635643711,3635643903,JP
+3635643904,3635644159,US
+3635644160,3635644255,JP
+3635644256,3635644319,US
+3635644320,3635644671,JP
+3635644672,3635645439,US
+3635645440,3635645696,JP
+3635645697,3635645728,US
+3635645729,3635645760,JP
+3635645761,3635645776,US
+3635645777,3635645951,JP
+3635645952,3635646335,US
+3635646336,3635646367,JP
+3635646368,3635648767,US
+3635648768,3635649023,JP
+3635649024,3635650559,US
3635650560,3635650815,JP
3635650816,3635651071,US
3635651072,3635651327,JP
@@ -147639,7 +150262,10 @@
3635656224,3635656319,US
3635656320,3635656447,JP
3635656448,3635656703,CA
-3635656704,3635659263,US
+3635656704,3635656967,JP
+3635656968,3635657023,US
+3635657024,3635657215,JP
+3635657216,3635659263,US
3635659264,3635660031,ID
3635660032,3635660287,CN
3635660288,3635660799,US
@@ -147669,7 +150295,19 @@
3636019200,3636021775,CA
3636021776,3636021791,US
3636021792,3636027391,CA
-3636027392,3636064255,US
+3636027392,3636028415,US
+3636028416,3636029951,SG
+3636029952,3636030207,US
+3636030208,3636031231,SG
+3636031232,3636031999,US
+3636032000,3636032511,SG
+3636032512,3636032767,US
+3636032768,3636033535,SG
+3636033536,3636033791,US
+3636033792,3636034303,SG
+3636034304,3636035327,US
+3636035328,3636035583,SG
+3636035584,3636064255,US
3636064256,3636068351,CA
3636068352,3636150495,US
3636150496,3636150527,CA
@@ -147771,7 +150409,8 @@
3636161872,3636161885,US
3636161886,3636161943,CA
3636161944,3636161951,US
-3636161952,3636161983,CN
+3636161952,3636161967,CA
+3636161968,3636161983,CN
3636161984,3636162015,US
3636162016,3636162559,CA
3636162560,3636163583,US
@@ -147821,9 +150460,7 @@
3636904544,3636904575,IN
3636904576,3636904607,US
3636904608,3636904671,IN
-3636904672,3636904703,US
-3636904704,3636904959,MY
-3636904960,3636905471,US
+3636904672,3636905471,US
3636905472,3636905727,CA
3636905728,3636905791,US
3636905792,3636905823,IN
@@ -148005,7 +150642,9 @@
3638198952,3638198959,BM
3638198960,3638198983,US
3638198984,3638198991,ES
-3638198992,3638199711,US
+3638198992,3638199167,US
+3638199168,3638199295,CN
+3638199296,3638199711,US
3638199712,3638199743,DE
3638199744,3638199807,US
3638199808,3638199815,CN
@@ -148124,7 +150763,11 @@
3638400000,3638400063,CA
3638400064,3638400271,US
3638400272,3638400279,CA
-3638400280,3638509295,US
+3638400280,3638400559,US
+3638400560,3638400567,PA
+3638400568,3638400639,US
+3638400640,3638400767,CA
+3638400768,3638509295,US
3638509296,3638509311,GB
3638509312,3638509567,US
3638509568,3638526911,CA
@@ -148254,12 +150897,15 @@
3639498768,3639498783,SI
3639498784,3639498791,US
3639498792,3639498799,NL
-3639498800,3639533567,US
+3639498800,3639513087,US
+3639513088,3639513119,AE
+3639513120,3639513239,US
+3639513240,3639513243,AE
+3639513244,3639533567,US
3639533568,3639537663,CA
3639537664,3639558143,US
3639558144,3639566335,CA
-3639566336,3639582719,US
-3639590912,3639593983,US
+3639566336,3639593983,US
3639593984,3639595007,GB
3639595008,3639607295,US
3639607296,3639611391,CA
@@ -148523,9 +151169,7 @@
3641103720,3641103727,HU
3641103728,3641106951,DE
3641106952,3641106959,CH
-3641106960,3641134367,DE
-3641134368,3641134375,BE
-3641134376,3641140671,DE
+3641106960,3641140671,DE
3641140672,3641140679,US
3641140680,3641147519,DE
3641147520,3641147527,AT
@@ -148600,18 +151244,16 @@
3641353808,3641353831,GB
3641353832,3641353839,A2
3641353840,3641353855,GB
-3641353856,3641353983,A2
+3641353856,3641353879,NG
+3641353880,3641353983,A2
3641353984,3641354239,AF
-3641354240,3641354255,NG
-3641354256,3641354311,A2
+3641354240,3641354311,A2
3641354312,3641354319,GB
3641354320,3641354327,A2
3641354328,3641354335,GB
3641354336,3641354339,A2
3641354340,3641354367,GB
-3641354368,3641354383,A2
-3641354384,3641354391,NG
-3641354392,3641354495,A2
+3641354368,3641354495,A2
3641354496,3641354751,GB
3641354752,3641355263,NG
3641355264,3641355519,AO
@@ -148621,14 +151263,14 @@
3641355776,3641356031,LB
3641356032,3641356191,A2
3641356192,3641356207,NG
-3641356208,3641357855,A2
+3641356208,3641357823,A2
+3641357824,3641357831,NG
+3641357832,3641357855,A2
3641357856,3641357879,GB
3641357880,3641357887,A2
3641357888,3641357927,GB
3641357928,3641358335,A2
-3641358336,3641358591,GB
-3641358592,3641358847,A2
-3641358848,3641359359,GB
+3641358336,3641359359,GB
3641359360,3641359615,IQ
3641359616,3641359639,GB
3641359640,3641359871,A2
@@ -148689,7 +151331,7 @@
3641565184,3641567343,SE
3641567344,3641567351,FI
3641567352,3641568967,SE
-3641568968,3641568975,NO
+3641568968,3641568975,DK
3641568976,3641573375,SE
3641573376,3641577471,NO
3641577472,3641581567,RU
@@ -149032,8 +151674,7 @@
3642415652,3642415655,MT
3642415656,3642417151,GB
3642417152,3642419199,DE
-3642419200,3642419967,US
-3642419968,3642421247,GB
+3642419200,3642421247,GB
3642421248,3642423091,A2
3642423092,3642423099,NG
3642423100,3642424151,A2
@@ -149129,8 +151770,7 @@
3642553472,3642553519,RU
3642553520,3642553523,UA
3642553524,3642553535,RU
-3642553536,3642553543,DE
-3642553544,3642553547,UA
+3642553536,3642553547,UA
3642553548,3642553567,RU
3642553568,3642553571,UA
3642553572,3642553575,RU
@@ -149147,11 +151787,17 @@
3642554120,3642554127,UA
3642554128,3642554159,RU
3642554160,3642554187,UA
-3642554188,3642554207,RU
+3642554188,3642554193,RU
+3642554194,3642554195,UA
+3642554196,3642554207,RU
3642554208,3642554219,UA
3642554220,3642554223,RU
3642554224,3642554367,UA
-3642554368,3642554573,LT
+3642554368,3642554427,LT
+3642554428,3642554431,UA
+3642554432,3642554447,LT
+3642554448,3642554463,UA
+3642554464,3642554573,LT
3642554574,3642554575,UA
3642554576,3642554623,LT
3642554624,3642554631,UA
@@ -149167,9 +151813,7 @@
3642554880,3642554911,DE
3642554912,3642554919,NL
3642554920,3642554931,DE
-3642554932,3642554951,UA
-3642554952,3642554955,GE
-3642554956,3642554959,UA
+3642554932,3642554959,UA
3642554960,3642554963,DE
3642554964,3642554967,UA
3642554968,3642554971,LV
@@ -149193,7 +151837,8 @@
3642555070,3642555071,DE
3642555072,3642555087,GE
3642555088,3642555103,DE
-3642555104,3642555135,UA
+3642555104,3642555111,CZ
+3642555112,3642555135,UA
3642555136,3642555153,LT
3642555154,3642555167,UA
3642555168,3642555183,LT
@@ -149211,9 +151856,7 @@
3642555440,3642555443,UA
3642555444,3642555463,PL
3642555464,3642555475,UA
-3642555476,3642555493,PL
-3642555494,3642555495,UA
-3642555496,3642555503,PL
+3642555476,3642555503,PL
3642555504,3642555647,UA
3642555648,3642555683,SE
3642555684,3642555685,GB
@@ -149226,14 +151869,14 @@
3642555728,3642555735,SE
3642555736,3642555743,GB
3642555744,3642555759,SE
-3642555760,3642555767,UA
-3642555768,3642555771,GB
+3642555760,3642555771,UA
3642555772,3642555775,SE
3642555776,3642555783,UA
3642555784,3642555787,GB
3642555788,3642555789,UA
3642555790,3642555791,SE
-3642555792,3642556159,UA
+3642555792,3642555795,CZ
+3642555796,3642556159,UA
3642556160,3642556415,LV
3642556416,3642558975,CZ
3642558976,3642559487,HR
@@ -149414,8 +152057,8 @@
3645183744,3645183871,GB
3645183872,3645183903,FR
3645183904,3645183935,IE
-3645183936,3645184256,FR
-3645184257,3645184447,GB
+3645183936,3645184255,FR
+3645184256,3645184447,GB
3645184448,3645186047,FR
3645186048,3645190143,GB
3645190144,3645194239,FI
@@ -149508,7 +152151,9 @@
3645435904,3645439999,GB
3645440000,3645444095,SE
3645444096,3645448191,SK
-3645448192,3645455487,DE
+3645448192,3645454335,DE
+3645454336,3645455359,RU
+3645455360,3645455487,DE
3645455488,3645456383,RU
3645456384,3645460479,GB
3645460480,3645464575,UA
@@ -149530,6 +152175,8 @@
3645507596,3645507599,DE
3645507600,3645507607,AT
3645507608,3645509631,DE
+3645509632,3645511679,NL
+3645511680,3645513727,TR
3645513728,3645517823,RU
3645517824,3645521919,IE
3645521920,3645526015,PL
@@ -149571,7 +152218,8 @@
3645601508,3645601759,SE
3645601760,3645601775,FR
3645601776,3645601779,GB
-3645601780,3645601799,SE
+3645601780,3645601783,US
+3645601784,3645601799,SE
3645601800,3645601803,GB
3645601804,3645603839,SE
3645603840,3645612031,BG
@@ -149995,9 +152643,7 @@
3645764087,3645764087,CH
3645764088,3645764091,DE
3645764092,3645764092,FR
-3645764093,3645764093,DE
-3645764094,3645764094,IT
-3645764095,3645764097,DE
+3645764093,3645764097,DE
3645764098,3645764098,IT
3645764099,3645764099,DE
3645764100,3645764100,BE
@@ -150540,9 +153186,7 @@
3645889920,3645890559,DE
3645890560,3645894655,RU
3645894656,3645898751,NL
-3645898752,3646501711,DE
-3646501712,3646501719,US
-3646501720,3646513103,DE
+3645898752,3646513103,DE
3646513104,3646513111,CA
3646513112,3646947327,DE
3646947328,3647209471,PL
@@ -150622,8 +153266,8 @@
3647965296,3647965303,DE
3647965304,3647965311,ES
3647965312,3647965319,DE
-3647965320,3647965423,ES
-3647965424,3647965439,DE
+3647965320,3647965431,ES
+3647965432,3647965439,DE
3647965440,3647965695,ES
3647965696,3647966207,CH
3647966208,3647966575,GB
@@ -150649,15 +153293,14 @@
3647973736,3647973743,DE
3647973744,3647973783,IT
3647973784,3647973791,DE
-3647973792,3647973951,IT
-3647973952,3647973959,DE
-3647973960,3647973967,IT
+3647973792,3647973967,IT
3647973968,3647973975,DE
3647973976,3647974047,IT
3647974048,3647974055,DE
3647974056,3647974399,IT
3647974400,3647976447,ES
-3647976448,3647976559,BE
+3647976448,3647976463,DE
+3647976464,3647976559,BE
3647976560,3647976575,FR
3647976576,3647976647,BE
3647976648,3647976663,DE
@@ -150688,13 +153331,13 @@
3647978912,3647979007,NL
3647979008,3647979136,IT
3647979137,3647979519,DE
-3647979520,3647980215,FR
+3647979520,3647979983,FR
+3647979984,3647979991,DE
+3647979992,3647980215,FR
3647980216,3647980223,DE
3647980224,3647980239,FR
3647980240,3647980247,DE
-3647980248,3647980255,FR
-3647980256,3647980271,DE
-3647980272,3647980471,FR
+3647980248,3647980471,FR
3647980472,3647980479,DE
3647980480,3647980495,FR
3647980496,3647980503,DE
@@ -150723,15 +153366,17 @@
3647987184,3647987191,DE
3647987192,3647987199,ES
3647987200,3647987455,DE
-3647987456,3647987527,ES
+3647987456,3647987487,ES
+3647987488,3647987495,DE
+3647987496,3647987527,ES
3647987528,3647987535,GB
3647987536,3647987543,DE
3647987544,3647987711,ES
3647987712,3647988735,IT
3647988736,3647988991,DE
-3647988992,3647989495,BE
-3647989496,3647989503,DE
-3647989504,3647989759,BE
+3647988992,3647989263,BE
+3647989264,3647989375,DE
+3647989376,3647989759,BE
3647989760,3647990271,DE
3647990272,3647990527,ES
3647990528,3647995903,DE
@@ -150784,8 +153429,7 @@
3648078496,3648078527,BE
3648078528,3648078591,BF
3648078592,3648078847,CG
-3648078848,3648079103,BE
-3648079104,3648080383,UG
+3648078848,3648080383,BE
3648080384,3648080511,TZ
3648080512,3648080543,BF
3648080544,3648080639,TZ
@@ -150806,7 +153450,7 @@
3648082432,3648082479,ZM
3648082480,3648084991,BE
3648084992,3648085759,GB
-3648085760,3648086015,LR
+3648085760,3648086015,ZM
3648086016,3648090111,AT
3648090112,3648094207,RU
3648094208,3648102399,PL
@@ -150890,7 +153534,9 @@
3648184320,3648192511,RU
3648192512,3648196607,DE
3648196608,3648200703,IT
-3648200704,3648208895,SE
+3648200704,3648208479,SE
+3648208480,3648208511,DK
+3648208512,3648208895,SE
3648208896,3648212991,DE
3648212992,3648217087,RU
3648217088,3648221183,UA
@@ -150967,12 +153613,9 @@
3648417856,3648417919,GB
3648417920,3648418047,AT
3648418048,3648418079,GB
-3648418080,3648418135,ES
-3648418136,3648418143,GB
-3648418144,3648418247,ES
+3648418080,3648418247,ES
3648418248,3648418255,CH
-3648418256,3648418263,ES
-3648418264,3648418271,GB
+3648418256,3648418271,GB
3648418272,3648418303,ES
3648418304,3648419327,GB
3648419328,3648419455,FR
@@ -150981,8 +153624,8 @@
3648419584,3648419839,GB
3648419840,3648419901,BE
3648419902,3648419903,GB
-3648419904,3648419935,BE
-3648419936,3648420095,GB
+3648419904,3648419967,BE
+3648419968,3648420095,GB
3648420096,3648420351,NL
3648420352,3648420863,GB
3648420864,3648421119,US
@@ -151010,9 +153653,7 @@
3648465272,3648465823,FI
3648465824,3648465855,AX
3648465856,3648466943,FI
-3648466944,3648469263,DE
-3648469264,3648469271,NL
-3648469272,3648469295,DE
+3648466944,3648469295,DE
3648469296,3648469311,AT
3648469312,3648471039,DE
3648471040,3648475135,PL
@@ -151058,8 +153699,15 @@
3649709824,3649765375,GB
3649765376,3649830911,EG
3649830912,3649835007,NL
-3649835008,3649839103,ES
-3649839104,3649847295,GB
+3649835008,3649838079,ES
+3649838080,3649839103,NL
+3649839104,3649840127,GB
+3649840128,3649840383,NL
+3649840384,3649843199,GB
+3649843200,3649845247,NL
+3649845248,3649845759,GB
+3649845760,3649847039,NL
+3649847040,3649847295,GB
3649847296,3649855487,DE
3649855488,3649856511,GB
3649856512,3649857023,US
@@ -151206,7 +153854,8 @@
3650367488,3650371583,RU
3650371584,3650375679,ES
3650375680,3650379775,NL
-3650379776,3650387967,IT
+3650379776,3650381823,DE
+3650381824,3650387967,IT
3650387968,3650392063,DE
3650392064,3650396159,NO
3650396160,3650404351,NL
@@ -151215,7 +153864,9 @@
3650416640,3650420735,BE
3650420736,3650424831,ES
3650424832,3650428927,RU
-3650428928,3650433023,NL
+3650428928,3650432431,NL
+3650432432,3650432447,DE
+3650432448,3650433023,NL
3650433024,3650437119,FI
3650437120,3650441215,NL
3650441216,3650445311,IT
@@ -151325,7 +153976,9 @@
3651087872,3651088127,DE
3651088128,3651088383,IE
3651088384,3651088639,GR
-3651088640,3651090919,DE
+3651088640,3651090767,DE
+3651090768,3651090775,GB
+3651090776,3651090919,DE
3651090920,3651090959,IE
3651090960,3651098111,DE
3651098112,3651098367,IE
@@ -151380,8 +154033,8 @@
3651204352,3651204607,PL
3651204608,3651205119,ES
3651205120,3651205375,GB
-3651205376,3651205631,ES
-3651205632,3651206143,DE
+3651205376,3651205887,ES
+3651205888,3651206143,DE
3651206144,3651206399,PL
3651206400,3651207167,DE
3651207168,3651207199,GB
@@ -151831,7 +154484,9 @@
3653407072,3653407103,A2
3653407104,3653407111,UG
3653407112,3653407119,ZM
-3653407120,3653407167,A2
+3653407120,3653407135,A2
+3653407136,3653407151,MZ
+3653407152,3653407167,A2
3653407168,3653407231,NG
3653407232,3653407391,A2
3653407392,3653407399,NG
@@ -151940,11 +154595,7 @@
3653472592,3653472767,AF
3653472768,3653472775,NL
3653472776,3653472791,AF
-3653472792,3653472799,NL
-3653472800,3653472807,AF
-3653472808,3653472815,NL
-3653472816,3653472823,AF
-3653472824,3653472831,NL
+3653472792,3653472831,NL
3653472832,3653472871,AF
3653472872,3653472879,NL
3653472880,3653472915,AF
@@ -152029,12 +154680,11 @@
3653664768,3653664895,DE
3653664896,3653664911,FR
3653664912,3653665023,NL
-3653665024,3653665071,DE
-3653665072,3653665151,NL
+3653665024,3653665087,DE
+3653665088,3653665151,NL
3653665152,3653665279,DE
-3653665280,3653666815,NL
-3653666816,3653667327,DE
-3653667328,3653668863,NL
+3653665280,3653665791,NL
+3653665792,3653668863,DE
3653668864,3653672959,SE
3653672960,3653681151,RU
3653681152,3653685247,ES
@@ -152231,9 +154881,7 @@
3673817088,3673882623,HK
3673882624,3673948159,JP
3673948160,3674210303,HK
-3674210304,3674431743,JP
-3674431744,3674431999,UA
-3674432000,3678404607,JP
+3674210304,3678404607,JP
3678404608,3678535679,IN
3678535680,3678666751,JP
3678666752,3678928895,TW
@@ -152475,8 +155123,8 @@
3745513472,3749838847,CN
3749838848,3749839871,SG
3749839872,3749840895,IN
-3749840896,3749841919,PH
-3749841920,3749846015,AU
+3749841920,3749842943,AU
+3749843968,3749846015,AU
3749846016,3749847039,IN
3749847040,3749855231,HK
3749855232,3749969919,KR
diff --git a/src/or/Makefile.am b/src/or/Makefile.am
index a9ac3cdee1..a5682081ae 100644
--- a/src/or/Makefile.am
+++ b/src/or/Makefile.am
@@ -7,7 +7,7 @@ else
tor_platform_source=
endif
-EXTRA_DIST=ntmain.c or_sha1.i
+EXTRA_DIST=ntmain.c or_sha1.i Makefile.nmake
if USE_EXTERNAL_EVDNS
evdns_source=
@@ -15,16 +15,46 @@ else
evdns_source=eventdns.c
endif
-libtor_a_SOURCES = buffers.c circuitbuild.c circuitlist.c \
- circuituse.c command.c config.c \
- connection.c connection_edge.c connection_or.c control.c \
- cpuworker.c directory.c dirserv.c dirvote.c \
- dns.c dnsserv.c geoip.c hibernate.c main.c $(tor_platform_source) \
- microdesc.c \
- networkstatus.c onion.c policies.c \
- reasons.c relay.c rendcommon.c rendclient.c rendmid.c \
- rendservice.c rephist.c router.c routerlist.c routerparse.c \
- $(evdns_source) config_codedigest.c
+libtor_a_SOURCES = \
+ buffers.c \
+ circuitbuild.c \
+ circuitlist.c \
+ circuituse.c \
+ command.c \
+ config.c \
+ connection.c \
+ connection_edge.c \
+ connection_or.c \
+ control.c \
+ cpuworker.c \
+ directory.c \
+ dirserv.c \
+ dirvote.c \
+ dns.c \
+ dnsserv.c \
+ geoip.c \
+ hibernate.c \
+ main.c \
+ microdesc.c \
+ networkstatus.c \
+ nodelist.c \
+ onion.c \
+ transports.c \
+ policies.c \
+ reasons.c \
+ relay.c \
+ rendclient.c \
+ rendcommon.c \
+ rendmid.c \
+ rendservice.c \
+ rephist.c \
+ router.c \
+ routerlist.c \
+ routerparse.c \
+ status.c \
+ $(evdns_source) \
+ $(tor_platform_source) \
+ config_codedigest.c
#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \
# ../common/libor-event.a
@@ -40,18 +70,55 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# This seems to matter nowhere but on windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
+
tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
tor_LDADD = ./libtor.a ../common/libor.a ../common/libor-crypto.a \
../common/libor-event.a \
- @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
-
-noinst_HEADERS = buffers.h circuitbuild.h circuitlist.h circuituse.h \
- command.h config.h connection_edge.h connection.h connection_or.h \
- control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \
- dnsserv.h geoip.h hibernate.h main.h microdesc.h networkstatus.h \
- ntmain.h onion.h policies.h reasons.h relay.h rendclient.h \
- rendcommon.h rendmid.h rendservice.h rephist.h router.h routerlist.h \
- routerparse.h or.h eventdns.h eventdns_tor.h micro-revision.i
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS = \
+ buffers.h \
+ circuitbuild.h \
+ circuitlist.h \
+ circuituse.h \
+ command.h \
+ config.h \
+ connection.h \
+ connection_edge.h \
+ connection_or.h \
+ control.h \
+ cpuworker.h \
+ directory.h \
+ dirserv.h \
+ dirvote.h \
+ dns.h \
+ dnsserv.h \
+ eventdns.h \
+ eventdns_tor.h \
+ geoip.h \
+ hibernate.h \
+ main.h \
+ microdesc.h \
+ networkstatus.h \
+ nodelist.h \
+ ntmain.h \
+ onion.h \
+ or.h \
+ transports.h \
+ policies.h \
+ reasons.h \
+ relay.h \
+ rendclient.h \
+ rendcommon.h \
+ rendmid.h \
+ rendservice.h \
+ rephist.h \
+ router.h \
+ routerlist.h \
+ routerparse.h \
+ status.h \
+ micro-revision.i
config_codedigest.o: or_sha1.i
@@ -59,8 +126,9 @@ tor_main.o: micro-revision.i
micro-revision.i: FORCE
@rm -f micro-revision.tmp; \
- if test -d ../../.git && test -x "`which git 2>&1;true`"; then \
- HASH="`git rev-parse --short=16 HEAD`"; \
+ if test -d "$(top_srcdir)/.git" && \
+ test -x "`which git 2>&1;true`"; then \
+ HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \
echo \"$$HASH\" > micro-revision.tmp; \
fi; \
if test ! -f micro-revision.tmp ; then \
@@ -72,11 +140,13 @@ micro-revision.i: FORCE
mv micro-revision.tmp micro-revision.i; \
fi; true
-or_sha1.i: $(tor_SOURCES)
+or_sha1.i: $(tor_SOURCES) $(libtor_a_SOURCES)
if test "@SHA1SUM@" != none; then \
- @SHA1SUM@ $(tor_SOURCES) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \
+ (cd "$(srcdir)" && @SHA1SUM@ $(tor_SOURCES) $(libtor_a_SOURCES)) | \
+ @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \
elif test "@OPENSSL@" != none; then \
- @OPENSSL@ sha1 $(tor_SOURCES) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \
+ (cd "$(srcdir)" && @OPENSSL@ sha1 $(tor_SOURCES) $(libtor_a_SOURCES)) | \
+ @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \
else \
rm or_sha1.i; \
touch or_sha1.i; \
diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake
new file mode 100644
index 0000000000..919edbbf22
--- /dev/null
+++ b/src/or/Makefile.nmake
@@ -0,0 +1,28 @@
+all: tor.exe
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common
+
+LIBS = ..\..\..\build-alpha\lib\libevent.a \
+ ..\..\..\build-alpha\lib\libcrypto.a \
+ ..\..\..\build-alpha\lib\libssl.a \
+ ..\..\..\build-alpha\lib\libz.a \
+ ws2_32.lib advapi32.lib shell32.lib
+
+LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \
+ command.obj config.obj connection.obj connection_edge.obj \
+ connection_or.obj control.obj cpuworker.obj directory.obj \
+ dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
+ hibernate.obj main.obj microdesc.obj networkstatus.obj \
+ nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
+ rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
+ rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
+ config_codedigest.obj ntmain.obj
+
+libtor.lib: $(LIBTOR_OBJECTS)
+ lib $(LIBTOR_OBJECTS) /out:libtor.lib
+
+tor.exe: libtor.lib tor_main.obj
+ $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj
+
+clean:
+ del $(LIBTOR_OBJECTS) *.lib tor.exe
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 05163637f2..f4aac0f0e4 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -23,9 +23,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
//#define PARANOIA
@@ -56,6 +53,13 @@
* forever.
*/
+static int parse_socks(const char *data, size_t datalen, socks_request_t *req,
+ int log_sockstype, int safe_socks, ssize_t *drain_out,
+ size_t *want_length_out);
+static int parse_socks_client(const uint8_t *data, size_t datalen,
+ int state, char **reason,
+ ssize_t *drain_out);
+
/* Chunk manipulation functions */
/** A single chunk on a buffer or in a freelist. */
@@ -64,8 +68,8 @@ typedef struct chunk_t {
size_t datalen; /**< The number of bytes stored in this chunk */
size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */
char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */
- char mem[1]; /**< The actual memory used for storage in this chunk. May be
- * more than one byte long. */
+ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in
+ * this chunk. */
} chunk_t;
#define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0])
@@ -547,11 +551,45 @@ buf_free(buf_t *buf)
{
if (!buf)
return;
+
buf_clear(buf);
buf->magic = 0xdeadbeef;
tor_free(buf);
}
+/** Return a new copy of <b>in_chunk</b> */
+static chunk_t *
+chunk_copy(const chunk_t *in_chunk)
+{
+ chunk_t *newch = tor_memdup(in_chunk, CHUNK_ALLOC_SIZE(in_chunk->memlen));
+ newch->next = NULL;
+ if (in_chunk->data) {
+ off_t offset = in_chunk->data - in_chunk->mem;
+ newch->data = newch->mem + offset;
+ }
+ return newch;
+}
+
+/** Return a new copy of <b>buf</b> */
+buf_t *
+buf_copy(const buf_t *buf)
+{
+ chunk_t *ch;
+ buf_t *out = buf_new();
+ out->default_chunk_size = buf->default_chunk_size;
+ for (ch = buf->head; ch; ch = ch->next) {
+ chunk_t *newch = chunk_copy(ch);
+ if (out->tail) {
+ out->tail->next = newch;
+ out->tail = newch;
+ } else {
+ out->head = out->tail = newch;
+ }
+ }
+ out->datalen = buf->datalen;
+ return out;
+}
+
/** Append a new chunk with enough capacity to hold <b>capacity</b> bytes to
* the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger
* than MAX_CHUNK_ALLOC. */
@@ -578,10 +616,6 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
return chunk;
}
-/** If we're using readv and writev, how many chunks are we willing to
- * read/write at a time? */
-#define N_IOV 3
-
/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
* <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
* *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
@@ -591,25 +625,9 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
int *reached_eof, int *socket_error)
{
ssize_t read_result;
-#if 0 && defined(HAVE_READV) && !defined(WIN32)
- struct iovec iov[N_IOV];
- int i;
- size_t remaining = at_most;
- for (i=0; chunk && i < N_IOV && remaining; ++i) {
- iov[i].iov_base = CHUNK_WRITE_PTR(chunk);
- if (remaining > CHUNK_REMAINING_CAPACITY(chunk))
- iov[i].iov_len = CHUNK_REMAINING_CAPACITY(chunk);
- else
- iov[i].iov_len = remaining;
- remaining -= iov[i].iov_len;
- chunk = chunk->next;
- }
- read_result = readv(fd, iov, i);
-#else
if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
at_most = CHUNK_REMAINING_CAPACITY(chunk);
read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
-#endif
if (read_result < 0) {
int e = tor_socket_errno(fd);
@@ -628,14 +646,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
return 0;
} else { /* actually got bytes. */
buf->datalen += read_result;
-#if 0 && defined(HAVE_READV) && !defined(WIN32)
- while ((size_t)read_result > CHUNK_REMAINING_CAPACITY(chunk)) {
- chunk->datalen += CHUNK_REMAINING_CAPACITY(chunk);
- read_result -= CHUNK_REMAINING_CAPACITY(chunk);
- chunk = chunk->next;
- tor_assert(chunk);
- }
-#endif
chunk->datalen += read_result;
log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
(int)buf->datalen);
@@ -771,25 +781,10 @@ flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
size_t *buf_flushlen)
{
ssize_t write_result;
-#if 0 && defined(HAVE_WRITEV) && !defined(WIN32)
- struct iovec iov[N_IOV];
- int i;
- size_t remaining = sz;
- for (i=0; chunk && i < N_IOV && remaining; ++i) {
- iov[i].iov_base = chunk->data;
- if (remaining > chunk->datalen)
- iov[i].iov_len = chunk->datalen;
- else
- iov[i].iov_len = remaining;
- remaining -= iov[i].iov_len;
- chunk = chunk->next;
- }
- write_result = writev(s, iov, i);
-#else
+
if (sz > chunk->datalen)
sz = chunk->datalen;
write_result = tor_socket_send(s, chunk->data, sz, 0);
-#endif
if (write_result < 0) {
int e = tor_socket_errno(s);
@@ -1010,6 +1005,33 @@ fetch_from_buf(char *string, size_t string_len, buf_t *buf)
return (int)buf->datalen;
}
+/** True iff the cell command <b>command</b> is one that implies a
+ * variable-length cell in Tor link protocol <b>linkproto</b>. */
+static inline int
+cell_command_is_var_length(uint8_t command, int linkproto)
+{
+ /* If linkproto is v2 (2), CELL_VERSIONS is the only variable-length cells
+ * work as implemented here. If it's 1, there are no variable-length cells.
+ * Tor does not support other versions right now, and so can't negotiate
+ * them.
+ */
+ switch (linkproto) {
+ case 1:
+ /* Link protocol version 1 has no variable-length cells. */
+ return 0;
+ case 2:
+ /* In link protocol version 2, VERSIONS is the only variable-length cell */
+ return command == CELL_VERSIONS;
+ case 0:
+ case 3:
+ default:
+ /* In link protocol version 3 and later, and in version "unknown",
+ * commands 128 and higher indicate variable-length. VERSIONS is
+ * grandfathered in. */
+ return command == CELL_VERSIONS || command >= 128;
+ }
+}
+
/** Check <b>buf</b> for a variable-length cell according to the rules of link
* protocol version <b>linkproto</b>. If one is found, pull it off the buffer
* and assign a newly allocated var_cell_t to *<b>out</b>, and return 1.
@@ -1024,12 +1046,6 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
var_cell_t *result;
uint8_t command;
uint16_t length;
- /* If linkproto is unknown (0) or v2 (2), variable-length cells work as
- * implemented here. If it's 1, there are no variable-length cells. Tor
- * does not support other versions right now, and so can't negotiate them.
- */
- if (linkproto == 1)
- return 0;
check();
*out = NULL;
if (buf->datalen < VAR_CELL_HEADER_SIZE)
@@ -1037,7 +1053,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
peek_from_buf(hdr, sizeof(hdr), buf);
command = get_uint8(hdr+2);
- if (!(CELL_COMMAND_IS_VAR_LENGTH(command)))
+ if (!(cell_command_is_var_length(command, linkproto)))
return 0;
length = ntohs(get_uint16(hdr+3));
@@ -1056,6 +1072,91 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
return 1;
}
+#ifdef USE_BUFFEREVENTS
+/** Try to read <b>n</b> bytes from <b>buf</b> at <b>pos</b> (which may be
+ * NULL for the start of the buffer), copying the data only if necessary. Set
+ * *<b>data_out</b> to a pointer to the desired bytes. Set <b>free_out</b>
+ * to 1 if we needed to malloc *<b>data</b> because the original bytes were
+ * noncontiguous; 0 otherwise. Return the number of bytes actually available
+ * at *<b>data_out</b>.
+ */
+static ssize_t
+inspect_evbuffer(struct evbuffer *buf, char **data_out, size_t n,
+ int *free_out, struct evbuffer_ptr *pos)
+{
+ int n_vecs, i;
+
+ if (evbuffer_get_length(buf) < n)
+ n = evbuffer_get_length(buf);
+ if (n == 0)
+ return 0;
+ n_vecs = evbuffer_peek(buf, n, pos, NULL, 0);
+ tor_assert(n_vecs > 0);
+ if (n_vecs == 1) {
+ struct evbuffer_iovec v;
+ i = evbuffer_peek(buf, n, pos, &v, 1);
+ tor_assert(i == 1);
+ *data_out = v.iov_base;
+ *free_out = 0;
+ return v.iov_len;
+ } else {
+ ev_ssize_t copied;
+ *data_out = tor_malloc(n);
+ *free_out = 1;
+ copied = evbuffer_copyout(buf, *data_out, n);
+ tor_assert(copied >= 0 && (size_t)copied == n);
+ return copied;
+ }
+}
+
+/** As fetch_var_cell_from_buf, buf works on an evbuffer. */
+int
+fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto)
+{
+ char *hdr = NULL;
+ int free_hdr = 0;
+ size_t n;
+ size_t buf_len;
+ uint8_t command;
+ uint16_t cell_length;
+ var_cell_t *cell;
+ int result = 0;
+
+ *out = NULL;
+ buf_len = evbuffer_get_length(buf);
+ if (buf_len < VAR_CELL_HEADER_SIZE)
+ return 0;
+
+ n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL);
+ tor_assert(n >= VAR_CELL_HEADER_SIZE);
+
+ command = get_uint8(hdr+2);
+ if (!(cell_command_is_var_length(command, linkproto))) {
+ goto done;
+ }
+
+ cell_length = ntohs(get_uint16(hdr+3));
+ if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) {
+ result = 1; /* Not all here yet. */
+ goto done;
+ }
+
+ cell = var_cell_new(cell_length);
+ cell->command = command;
+ cell->circ_id = ntohs(get_uint16(hdr));
+ evbuffer_drain(buf, VAR_CELL_HEADER_SIZE);
+ evbuffer_remove(buf, cell->payload, cell_length);
+ *out = cell;
+ result = 1;
+
+ done:
+ if (free_hdr && hdr)
+ tor_free(hdr);
+ return result;
+}
+#endif
+
/** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to
* <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately.
* Return the number of bytes actually copied.
@@ -1063,8 +1164,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
int
move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
{
- /* XXXX we can do way better here, but this doesn't turn up in any
- * profiles. */
+ /* We can do way better here, but this doesn't turn up in any profiles. */
char b[4096];
size_t cp, len;
len = *buf_flushlen;
@@ -1299,6 +1399,94 @@ fetch_from_buf_http(buf_t *buf,
return 1;
}
+#ifdef USE_BUFFEREVENTS
+/** As fetch_from_buf_http, buf works on an evbuffer. */
+int
+fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete)
+{
+ struct evbuffer_ptr crlf, content_length;
+ size_t headerlen, bodylen, contentlen;
+
+ /* Find the first \r\n\r\n in the buffer */
+ crlf = evbuffer_search(buf, "\r\n\r\n", 4, NULL);
+ if (crlf.pos < 0) {
+ /* We didn't find one. */
+ if (evbuffer_get_length(buf) > max_headerlen)
+ return -1; /* Headers too long. */
+ return 0; /* Headers not here yet. */
+ } else if (crlf.pos > (int)max_headerlen) {
+ return -1; /* Headers too long. */
+ }
+
+ headerlen = crlf.pos + 4; /* Skip over the \r\n\r\n */
+ bodylen = evbuffer_get_length(buf) - headerlen;
+ if (bodylen > max_bodylen)
+ return -1; /* body too long */
+
+ /* Look for the first occurrence of CONTENT_LENGTH insize buf before the
+ * crlfcrlf */
+ content_length = evbuffer_search_range(buf, CONTENT_LENGTH,
+ strlen(CONTENT_LENGTH), NULL, &crlf);
+
+ if (content_length.pos >= 0) {
+ /* We found a content_length: parse it and figure out if the body is here
+ * yet. */
+ struct evbuffer_ptr eol;
+ char *data = NULL;
+ int free_data = 0;
+ int n, i;
+ n = evbuffer_ptr_set(buf, &content_length, strlen(CONTENT_LENGTH),
+ EVBUFFER_PTR_ADD);
+ tor_assert(n == 0);
+ eol = evbuffer_search_eol(buf, &content_length, NULL, EVBUFFER_EOL_CRLF);
+ tor_assert(eol.pos > content_length.pos);
+ tor_assert(eol.pos <= crlf.pos);
+ inspect_evbuffer(buf, &data, eol.pos - content_length.pos, &free_data,
+ &content_length);
+
+ i = atoi(data);
+ if (free_data)
+ tor_free(data);
+ if (i < 0) {
+ log_warn(LD_PROTOCOL, "Content-Length is less than zero; it looks like "
+ "someone is trying to crash us.");
+ return -1;
+ }
+ contentlen = i;
+ /* if content-length is malformed, then our body length is 0. fine. */
+ log_debug(LD_HTTP,"Got a contentlen of %d.",(int)contentlen);
+ if (bodylen < contentlen) {
+ if (!force_complete) {
+ log_debug(LD_HTTP,"body not all here yet.");
+ return 0; /* not all there yet */
+ }
+ }
+ if (bodylen > contentlen) {
+ bodylen = contentlen;
+ log_debug(LD_HTTP,"bodylen reduced to %d.",(int)bodylen);
+ }
+ }
+
+ if (headers_out) {
+ *headers_out = tor_malloc(headerlen+1);
+ evbuffer_remove(buf, *headers_out, headerlen);
+ (*headers_out)[headerlen] = '\0';
+ }
+ if (body_out) {
+ tor_assert(headers_out);
+ tor_assert(body_used);
+ *body_used = bodylen;
+ *body_out = tor_malloc(bodylen+1);
+ evbuffer_remove(buf, *body_out, bodylen);
+ (*body_out)[bodylen] = '\0';
+ }
+ return 1;
+}
+#endif
+
/**
* Wait this many seconds before warning the user about using SOCKS unsafely
* again (requires that WarnUnsafeSocks is turned on). */
@@ -1313,7 +1501,7 @@ log_unsafe_socks_warning(int socks_protocol, const char *address,
{
static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *m = NULL;
if (! options->WarnUnsafeSocks)
return;
@@ -1340,6 +1528,31 @@ log_unsafe_socks_warning(int socks_protocol, const char *address,
* actually significantly higher than the longest possible socks message. */
#define MAX_SOCKS_MESSAGE_LEN 512
+/** Return a new socks_request_t. */
+socks_request_t *
+socks_request_new(void)
+{
+ return tor_malloc_zero(sizeof(socks_request_t));
+}
+
+/** Free all storage held in the socks_request_t <b>req</b>. */
+void
+socks_request_free(socks_request_t *req)
+{
+ if (!req)
+ return;
+ if (req->username) {
+ memset(req->username, 0x10, req->usernamelen);
+ tor_free(req->username);
+ }
+ if (req->password) {
+ memset(req->password, 0x04, req->passwordlen);
+ tor_free(req->password);
+ }
+ memset(req, 0xCC, sizeof(socks_request_t));
+ tor_free(req);
+}
+
/** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
* of the forms
* - socks4: "socksheader username\\0"
@@ -1369,59 +1582,241 @@ int
fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks)
{
+ int res;
+ ssize_t n_drain;
+ size_t want_length = 128;
+
+ if (buf->datalen < 2) /* version and another byte */
+ return 0;
+
+ do {
+ n_drain = 0;
+ buf_pullup(buf, want_length, 0);
+ tor_assert(buf->head && buf->head->datalen >= 2);
+ want_length = 0;
+
+ res = parse_socks(buf->head->data, buf->head->datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (n_drain < 0)
+ buf_clear(buf);
+ else if (n_drain > 0)
+ buf_remove_from_front(buf, n_drain);
+
+ } while (res == 0 && buf->head && want_length < buf->datalen &&
+ buf->datalen >= 2);
+
+ return res;
+}
+
+#ifdef USE_BUFFEREVENTS
+/* As fetch_from_buf_socks(), but targets an evbuffer instead. */
+int
+fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
+ int log_sockstype, int safe_socks)
+{
+ char *data;
+ ssize_t n_drain;
+ size_t datalen, buflen, want_length;
+ int res;
+
+ buflen = evbuffer_get_length(buf);
+ if (buflen < 2)
+ return 0;
+
+ {
+ /* See if we can find the socks request in the first chunk of the buffer.
+ */
+ struct evbuffer_iovec v;
+ int i;
+ n_drain = 0;
+ i = evbuffer_peek(buf, -1, NULL, &v, 1);
+ tor_assert(i == 1);
+ data = v.iov_base;
+ datalen = v.iov_len;
+ want_length = 0;
+
+ res = parse_socks(data, datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (n_drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+ else if (n_drain > 0)
+ evbuffer_drain(buf, n_drain);
+
+ if (res)
+ return res;
+ }
+
+ /* Okay, the first chunk of the buffer didn't have a complete socks request.
+ * That means that either we don't have a whole socks request at all, or
+ * it's gotten split up. We're going to try passing parse_socks() bigger
+ * and bigger chunks until either it says "Okay, I got it", or it says it
+ * will need more data than we currently have. */
+
+ /* Loop while we have more data that we haven't given parse_socks() yet. */
+ do {
+ int free_data = 0;
+ const size_t last_wanted = want_length;
+ n_drain = 0;
+ data = NULL;
+ datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL);
+
+ want_length = 0;
+ res = parse_socks(data, datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (free_data)
+ tor_free(data);
+
+ if (n_drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+ else if (n_drain > 0)
+ evbuffer_drain(buf, n_drain);
+
+ if (res == 0 && n_drain == 0 && want_length <= last_wanted) {
+ /* If we drained nothing, and we didn't ask for more than last time,
+ * then we probably wanted more data than the buffer actually had,
+ * and we're finding out that we're not satisified with it. It's
+ * time to break until we have more data. */
+ break;
+ }
+
+ buflen = evbuffer_get_length(buf);
+ } while (res == 0 && want_length <= buflen && buflen >= 2);
+
+ return res;
+}
+#endif
+
+/** Implementation helper to implement fetch_from_*_socks. Instead of looking
+ * at a buffer's contents, we look at the <b>datalen</b> bytes of data in
+ * <b>data</b>. Instead of removing data from the buffer, we set
+ * <b>drain_out</b> to the amount of data that should be removed (or -1 if the
+ * buffer should be cleared). Instead of pulling more data into the first
+ * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes
+ * we'd like to see in the input buffer, if they're available. */
+static int
+parse_socks(const char *data, size_t datalen, socks_request_t *req,
+ int log_sockstype, int safe_socks, ssize_t *drain_out,
+ size_t *want_length_out)
+{
unsigned int len;
char tmpbuf[TOR_ADDR_BUF_LEN+1];
tor_addr_t destaddr;
uint32_t destip;
uint8_t socksver;
- enum {socks4, socks4a} socks4_prot = socks4a;
char *next, *startaddr;
+ unsigned char usernamelen, passlen;
struct in_addr in;
- if (buf->datalen < 2) /* version and another byte */
+ if (datalen < 2) {
+ /* We always need at least 2 bytes. */
+ *want_length_out = 2;
return 0;
+ }
- buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
- tor_assert(buf->head && buf->head->datalen >= 2);
+ if (req->socks_version == 5 && !req->got_auth) {
+ /* See if we have received authentication. Strictly speaking, we should
+ also check whether we actually negotiated username/password
+ authentication. But some broken clients will send us authentication
+ even if we negotiated SOCKS_NO_AUTH. */
+ if (*data == 1) { /* username/pass version 1 */
+ /* Format is: authversion [1 byte] == 1
+ usernamelen [1 byte]
+ username [usernamelen bytes]
+ passlen [1 byte]
+ password [passlen bytes] */
+ usernamelen = (unsigned char)*(data + 1);
+ if (datalen < 2u + usernamelen + 1u) {
+ *want_length_out = 2u + usernamelen + 1u;
+ return 0;
+ }
+ passlen = (unsigned char)*(data + 2u + usernamelen);
+ if (datalen < 2u + usernamelen + 1u + passlen) {
+ *want_length_out = 2u + usernamelen + 1u + passlen;
+ return 0;
+ }
+ req->replylen = 2; /* 2 bytes of response */
+ req->reply[0] = 5;
+ req->reply[1] = 0; /* authentication successful */
+ log_debug(LD_APP,
+ "socks5: Accepted username/password without checking.");
+ if (usernamelen) {
+ req->username = tor_memdup(data+2u, usernamelen);
+ req->usernamelen = usernamelen;
+ }
+ if (passlen) {
+ req->password = tor_memdup(data+3u+usernamelen, passlen);
+ req->passwordlen = passlen;
+ }
+ *drain_out = 2u + usernamelen + 1u + passlen;
+ req->got_auth = 1;
+ *want_length_out = 7; /* Minimal socks5 sommand. */
+ return 0;
+ } else if (req->auth_type == SOCKS_USER_PASS) {
+ /* unknown version byte */
+ log_warn(LD_APP, "Socks5 username/password version %d not recognized; "
+ "rejecting.", (int)*data);
+ return -1;
+ }
+ }
- socksver = *buf->head->data;
+ socksver = *data;
switch (socksver) { /* which version of socks? */
-
case 5: /* socks5 */
if (req->socks_version != 5) { /* we need to negotiate a method */
- unsigned char nummethods = (unsigned char)*(buf->head->data+1);
+ unsigned char nummethods = (unsigned char)*(data+1);
+ int r=0;
tor_assert(!req->socks_version);
- if (buf->datalen < 2u+nummethods)
+ if (datalen < 2u+nummethods) {
+ *want_length_out = 2u+nummethods;
return 0;
- buf_pullup(buf, 2u+nummethods, 0);
- if (!nummethods || !memchr(buf->head->data+2, 0, nummethods)) {
+ }
+ if (!nummethods)
+ return -1;
+ req->replylen = 2; /* 2 bytes of response */
+ req->reply[0] = 5; /* socks5 reply */
+ if (memchr(data+2, SOCKS_NO_AUTH, nummethods)) {
+ req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth
+ method */
+ req->socks_version = 5; /* remember we've already negotiated auth */
+ log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
+ r=0;
+ } else if (memchr(data+2, SOCKS_USER_PASS, nummethods)) {
+ req->auth_type = SOCKS_USER_PASS;
+ req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass"
+ auth method */
+ req->socks_version = 5; /* remember we've already negotiated auth */
+ log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
+ r=0;
+ } else {
log_warn(LD_APP,
- "socks5: offered methods don't include 'no auth'. "
- "Rejecting.");
- req->replylen = 2; /* 2 bytes of response */
- req->reply[0] = 5;
+ "socks5: offered methods don't include 'no auth' or "
+ "username/password. Rejecting.");
req->reply[1] = '\xFF'; /* reject all methods */
- return -1;
+ r=-1;
}
- /* remove packet from buf. also remove any other extraneous
- * bytes, to support broken socks clients. */
- buf_clear(buf);
+ /* Remove packet from buf. Some SOCKS clients will have sent extra
+ * junk at this point; let's hope it's an authentication message. */
+ *drain_out = 2u + nummethods;
- req->replylen = 2; /* 2 bytes of response */
- req->reply[0] = 5; /* socks5 reply */
- req->reply[1] = 0; /* tell client to use "none" auth method */
- req->socks_version = 5; /* remember we've already negotiated auth */
- log_debug(LD_APP,"socks5: accepted method 0");
- return 0;
+ return r;
+ }
+ if (req->auth_type != SOCKS_NO_AUTH && !req->got_auth) {
+ log_warn(LD_APP,
+ "socks5: negotiated authentication, but none provided");
+ return -1;
}
/* we know the method; read in the request */
log_debug(LD_APP,"socks5: checking request");
- if (buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */
+ if (datalen < 7) {/* basic info plus >=1 for addr plus 2 for port */
+ *want_length_out = 7;
return 0; /* not yet */
- tor_assert(buf->head->datalen >= 8);
- req->command = (unsigned char) *(buf->head->data+1);
+ }
+ req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE &&
req->command != SOCKS_COMMAND_RESOLVE_PTR) {
@@ -1430,19 +1825,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->command);
return -1;
}
- switch (*(buf->head->data+3)) { /* address type */
+ switch (*(data+3)) { /* address type */
case 1: /* IPv4 address */
case 4: /* IPv6 address */ {
- const int is_v6 = *(buf->head->data+3) == 4;
+ const int is_v6 = *(data+3) == 4;
const unsigned addrlen = is_v6 ? 16 : 4;
log_debug(LD_APP,"socks5: ipv4 address type");
- if (buf->datalen < 6+addrlen) /* ip/port there? */
+ if (datalen < 6+addrlen) {/* ip/port there? */
+ *want_length_out = 6+addrlen;
return 0; /* not yet */
+ }
if (is_v6)
- tor_addr_from_ipv6_bytes(&destaddr, buf->head->data+4);
+ tor_addr_from_ipv6_bytes(&destaddr, data+4);
else
- tor_addr_from_ipv4n(&destaddr, get_uint32(buf->head->data+4));
+ tor_addr_from_ipv4n(&destaddr, get_uint32(data+4));
tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
@@ -1454,8 +1851,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
strlcpy(req->address,tmpbuf,sizeof(req->address));
- req->port = ntohs(get_uint16(buf->head->data+4+addrlen));
- buf_remove_from_front(buf, 6+addrlen);
+ req->port = ntohs(get_uint16(data+4+addrlen));
+ *drain_out = 6+addrlen;
if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
!addressmap_have_mapping(req->address,0)) {
log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
@@ -1471,21 +1868,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
"hostname type. Rejecting.");
return -1;
}
- len = (unsigned char)*(buf->head->data+4);
- if (buf->datalen < 7+len) /* addr/port there? */
+ len = (unsigned char)*(data+4);
+ if (datalen < 7+len) { /* addr/port there? */
+ *want_length_out = 7+len;
return 0; /* not yet */
- buf_pullup(buf, 7+len, 0);
- tor_assert(buf->head->datalen >= 7+len);
+ }
if (len+1 > MAX_SOCKS_ADDR_LEN) {
log_warn(LD_APP,
"socks5 hostname is %d bytes, which doesn't fit in "
"%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN);
return -1;
}
- memcpy(req->address,buf->head->data+5,len);
+ memcpy(req->address,data+5,len);
req->address[len] = 0;
- req->port = ntohs(get_uint16(buf->head->data+5+len));
- buf_remove_from_front(buf, 5+len+2);
+ req->port = ntohs(get_uint16(data+5+len));
+ *drain_out = 5+len+2;
if (!tor_strisprint(req->address) || strchr(req->address,'\"')) {
log_warn(LD_PROTOCOL,
"Your application (using socks5 to port %d) gave Tor "
@@ -1495,25 +1892,29 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
}
if (log_sockstype)
log_notice(LD_APP,
- "Your application (using socks5 to port %d) gave "
- "Tor a hostname, which means Tor will do the DNS resolve "
- "for you. This is good.", req->port);
+ "Your application (using socks5 to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
return 1;
default: /* unsupported */
log_warn(LD_APP,"socks5: unsupported address type %d. Rejecting.",
- (int) *(buf->head->data+3));
+ (int) *(data+3));
return -1;
}
tor_assert(0);
- case 4: /* socks4 */
- /* http://archive.socks.permeo.com/protocol/socks4.protocol */
- /* http://archive.socks.permeo.com/protocol/socks4a.protocol */
+ case 4: { /* socks4 */
+ enum {socks4, socks4a} socks4_prot = socks4a;
+ const char *authstart, *authend;
+ /* http://ss5.sourceforge.net/socks4.protocol.txt */
+ /* http://ss5.sourceforge.net/socks4A.protocol.txt */
req->socks_version = 4;
- if (buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */
+ if (datalen < SOCKS4_NETWORK_LEN) {/* basic info available? */
+ *want_length_out = SOCKS4_NETWORK_LEN;
return 0; /* not yet */
- buf_pullup(buf, 1280, 0);
- req->command = (unsigned char) *(buf->head->data+1);
+ }
+ // buf_pullup(buf, 1280, 0);
+ req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE) {
/* not a connect or resolve? we don't support it. (No resolve_ptr with
@@ -1523,8 +1924,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
- req->port = ntohs(get_uint16(buf->head->data+2));
- destip = ntohl(get_uint32(buf->head->data+4));
+ req->port = ntohs(get_uint16(data+2));
+ destip = ntohl(get_uint32(data+4));
if ((!req->port && req->command!=SOCKS_COMMAND_RESOLVE) || !destip) {
log_warn(LD_APP,"socks4: Port or DestIP is zero. Rejecting.");
return -1;
@@ -1544,17 +1945,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
socks4_prot = socks4;
}
- next = memchr(buf->head->data+SOCKS4_NETWORK_LEN, 0,
- buf->head->datalen-SOCKS4_NETWORK_LEN);
+ authstart = data + SOCKS4_NETWORK_LEN;
+ next = memchr(authstart, 0,
+ datalen-SOCKS4_NETWORK_LEN);
if (!next) {
- if (buf->head->datalen >= 1024) {
+ if (datalen >= 1024) {
log_debug(LD_APP, "Socks4 user name too long; rejecting.");
return -1;
}
log_debug(LD_APP,"socks4: Username not here yet.");
+ *want_length_out = datalen+1024; /* More than we need, but safe */
return 0;
}
- tor_assert(next < CHUNK_WRITE_PTR(buf->head));
+ authend = next;
+ tor_assert(next < data+datalen);
startaddr = NULL;
if (socks4_prot != socks4a &&
@@ -1565,18 +1969,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
if (socks4_prot == socks4a) {
- if (next+1 == CHUNK_WRITE_PTR(buf->head)) {
+ if (next+1 == data+datalen) {
log_debug(LD_APP,"socks4: No part of destaddr here yet.");
+ *want_length_out = datalen + 1024; /* More than we need, but safe */
return 0;
}
startaddr = next+1;
- next = memchr(startaddr, 0, CHUNK_WRITE_PTR(buf->head)-startaddr);
+ next = memchr(startaddr, 0, data + datalen - startaddr);
if (!next) {
- if (buf->head->datalen >= 1024) {
+ if (datalen >= 1024) {
log_debug(LD_APP,"socks4: Destaddr too long.");
return -1;
}
log_debug(LD_APP,"socks4: Destaddr not all here yet.");
+ *want_length_out = datalen + 1024; /* More than we need, but safe */
return 0;
}
if (MAX_SOCKS_ADDR_LEN <= next-startaddr) {
@@ -1587,9 +1993,9 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
if (log_sockstype)
log_notice(LD_APP,
- "Your application (using socks4a to port %d) gave "
- "Tor a hostname, which means Tor will do the DNS resolve "
- "for you. This is good.", req->port);
+ "Your application (using socks4a to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
}
log_debug(LD_APP,"socks4: Everything is here. Success.");
strlcpy(req->address, startaddr ? startaddr : tmpbuf,
@@ -1601,15 +2007,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->port, escaped(req->address));
return -1;
}
+ if (authend != authstart) {
+ req->got_auth = 1;
+ req->usernamelen = authend - authstart;
+ req->username = tor_memdup(authstart, authend - authstart);
+ }
/* next points to the final \0 on inbuf */
- buf_remove_from_front(buf, next - buf->head->data + 1);
+ *drain_out = next - data + 1;
return 1;
-
+ }
case 'G': /* get */
case 'H': /* head */
case 'P': /* put/post */
case 'C': /* connect */
- strlcpy(req->reply,
+ strlcpy((char*)req->reply,
"HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
"<html>\n"
@@ -1635,14 +2046,15 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
"</body>\n"
"</html>\n"
, MAX_SOCKS_REPLY_LEN);
- req->replylen = strlen(req->reply)+1;
+ req->replylen = strlen((char*)req->reply)+1;
/* fall through */
default: /* version is not socks4 or socks5 */
log_warn(LD_APP,
"Socks version %d not recognized. (Tor is not an http proxy.)",
- *(buf->head->data));
+ *(data));
{
- char *tmp = tor_strndup(buf->head->data, 8); /*XXXX what if longer?*/
+ /* Tell the controller the first 8 bytes. */
+ char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
control_event_client_status(LOG_WARN,
"SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
escaped(tmp));
@@ -1664,21 +2076,67 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int
fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
{
- unsigned char *data;
- size_t addrlen;
-
+ ssize_t drain = 0;
+ int r;
if (buf->datalen < 2)
return 0;
buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
tor_assert(buf->head && buf->head->datalen >= 2);
- data = (unsigned char *) buf->head->data;
+ r = parse_socks_client((uint8_t*)buf->head->data, buf->head->datalen,
+ state, reason, &drain);
+ if (drain > 0)
+ buf_remove_from_front(buf, drain);
+ else if (drain < 0)
+ buf_clear(buf);
+
+ return r;
+}
+
+#ifdef USE_BUFFEREVENTS
+/** As fetch_from_buf_socks_client, buf works on an evbuffer */
+int
+fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
+ char **reason)
+{
+ ssize_t drain = 0;
+ uint8_t *data;
+ size_t datalen;
+ int r;
+
+ /* Linearize the SOCKS response in the buffer, up to 128 bytes.
+ * (parse_socks_client shouldn't need to see anything beyond that.) */
+ datalen = evbuffer_get_length(buf);
+ if (datalen > MAX_SOCKS_MESSAGE_LEN)
+ datalen = MAX_SOCKS_MESSAGE_LEN;
+ data = evbuffer_pullup(buf, datalen);
+
+ r = parse_socks_client(data, datalen, state, reason, &drain);
+ if (drain > 0)
+ evbuffer_drain(buf, drain);
+ else if (drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+
+ return r;
+}
+#endif
+
+/** Implementation logic for fetch_from_*_socks_client. */
+static int
+parse_socks_client(const uint8_t *data, size_t datalen,
+ int state, char **reason,
+ ssize_t *drain_out)
+{
+ unsigned int addrlen;
+ *drain_out = 0;
+ if (datalen < 2)
+ return 0;
switch (state) {
case PROXY_SOCKS4_WANT_CONNECT_OK:
/* Wait for the complete response */
- if (buf->head->datalen < 8)
+ if (datalen < 8)
return 0;
if (data[1] != 0x5a) {
@@ -1687,7 +2145,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
/* Success */
- buf_remove_from_front(buf, 8);
+ *drain_out = 8;
return 1;
case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
@@ -1699,7 +2157,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
@@ -1709,11 +2167,11 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
case 0x00:
log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
"doesn't require authentication.");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case 0x02:
log_info(LD_NET, "SOCKS 5 client: need authentication.");
- buf_clear(buf);
+ *drain_out = -1;
return 2;
/* fall through */
}
@@ -1730,7 +2188,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
log_info(LD_NET, "SOCKS 5 client: authentication successful.");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case PROXY_SOCKS5_WANT_CONNECT_OK:
@@ -1739,7 +2197,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
* the data used */
/* wait for address type field to arrive */
- if (buf->datalen < 4)
+ if (datalen < 4)
return 0;
switch (data[3]) {
@@ -1750,7 +2208,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
addrlen = 16;
break;
case 0x03: /* fqdn (can this happen here?) */
- if (buf->datalen < 5)
+ if (datalen < 5)
return 0;
addrlen = 1 + data[4];
break;
@@ -1760,7 +2218,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
/* wait for address and port */
- if (buf->datalen < 6 + addrlen)
+ if (datalen < 6 + addrlen)
return 0;
if (data[1] != 0x00) {
@@ -1768,7 +2226,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
return -1;
}
- buf_remove_from_front(buf, 6 + addrlen);
+ *drain_out = 6 + addrlen;
return 1;
}
@@ -1794,6 +2252,27 @@ peek_buf_has_control0_command(buf_t *buf)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+int
+peek_evbuffer_has_control0_command(struct evbuffer *buf)
+{
+ int result = 0;
+ if (evbuffer_get_length(buf) >= 4) {
+ int free_out = 0;
+ char *data = NULL;
+ size_t n = inspect_evbuffer(buf, &data, 4, &free_out, NULL);
+ uint16_t cmd;
+ tor_assert(n >= 4);
+ cmd = ntohs(get_uint16(data+2));
+ if (cmd <= 0x14)
+ result = 1;
+ if (free_out)
+ tor_free(data);
+ }
+ return result;
+}
+#endif
+
/** Return the index within <b>buf</b> at which <b>ch</b> first appears,
* or -1 if <b>ch</b> does not appear on buf. */
static off_t
@@ -1811,12 +2290,12 @@ buf_find_offset_of_char(buf_t *buf, char ch)
return -1;
}
-/** Try to read a single LF-terminated line from <b>buf</b>, and write it,
- * NUL-terminated, into the *<b>data_len</b> byte buffer at <b>data_out</b>.
- * Set *<b>data_len</b> to the number of bytes in the line, not counting the
- * terminating NUL. Return 1 if we read a whole line, return 0 if we don't
- * have a whole line yet, and return -1 if the line length exceeds
- * *<b>data_len</b>.
+/** Try to read a single LF-terminated line from <b>buf</b>, and write it
+ * (including the LF), NUL-terminated, into the *<b>data_len</b> byte buffer
+ * at <b>data_out</b>. Set *<b>data_len</b> to the number of bytes in the
+ * line, not counting the terminating NUL. Return 1 if we read a whole line,
+ * return 0 if we don't have a whole line yet, and return -1 if the line
+ * length exceeds *<b>data_len</b>.
*/
int
fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
@@ -1890,6 +2369,96 @@ write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
return 0;
}
+#ifdef USE_BUFFEREVENTS
+int
+write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+ const char *data, size_t data_len,
+ int done)
+{
+ char *next;
+ size_t old_avail, avail;
+ int over = 0, n;
+ struct evbuffer_iovec vec[1];
+ do {
+ {
+ size_t cap = data_len / 4;
+ if (cap < 128)
+ cap = 128;
+ /* XXXX NM this strategy is fragmentation-prone. We should really have
+ * two iovecs, and write first into the one, and then into the
+ * second if the first gets full. */
+ n = evbuffer_reserve_space(buf, cap, vec, 1);
+ tor_assert(n == 1);
+ }
+
+ next = vec[0].iov_base;
+ avail = old_avail = vec[0].iov_len;
+
+ switch (tor_zlib_process(state, &next, &avail, &data, &data_len, done)) {
+ case TOR_ZLIB_DONE:
+ over = 1;
+ break;
+ case TOR_ZLIB_ERR:
+ return -1;
+ case TOR_ZLIB_OK:
+ if (data_len == 0)
+ over = 1;
+ break;
+ case TOR_ZLIB_BUF_FULL:
+ if (avail) {
+ /* Zlib says we need more room (ZLIB_BUF_FULL). Start a new chunk
+ * automatically, whether were going to or not. */
+ }
+ break;
+ }
+
+ /* XXXX possible infinite loop on BUF_FULL. */
+ vec[0].iov_len = old_avail - avail;
+ evbuffer_commit_space(buf, vec, 1);
+
+ } while (!over);
+ check();
+ return 0;
+}
+#endif
+
+/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */
+int
+generic_buffer_set_to_copy(generic_buffer_t **output,
+ const generic_buffer_t *input)
+{
+#ifdef USE_BUFFEREVENTS
+ struct evbuffer_ptr ptr;
+ size_t remaining = evbuffer_get_length(input);
+ if (*output) {
+ evbuffer_drain(*output, evbuffer_get_length(*output));
+ } else {
+ if (!(*output = evbuffer_new()))
+ return -1;
+ }
+ evbuffer_ptr_set((struct evbuffer*)input, &ptr, 0, EVBUFFER_PTR_SET);
+ while (remaining) {
+ struct evbuffer_iovec v[4];
+ int n_used, i;
+ n_used = evbuffer_peek((struct evbuffer*)input, -1, &ptr, v, 4);
+ if (n_used < 0)
+ return -1;
+ for (i=0;i<n_used;++i) {
+ evbuffer_add(*output, v[i].iov_base, v[i].iov_len);
+ tor_assert(v[i].iov_len <= remaining);
+ remaining -= v[i].iov_len;
+ evbuffer_ptr_set((struct evbuffer*)input,
+ &ptr, v[i].iov_len, EVBUFFER_PTR_ADD);
+ }
+ }
+#else
+ if (*output)
+ buf_free(*output);
+ *output = buf_copy(input);
+#endif
+ return 0;
+}
+
/** Log an error and exit if <b>buf</b> is corrupted.
*/
void
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 63fab4957a..7b2a2acc3c 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -16,6 +16,7 @@ buf_t *buf_new(void);
buf_t *buf_new_with_capacity(size_t size);
void buf_free(buf_t *buf);
void buf_clear(buf_t *buf);
+buf_t *buf_copy(const buf_t *buf);
void buf_shrink(buf_t *buf);
void buf_shrink_freelists(int free_all);
void buf_dump_freelist_sizes(int severity);
@@ -41,6 +42,8 @@ int fetch_from_buf_http(buf_t *buf,
char **headers_out, size_t max_headerlen,
char **body_out, size_t *body_used, size_t max_bodylen,
int force_complete);
+socks_request_t *socks_request_new(void);
+void socks_request_free(socks_request_t *req);
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks);
int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason);
@@ -48,6 +51,41 @@ int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
int peek_buf_has_control0_command(buf_t *buf);
+#ifdef USE_BUFFEREVENTS
+int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto);
+int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
+ int log_sockstype, int safe_socks);
+int fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
+ char **reason);
+int fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete);
+int peek_evbuffer_has_control0_command(struct evbuffer *buf);
+int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+ const char *data, size_t data_len,
+ int done);
+#endif
+
+#ifdef USE_BUFFEREVENTS
+#define generic_buffer_new() evbuffer_new()
+#define generic_buffer_len(b) evbuffer_get_length((b))
+#define generic_buffer_add(b,dat,len) evbuffer_add((b),(dat),(len))
+#define generic_buffer_get(b,buf,buflen) evbuffer_remove((b),(buf),(buflen))
+#define generic_buffer_clear(b) evbuffer_drain((b), evbuffer_get_length((b)))
+#define generic_buffer_free(b) evbuffer_free((b))
+#else
+#define generic_buffer_new() buf_new()
+#define generic_buffer_len(b) buf_datalen((b))
+#define generic_buffer_add(b,dat,len) write_to_buf((dat),(len),(b))
+#define generic_buffer_get(b,buf,buflen) fetch_from_buf((buf),(buflen),(b))
+#define generic_buffer_clear(b) buf_clear((b))
+#define generic_buffer_free(b) buf_free((b))
+#endif
+int generic_buffer_set_to_copy(generic_buffer_t **output,
+ const generic_buffer_t *input);
+
void assert_buf_ok(buf_t *buf);
#ifdef BUFFERS_PRIVATE
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index c6be46d858..b04bd10120 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -23,8 +23,10 @@
#include "directory.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "policies.h"
+#include "transports.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
@@ -55,8 +57,8 @@ extern circuit_t *global_circuitlist;
/** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just
- * use a routerinfo_t, since we want to remember these even when we
- * don't have a directory. */
+ * use a node_t, since we want to remember these even when we
+ * don't have any directory info. */
typedef struct {
char nickname[MAX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
@@ -78,6 +80,28 @@ typedef struct {
* at which we last failed to connect to it. */
} entry_guard_t;
+/** Information about a configured bridge. Currently this just matches the
+ * ones in the torrc file, but one day we may be able to learn about new
+ * bridges on our own, and remember them in the state file. */
+typedef struct {
+ /** Address of the bridge. */
+ tor_addr_t addr;
+ /** TLS port for the bridge. */
+ uint16_t port;
+ /** Boolean: We are re-parsing our bridge list, and we are going to remove
+ * this one if we don't find it in the list of configured bridges. */
+ unsigned marked_for_removal : 1;
+ /** Expected identity digest, or all zero bytes if we don't know what the
+ * digest should be. */
+ char identity[DIGEST_LEN];
+
+ /** Name of pluggable transport protocol taken from its config line. */
+ char *transport_name;
+
+ /** When should we next try to fetch a descriptor for this bridge? */
+ download_status_t fetch_status;
+} bridge_info_t;
+
/** A list of our chosen entry guards. */
static smartlist_t *entry_guards = NULL;
/** A value of 1 means that the entry_guards list has changed
@@ -95,11 +119,13 @@ static int circuit_deliver_create_cell(circuit_t *circ,
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
-static int count_acceptable_routers(smartlist_t *routers);
+static int count_acceptable_nodes(smartlist_t *routers);
static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static void entry_guards_changed(void);
+static void bridge_free(bridge_info_t *bridge);
+
/**
* This function decides if CBT learning should be disabled. It returns
* true if one or more of the following four conditions are met:
@@ -1381,7 +1407,7 @@ circuit_build_times_set_timeout_worker(circuit_build_times_t *cbt)
cbt->close_ms = MAX(cbt->close_ms, circuit_build_times_initial_timeout());
if (cbt->timeout_ms > max_time) {
- log_notice(LD_CIRC,
+ log_info(LD_CIRC,
"Circuit build timeout of %dms is beyond the maximum build "
"time we have ever observed. Capping it to %dms.",
(int)cbt->timeout_ms, max_time);
@@ -1429,7 +1455,7 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
timeout_rate = circuit_build_times_timeout_rate(cbt);
if (prev_timeout > tor_lround(cbt->timeout_ms/1000)) {
- log_notice(LD_CIRC,
+ log_info(LD_CIRC,
"Based on %d circuit times, it looks like we don't need to "
"wait so long for circuits to finish. We will now assume a "
"circuit is too slow to use after waiting %ld seconds.",
@@ -1440,7 +1466,7 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha,
timeout_rate);
} else if (prev_timeout < tor_lround(cbt->timeout_ms/1000)) {
- log_notice(LD_CIRC,
+ log_info(LD_CIRC,
"Based on %d circuit times, it looks like we need to wait "
"longer for circuits to finish. We will now assume a "
"circuit is too slow to use after waiting %ld seconds.",
@@ -1532,10 +1558,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
hop = circ->cpath;
do {
- routerinfo_t *ri;
- routerstatus_t *rs;
char *elt;
const char *id;
+ const node_t *node;
if (!hop)
break;
if (!verbose && hop->state != CPATH_STATE_OPEN)
@@ -1545,10 +1570,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
id = hop->extend_info->identity_digest;
if (verbose_names) {
elt = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1);
- if ((ri = router_get_by_digest(id))) {
- router_get_verbose_nickname(elt, ri);
- } else if ((rs = router_get_consensus_status_by_id(id))) {
- routerstatus_get_verbose_nickname(elt, rs);
+ if ((node = node_get_by_id(id))) {
+ node_get_verbose_nickname(node, elt);
} else if (is_legal_nickname(hop->extend_info->nickname)) {
elt[0] = '$';
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
@@ -1560,9 +1583,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
}
} else { /* ! verbose_names */
- if ((ri = router_get_by_digest(id)) &&
- ri->is_named) {
- elt = tor_strdup(hop->extend_info->nickname);
+ node = node_get_by_id(id);
+ if (node && node_is_named(node)) {
+ elt = tor_strdup(node_get_nickname(node));
} else {
elt = tor_malloc(HEX_DIGEST_LEN+2);
elt[0] = '$';
@@ -1631,31 +1654,28 @@ void
circuit_rep_hist_note_result(origin_circuit_t *circ)
{
crypt_path_t *hop;
- char *prev_digest = NULL;
- routerinfo_t *router;
+ const char *prev_digest = NULL;
hop = circ->cpath;
if (!hop) /* circuit hasn't started building yet. */
return;
if (server_mode(get_options())) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return;
prev_digest = me->cache_info.identity_digest;
}
do {
- router = router_get_by_digest(hop->extend_info->identity_digest);
- if (router) {
+ const node_t *node = node_get_by_id(hop->extend_info->identity_digest);
+ if (node) { /* Why do we check this? We know the identity. -NM XXXX */
if (prev_digest) {
if (hop->state == CPATH_STATE_OPEN)
- rep_hist_note_extend_succeeded(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_succeeded(prev_digest, node->identity);
else {
- rep_hist_note_extend_failed(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_failed(prev_digest, node->identity);
break;
}
}
- prev_digest = router->cache_info.identity_digest;
+ prev_digest = node->identity;
} else {
prev_digest = NULL;
}
@@ -1924,7 +1944,7 @@ int
inform_testing_reachability(void)
{
char dirbuf[128];
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
control_event_server_status(LOG_NOTICE,
@@ -1953,7 +1973,7 @@ inform_testing_reachability(void)
static INLINE int
should_use_create_fast_for_circuit(origin_circuit_t *circ)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
@@ -1961,9 +1981,10 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ)
return 1; /* our hand is forced: only a create_fast will work. */
if (!options->FastFirstHopPK)
return 0; /* we prefer to avoid create_fast */
- if (server_mode(options)) {
+ if (public_server_mode(options)) {
/* We're a server, and we know an onion key. We can choose.
- * Prefer to blend in. */
+ * Prefer to blend our circuit into the other circuits we are
+ * creating on behalf of others. */
return 0;
}
@@ -1996,7 +2017,7 @@ int
circuit_send_next_onion_skin(origin_circuit_t *circ)
{
crypt_path_t *hop;
- routerinfo_t *router;
+ const node_t *node;
char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
char *onionskin;
size_t payload_len;
@@ -2012,7 +2033,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
else
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
- router = router_get_by_digest(circ->_base.n_conn->identity_digest);
+ node = node_get_by_id(circ->_base.n_conn->identity_digest);
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We are an OR and we know the right onion key: we should
@@ -2046,7 +2067,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
fast ? "CREATE_FAST" : "CREATE",
- router ? router_describe(router) : "<unnamed>");
+ node ? node_describe(node) : "<unnamed>");
} else {
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
@@ -2088,7 +2109,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
if (circ->build_state->onehop_tunnel)
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0);
if (!can_complete_circuit && !circ->build_state->onehop_tunnel) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
can_complete_circuit=1;
/* FFFF Log a count of known routers here */
log_notice(LD_GENERAL,
@@ -2096,6 +2117,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
"Looks like client functionality is working.");
control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0);
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
+ clear_broken_connection_map(1);
if (server_mode(options) && !check_whether_orport_reachable()) {
inform_testing_reachability();
consider_testing_reachability(1, 1);
@@ -2523,12 +2545,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
*/
static int
new_route_len(uint8_t purpose, extend_info_t *exit,
- smartlist_t *routers)
+ smartlist_t *nodes)
{
int num_acceptable_routers;
int routelen;
- tor_assert(routers);
+ tor_assert(nodes);
routelen = DEFAULT_ROUTE_LEN;
if (exit &&
@@ -2536,10 +2558,10 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
routelen++;
- num_acceptable_routers = count_acceptable_routers(routers);
+ num_acceptable_routers = count_acceptable_nodes(nodes);
log_debug(LD_CIRC,"Chosen route length %d (%d/%d routers suitable).",
- routelen, num_acceptable_routers, smartlist_len(routers));
+ routelen, num_acceptable_routers, smartlist_len(nodes));
if (num_acceptable_routers < 2) {
log_info(LD_CIRC,
@@ -2557,24 +2579,12 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
return routelen;
}
-/** Fetch the list of predicted ports, dup it into a smartlist of
- * uint16_t's, remove the ones that are already handled by an
- * existing circuit, and return it.
- */
+/** Return a newly allocated list of uint16_t * for each predicted port not
+ * handled by a current circuit. */
static smartlist_t *
circuit_get_unhandled_ports(time_t now)
{
- smartlist_t *source = rep_hist_get_predicted_ports(now);
- smartlist_t *dest = smartlist_create();
- uint16_t *tmp;
- int i;
-
- for (i = 0; i < smartlist_len(source); ++i) {
- tmp = tor_malloc(sizeof(uint16_t));
- memcpy(tmp, smartlist_get(source, i), sizeof(uint16_t));
- smartlist_add(dest, tmp);
- }
-
+ smartlist_t *dest = rep_hist_get_predicted_ports(now);
circuit_remove_handled_ports(dest);
return dest;
}
@@ -2608,12 +2618,12 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
return enough;
}
-/** Return 1 if <b>router</b> can handle one or more of the ports in
+/** Return 1 if <b>node</b> can handle one or more of the ports in
* <b>needed_ports</b>, else return 0.
*/
static int
-router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
-{
+node_handles_some_port(const node_t *node, smartlist_t *needed_ports)
+{ /* XXXX MOVE */
int i;
uint16_t port;
@@ -2623,7 +2633,10 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
needed_ports is explicitly a smartlist of uint16_t's */
port = *(uint16_t *)smartlist_get(needed_ports, i);
tor_assert(port);
- r = compare_addr_to_addr_policy(0, port, router->exit_policy);
+ if (node)
+ r = compare_tor_addr_to_node_policy(NULL, port, node);
+ else
+ continue;
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 1;
}
@@ -2635,14 +2648,18 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
static int
ap_stream_wants_exit_attention(connection_t *conn)
{
- if (conn->type == CONN_TYPE_AP &&
- conn->state == AP_CONN_STATE_CIRCUIT_WAIT &&
+ entry_connection_t *entry;
+ if (conn->type != CONN_TYPE_AP)
+ return 0;
+ entry = TO_ENTRY_CONN(conn);
+
+ if (conn->state == AP_CONN_STATE_CIRCUIT_WAIT &&
!conn->marked_for_close &&
- !(TO_EDGE_CONN(conn)->want_onehop) && /* ignore one-hop streams */
- !(TO_EDGE_CONN(conn)->use_begindir) && /* ignore targeted dir fetches */
- !(TO_EDGE_CONN(conn)->chosen_exit_name) && /* ignore defined streams */
+ !(entry->want_onehop) && /* ignore one-hop streams */
+ !(entry->use_begindir) && /* ignore targeted dir fetches */
+ !(entry->chosen_exit_name) && /* ignore defined streams */
!connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) &&
- !circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0,
+ !circuit_stream_is_being_handled(TO_ENTRY_CONN(conn), 0,
MIN_CIRCUITS_HANDLING_STREAM))
return 1;
return 0;
@@ -2656,18 +2673,17 @@ ap_stream_wants_exit_attention(connection_t *conn)
*
* Return NULL if we can't find any suitable routers.
*/
-static routerinfo_t *
-choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
- int need_capacity)
+static const node_t *
+choose_good_exit_server_general(int need_uptime, int need_capacity)
{
int *n_supported;
- int i;
int n_pending_connections = 0;
smartlist_t *connections;
int best_support = -1;
int n_best_support=0;
- routerinfo_t *router;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ const smartlist_t *the_nodes;
+ const node_t *node=NULL;
connections = get_connection_array();
@@ -2688,10 +2704,11 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*
* -1 means "Don't use this router at all."
*/
- n_supported = tor_malloc(sizeof(int)*smartlist_len(dir->routers));
- for (i = 0; i < smartlist_len(dir->routers); ++i) {/* iterate over routers */
- router = smartlist_get(dir->routers, i);
- if (router_is_me(router)) {
+ the_nodes = nodelist_get_list();
+ n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes));
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ const int i = node_sl_idx;
+ if (router_digest_is_me(node->identity)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s -- it's me.", router->nickname);
/* XXX there's probably a reverse predecessor attack here, but
@@ -2699,41 +2716,44 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*/
continue;
}
- if (!router->is_running || router->is_bad_exit) {
+ if (!node_has_descriptor(node)) {
+ n_supported[i] = -1;
+ continue;
+ }
+ if (!node->is_running || node->is_bad_exit) {
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
-
- if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, router)) {
+ if (routerset_contains_node(options->_ExcludeExitNodesUnion, node)) {
n_supported[i] = -1;
continue; /* user asked us not to use it, no matter what */
}
if (options->ExitNodes &&
- !routerset_contains_router(options->ExitNodes, router)) {
+ !routerset_contains_node(options->ExitNodes, node)) {
n_supported[i] = -1;
continue; /* not one of our chosen exit nodes */
}
- if (router_is_unreliable(router, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
n_supported[i] = -1;
continue; /* skip routers that are not suitable. Don't worry if
* this makes us reject all the possible routers: if so,
* we'll retry later in this function with need_update and
* need_capacity set to 0. */
}
- if (!(router->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
+ if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
/* if it's invalid and we don't want it */
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.",
// router->nickname, i);
continue; /* skip invalid routers */
}
- if (options->ExcludeSingleHopRelays && router->allow_single_hop_exits) {
+ if (options->ExcludeSingleHopRelays &&
+ node_allows_single_hop_exits(node)) {
n_supported[i] = -1;
continue;
}
- if (router_exit_policy_rejects_all(router)) {
+ if (node_exit_policy_rejects_all(node)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
// router->nickname, i);
@@ -2741,11 +2761,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
n_supported[i] = 0;
/* iterate over connections */
- SMARTLIST_FOREACH(connections, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) {
if (!ap_stream_wants_exit_attention(conn))
continue; /* Skip everything but APs in CIRCUIT_WAIT */
- if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) {
+ if (connection_ap_can_use_exit(TO_ENTRY_CONN(conn), node)) {
++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]);
@@ -2753,7 +2772,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
// log_fn(LOG_DEBUG,"%s (index %d) would reject this stream.",
// router->nickname, i);
}
- }); /* End looping over connections. */
+ } SMARTLIST_FOREACH_END(conn);
if (n_pending_connections > 0 && n_supported[i] == 0) {
/* Leave best_support at -1 if that's where it is, so we can
* distinguish it later. */
@@ -2770,7 +2789,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* count of equally good routers.*/
++n_best_support;
}
- }
+ } SMARTLIST_FOREACH_END(node);
log_info(LD_CIRC,
"Found %d servers that might support %d/%d pending connections.",
n_best_support, best_support >= 0 ? best_support : 0,
@@ -2781,11 +2800,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
if (best_support > 0) {
smartlist_t *supporting = smartlist_create();
- for (i = 0; i < smartlist_len(dir->routers); i++)
- if (n_supported[i] == best_support)
- smartlist_add(supporting, smartlist_get(dir->routers, i));
+ SMARTLIST_FOREACH(the_nodes, const node_t *, node, {
+ if (n_supported[node_sl_idx] == best_support)
+ smartlist_add(supporting, (void*)node);
+ });
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
smartlist_free(supporting);
} else {
/* Either there are no pending connections, or no routers even seem to
@@ -2803,7 +2823,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
need_capacity?", fast":"",
need_uptime?", stable":"");
tor_free(n_supported);
- return choose_good_exit_server_general(dir, 0, 0);
+ return choose_good_exit_server_general(0, 0);
}
log_notice(LD_CIRC, "All routers are down or won't exit%s -- "
"choosing a doomed exit at random.",
@@ -2814,18 +2834,17 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
for (attempt = 0; attempt < 2; attempt++) {
/* try once to pick only from routers that satisfy a needed port,
* then if there are none, pick from any that support exiting. */
- for (i = 0; i < smartlist_len(dir->routers); i++) {
- router = smartlist_get(dir->routers, i);
- if (n_supported[i] != -1 &&
- (attempt || router_handles_some_port(router, needed_ports))) {
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ if (n_supported[node_sl_idx] != -1 &&
+ (attempt || node_handles_some_port(node, needed_ports))) {
// log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.",
// try, router->nickname);
- smartlist_add(supporting, router);
+ smartlist_add(supporting, (void*)node);
}
- }
+ } SMARTLIST_FOREACH_END(node);
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
- if (router)
+ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ if (node)
break;
smartlist_clear(supporting);
}
@@ -2835,9 +2854,9 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
tor_free(n_supported);
- if (router) {
- log_info(LD_CIRC, "Chose exit server '%s'", router_describe(router));
- return router;
+ if (node) {
+ log_info(LD_CIRC, "Chose exit server '%s'", node_describe(node));
+ return node;
}
if (options->ExitNodes) {
log_warn(LD_CIRC,
@@ -2858,12 +2877,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* For client-side rendezvous circuits, choose a random node, weighted
* toward the preferences in 'options'.
*/
-static routerinfo_t *
-choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
+static const node_t *
+choose_good_exit_server(uint8_t purpose,
int need_uptime, int need_capacity, int is_internal)
{
- or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_DESC;
if (need_uptime)
flags |= CRN_NEED_UPTIME;
if (need_capacity)
@@ -2876,7 +2895,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
if (is_internal) /* pick it like a middle hop */
return router_choose_random_node(NULL, options->ExcludeNodes, flags);
else
- return choose_good_exit_server_general(dir,need_uptime,need_capacity);
+ return choose_good_exit_server_general(need_uptime,need_capacity);
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS)
flags |= CRN_ALLOW_INVALID;
@@ -2892,7 +2911,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
static void
warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
routerset_t *rs = options->ExcludeNodes;
const char *description;
uint8_t purpose = circ->_base.purpose;
@@ -2969,13 +2988,12 @@ static int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
{
cpath_build_state_t *state = circ->build_state;
- routerlist_t *rl = router_get_routerlist();
if (state->onehop_tunnel) {
log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel.");
state->desired_path_len = 1;
} else {
- int r = new_route_len(circ->_base.purpose, exit, rl->routers);
+ int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list());
if (r < 1) /* must be at least 1 */
return -1;
state->desired_path_len = r;
@@ -2987,14 +3005,15 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
extend_info_describe(exit));
exit = extend_info_dup(exit);
} else { /* we have to decide one */
- routerinfo_t *router =
- choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
+ const node_t *node =
+ choose_good_exit_server(circ->_base.purpose, state->need_uptime,
state->need_capacity, state->is_internal);
- if (!router) {
+ if (!node) {
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
}
- exit = extend_info_from_router(router);
+ exit = extend_info_from_node(node);
+ tor_assert(exit);
}
state->chosen_exit = exit;
return 0;
@@ -3045,35 +3064,30 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit)
* and available for building circuits through.
*/
static int
-count_acceptable_routers(smartlist_t *routers)
+count_acceptable_nodes(smartlist_t *nodes)
{
- int i, n;
int num=0;
- routerinfo_t *r;
- n = smartlist_len(routers);
- for (i=0;i<n;i++) {
- r = smartlist_get(routers, i);
-// log_debug(LD_CIRC,
+ SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
+ // log_debug(LD_CIRC,
// "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname);
- if (r->is_running == 0) {
+ if (! node->is_running)
// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
- goto next_i_loop;
- }
- if (r->is_valid == 0) {
+ continue;
+ if (! node->is_valid)
// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
- goto next_i_loop;
+ continue;
+ if (! node_has_descriptor(node))
+ continue;
/* XXX This clause makes us count incorrectly: if AllowInvalidRouters
* allows this node in some places, then we're getting an inaccurate
* count. For now, be conservative and don't count it. But later we
* should try to be smarter. */
- }
- num++;
+ ++num;
+ } SMARTLIST_FOREACH_END(node);
+
// log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num);
- next_i_loop:
- ; /* C requires an explicit statement after the label */
- }
return num;
}
@@ -3101,31 +3115,29 @@ onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
* circuit. In particular, make sure we don't pick the exit node or its
* family, and make sure we don't duplicate any previous nodes or their
* families. */
-static routerinfo_t *
+static const node_t *
choose_good_middle_server(uint8_t purpose,
cpath_build_state_t *state,
crypt_path_t *head,
int cur_len)
{
int i;
- routerinfo_t *r, *choice;
+ const node_t *r, *choice;
crypt_path_t *cpath;
smartlist_t *excluded;
- or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_DESC;
tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose &&
purpose <= _CIRCUIT_PURPOSE_MAX);
log_debug(LD_CIRC, "Contemplating intermediate hop: random choice.");
excluded = smartlist_create();
- if ((r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((r = build_state_get_exit_node(state))) {
+ nodelist_add_node_and_family(excluded, r);
}
for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) {
- if ((r = router_get_by_digest(cpath->extend_info->identity_digest))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
+ nodelist_add_node_and_family(excluded, r);
}
}
@@ -3148,44 +3160,43 @@ choose_good_middle_server(uint8_t purpose,
* If <b>state</b> is NULL, we're choosing a router to serve as an entry
* guard, not for any particular circuit.
*/
-static routerinfo_t *
+static const node_t *
choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
{
- routerinfo_t *r, *choice;
+ const node_t *choice;
smartlist_t *excluded;
- or_options_t *options = get_options();
- router_crn_flags_t flags = CRN_NEED_GUARD;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC;
+ const node_t *node;
if (state && options->UseEntryGuards &&
(purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) {
+ /* This is request for an entry server to use for a regular circuit,
+ * and we use entry guard nodes. Just return one of the guard nodes. */
return choose_random_entry(state);
}
excluded = smartlist_create();
- if (state && (r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if (state && (node = build_state_get_exit_node(state))) {
+ /* Exclude the exit node from the state, if we have one. Also exclude its
+ * family. */
+ nodelist_add_node_and_family(excluded, node);
}
if (firewall_is_fascist_or()) {
- /*XXXX This could slow things down a lot; use a smarter implementation */
- /* exclude all ORs that listen on the wrong port, if anybody notices. */
- routerlist_t *rl = router_get_routerlist();
- int i;
-
- for (i=0; i < smartlist_len(rl->routers); i++) {
- r = smartlist_get(rl->routers, i);
- if (!fascist_firewall_allows_or(r))
- smartlist_add(excluded, r);
- }
+ /* Exclude all ORs that we can't reach through our firewall */
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (!fascist_firewall_allows_node(node))
+ smartlist_add(excluded, (void*)node);
+ });
}
- /* and exclude current entry guards, if applicable */
+ /* and exclude current entry guards and their families, if applicable */
if (options->UseEntryGuards && entry_guards) {
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
{
- if ((r = router_get_by_digest(entry->identity))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((node = node_get_by_id(entry->identity))) {
+ nodelist_add_node_and_family(excluded, node);
}
});
}
@@ -3241,14 +3252,18 @@ onion_extend_cpath(origin_circuit_t *circ)
if (cur_len == state->desired_path_len - 1) { /* Picking last node */
info = extend_info_dup(state->chosen_exit);
} else if (cur_len == 0) { /* picking first node */
- routerinfo_t *r = choose_good_entry_server(purpose, state);
- if (r)
- info = extend_info_from_router(r);
+ const node_t *r = choose_good_entry_server(purpose, state);
+ if (r) {
+ info = extend_info_from_node(r);
+ tor_assert(info);
+ }
} else {
- routerinfo_t *r =
+ const node_t *r =
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
- if (r)
- info = extend_info_from_router(r);
+ if (r) {
+ info = extend_info_from_node(r);
+ tor_assert(info);
+ }
}
if (!info) {
@@ -3308,7 +3323,7 @@ extend_info_alloc(const char *nickname, const char *digest,
/** Allocate and return a new extend_info_t that can be used to build a
* circuit to or through the router <b>r</b>. */
extend_info_t *
-extend_info_from_router(routerinfo_t *r)
+extend_info_from_router(const routerinfo_t *r)
{
tor_addr_t addr;
tor_assert(r);
@@ -3317,6 +3332,29 @@ extend_info_from_router(routerinfo_t *r)
r->onion_pkey, &addr, r->or_port);
}
+/** Allocate and return a new extend_info that can be used to build a ircuit
+ * to or through the node <b>node</b>. May return NULL if there is not
+ * enough info about <b>node</b> to extend to it--for example, if there
+ * is no routerinfo_t or microdesc_t.
+ **/
+extend_info_t *
+extend_info_from_node(const node_t *node)
+{
+ if (node->ri) {
+ return extend_info_from_router(node->ri);
+ } else if (node->rs && node->md) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return extend_info_alloc(node->rs->nickname,
+ node->identity,
+ node->md->onion_pkey,
+ &addr,
+ node->rs->or_port);
+ } else {
+ return NULL;
+ }
+}
+
/** Release storage held by an extend_info_t struct. */
void
extend_info_free(extend_info_t *info)
@@ -3347,12 +3385,12 @@ extend_info_dup(extend_info_t *info)
* If there is no chosen exit, or if we don't know the routerinfo_t for
* the chosen exit, return NULL.
*/
-routerinfo_t *
-build_state_get_exit_router(cpath_build_state_t *state)
+const node_t *
+build_state_get_exit_node(cpath_build_state_t *state)
{
if (!state || !state->chosen_exit)
return NULL;
- return router_get_by_digest(state->chosen_exit->identity_digest);
+ return node_get_by_id(state->chosen_exit->identity_digest);
}
/** Return the nickname for the chosen exit router in <b>state</b>. If
@@ -3374,10 +3412,10 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
*
* If it's not usable, set *<b>reason</b> to a static string explaining why.
*/
-/*XXXX take a routerstatus, not a routerinfo. */
static int
-entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
- time_t now, or_options_t *options, const char **reason)
+entry_guard_set_status(entry_guard_t *e, const node_t *node,
+ time_t now, const or_options_t *options,
+ const char **reason)
{
char buf[HEX_DIGEST_LEN+1];
int changed = 0;
@@ -3385,18 +3423,19 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
*reason = NULL;
/* Do we want to mark this guard as bad? */
- if (!ri)
+ if (!node)
*reason = "unlisted";
- else if (!ri->is_running)
+ else if (!node->is_running)
*reason = "down";
- else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE)
+ else if (options->UseBridges && (!node->ri ||
+ node->ri->purpose != ROUTER_PURPOSE_BRIDGE))
*reason = "not a bridge";
- else if (options->UseBridges && !routerinfo_is_a_configured_bridge(ri))
+ else if (options->UseBridges && !node_is_a_configured_bridge(node))
*reason = "not a configured bridge";
- else if (!options->UseBridges && !ri->is_possible_guard &&
- !routerset_contains_router(options->EntryNodes,ri))
+ else if (!options->UseBridges && !node->is_possible_guard &&
+ !routerset_contains_node(options->EntryNodes,node))
*reason = "not recommended as a guard";
- else if (routerset_contains_router(options->ExcludeNodes, ri))
+ else if (routerset_contains_node(options->ExcludeNodes, node))
*reason = "excluded";
if (*reason && ! e->bad_since) {
@@ -3440,7 +3479,7 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
return now > (e->last_attempted + 36*60*60);
}
-/** Return the router corresponding to <b>e</b>, if <b>e</b> is
+/** Return the node corresponding to <b>e</b>, if <b>e</b> is
* working well enough that we are willing to use it as an entry
* right now. (Else return NULL.) In particular, it must be
* - Listed as either up or never yet contacted;
@@ -3454,12 +3493,12 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
*
* If the answer is no, set *<b>msg</b> to an explanation of why.
*/
-static INLINE routerinfo_t *
+static INLINE const node_t *
entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
int assume_reachable, const char **msg)
{
- routerinfo_t *r;
- or_options_t *options = get_options();
+ const node_t *node;
+ const or_options_t *options = get_options();
tor_assert(msg);
if (e->bad_since) {
@@ -3472,38 +3511,39 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
*msg = "unreachable";
return NULL;
}
- r = router_get_by_digest(e->identity);
- if (!r) {
+ node = node_get_by_id(e->identity);
+ if (!node || !node_has_descriptor(node)) {
*msg = "no descriptor";
return NULL;
}
- if (options->UseBridges) {
- if (r->purpose != ROUTER_PURPOSE_BRIDGE) {
+ if (get_options()->UseBridges) {
+ if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) {
*msg = "not a bridge";
return NULL;
}
- if (!routerinfo_is_a_configured_bridge(r)) {
+ if (!node_is_a_configured_bridge(node)) {
*msg = "not a configured bridge";
return NULL;
}
- } else if (r->purpose != ROUTER_PURPOSE_GENERAL) {
- *msg = "not general-purpose";
- return NULL;
+ } else { /* !get_options()->UseBridges */
+ if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) {
+ *msg = "not general-purpose";
+ return NULL;
+ }
}
- if (options->EntryNodes &&
- routerset_contains_router(options->EntryNodes, r)) {
+ if (routerset_contains_node(options->EntryNodes, node)) {
/* they asked for it, they get it */
need_uptime = need_capacity = 0;
}
- if (router_is_unreliable(r, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
*msg = "not fast/stable";
return NULL;
}
- if (!fascist_firewall_allows_or(r)) {
+ if (!fascist_firewall_allows_node(node)) {
*msg = "unreachable by config";
return NULL;
}
- return r;
+ return node;
}
/** Return the number of entry guards that we think are usable. */
@@ -3583,7 +3623,7 @@ control_event_guard_deferred(void)
#if 0
int n = 0;
const char *msg;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!entry_guards)
return;
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
@@ -3605,15 +3645,15 @@ control_event_guard_deferred(void)
* If <b>chosen</b> is defined, use that one, and if it's not
* already in our entry_guards list, put it at the *beginning*.
* Else, put the one we pick at the end of the list. */
-static routerinfo_t *
-add_an_entry_guard(routerinfo_t *chosen, int reset_status)
+static const node_t *
+add_an_entry_guard(const node_t *chosen, int reset_status, int prepend)
{
- routerinfo_t *router;
+ const node_t *node;
entry_guard_t *entry;
if (chosen) {
- router = chosen;
- entry = is_an_entry_guard(router->cache_info.identity_digest);
+ node = chosen;
+ entry = is_an_entry_guard(node->identity);
if (entry) {
if (reset_status) {
entry->bad_since = 0;
@@ -3622,15 +3662,15 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
return NULL;
}
} else {
- router = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
- if (!router)
+ node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
+ if (!node)
return NULL;
}
entry = tor_malloc_zero(sizeof(entry_guard_t));
- log_info(LD_CIRC, "Chose '%s' as new entry guard.",
- router_describe(router));
- strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname));
- memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN);
+ log_info(LD_CIRC, "Chose %s as new entry guard.",
+ node_describe(node));
+ strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname));
+ memcpy(entry->identity, node->identity, DIGEST_LEN);
/* Choose expiry time smudged over the past month. The goal here
* is to a) spread out when Tor clients rotate their guards, so they
* don't all select them on the same day, and b) avoid leaving a
@@ -3638,27 +3678,27 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
* this guard. For details, see the Jan 2010 or-dev thread. */
entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30);
entry->chosen_by_version = tor_strdup(VERSION);
- if (chosen) /* prepend */
+ if (prepend)
smartlist_insert(entry_guards, 0, entry);
- else /* append */
+ else
smartlist_add(entry_guards, entry);
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
log_entry_guards(LOG_INFO);
- return router;
+ return node;
}
/** If the use of entry guards is configured, choose more entry guards
* until we have enough in the list. */
static void
-pick_entry_guards(or_options_t *options)
+pick_entry_guards(const or_options_t *options)
{
int changed = 0;
tor_assert(entry_guards);
while (num_live_entry_guards() < options->NumEntryGuards) {
- if (!add_an_entry_guard(NULL, 0))
+ if (!add_an_entry_guard(NULL, 0, 0))
break;
changed = 1;
}
@@ -3784,7 +3824,7 @@ remove_dead_entry_guards(time_t now)
* think that things are unlisted.
*/
void
-entry_guards_compute_status(or_options_t *options, time_t now)
+entry_guards_compute_status(const or_options_t *options, time_t now)
{
int changed = 0;
digestmap_t *reasons;
@@ -3798,7 +3838,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
reasons = digestmap_new();
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry)
{
- routerinfo_t *r = router_get_by_digest(entry->identity);
+ const node_t *r = node_get_by_id(entry->identity);
const char *reason = NULL;
if (entry_guard_set_status(entry, r, now, options, &reason))
changed = 1;
@@ -3817,7 +3857,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *reason = digestmap_get(reasons, entry->identity);
const char *live_msg = "";
- routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
+ const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.",
entry->nickname,
hex_str(entry->identity, DIGEST_LEN),
@@ -3935,7 +3975,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
break;
if (e->made_contact) {
const char *msg;
- routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg);
+ const node_t *r = entry_is_live(e, 0, 1, 1, &msg);
if (r && e->unreachable_since) {
refuse_conn = 1;
e->can_retry = 1;
@@ -3971,12 +4011,12 @@ entry_nodes_should_be_added(void)
should_add_entry_nodes = 1;
}
-/** Add all nodes in EntryNodes that aren't currently guard nodes to the list
- * of guard nodes, at the front. */
+/** Adjust the entry guards list so that it only contains entries from
+ * EntryNodes, adding new entries from EntryNodes to the list as needed. */
static void
-entry_guards_prepend_from_config(or_options_t *options)
+entry_guards_set_from_config(const or_options_t *options)
{
- smartlist_t *entry_routers, *entry_fps;
+ smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps;
smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
tor_assert(entry_guards);
@@ -3996,23 +4036,19 @@ entry_guards_prepend_from_config(or_options_t *options)
tor_free(string);
}
- entry_routers = smartlist_create();
+ entry_nodes = smartlist_create();
+ worse_entry_nodes = smartlist_create();
entry_fps = smartlist_create();
old_entry_guards_on_list = smartlist_create();
old_entry_guards_not_on_list = smartlist_create();
/* Split entry guards into those on the list and those not. */
- /* XXXX023 Now that we allow countries and IP ranges in EntryNodes, this is
- * potentially an enormous list. For now, we disable such values for
- * EntryNodes in options_validate(); really, this wants a better solution.
- * Perhaps we should do this calculation once whenever the list of routers
- * changes or the entrynodes setting changes.
- */
- routerset_get_all_routers(entry_routers, options->EntryNodes,
- options->ExcludeNodes, 0);
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri,
- smartlist_add(entry_fps,ri->cache_info.identity_digest));
+ routerset_get_all_nodes(entry_nodes, options->EntryNodes,
+ options->ExcludeNodes, 0);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
+ smartlist_add(entry_fps, (void*)node->identity));
+
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, {
if (smartlist_digest_isin(entry_fps, e->identity))
smartlist_add(old_entry_guards_on_list, e);
@@ -4020,27 +4056,47 @@ entry_guards_prepend_from_config(or_options_t *options)
smartlist_add(old_entry_guards_not_on_list, e);
});
- /* Remove all currently configured entry guards from entry_routers. */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- if (is_an_entry_guard(ri->cache_info.identity_digest)) {
- SMARTLIST_DEL_CURRENT(entry_routers, ri);
+ /* Remove all currently configured guard nodes, excluded nodes, unreachable
+ * nodes, or non-Guard nodes from entry_nodes. */
+ SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
+ if (is_an_entry_guard(node->identity)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
+ continue;
+ } else if (routerset_contains_node(options->ExcludeNodes, node)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
+ continue;
+ } else if (!fascist_firewall_allows_node(node)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
+ continue;
+ } else if (! node->is_possible_guard) {
+ smartlist_add(worse_entry_nodes, (node_t*)node);
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
}
- });
+ } SMARTLIST_FOREACH_END(node);
/* Now build the new entry_guards list. */
smartlist_clear(entry_guards);
/* First, the previously configured guards that are in EntryNodes. */
smartlist_add_all(entry_guards, old_entry_guards_on_list);
+ /* Next, scramble the rest of EntryNodes, putting the guards first. */
+ smartlist_shuffle(entry_nodes);
+ smartlist_shuffle(worse_entry_nodes);
+ smartlist_add_all(entry_nodes, worse_entry_nodes);
+
/* Next, the rest of EntryNodes */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- add_an_entry_guard(ri, 0);
- });
+ SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
+ add_an_entry_guard(node, 0, 0);
+ if (smartlist_len(entry_guards) > options->NumEntryGuards * 10)
+ break;
+ } SMARTLIST_FOREACH_END(node);
+ log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards));
/* Finally, free the remaining previously configured guards that are not in
* EntryNodes. */
SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
entry_guard_free(e));
- smartlist_free(entry_routers);
+ smartlist_free(entry_nodes);
+ smartlist_free(worse_entry_nodes);
smartlist_free(entry_fps);
smartlist_free(old_entry_guards_on_list);
smartlist_free(old_entry_guards_not_on_list);
@@ -4052,7 +4108,7 @@ entry_guards_prepend_from_config(or_options_t *options)
* list already and we must stick to it.
*/
int
-entry_list_is_constrained(or_options_t *options)
+entry_list_is_constrained(const or_options_t *options)
{
if (options->EntryNodes)
return 1;
@@ -4066,20 +4122,21 @@ entry_list_is_constrained(or_options_t *options)
* make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random
* guard (likely a bridge). */
-routerinfo_t *
+const node_t *
choose_random_entry(cpath_build_state_t *state)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *live_entry_guards = smartlist_create();
smartlist_t *exit_family = smartlist_create();
- routerinfo_t *chosen_exit = state?build_state_get_exit_router(state) : NULL;
- routerinfo_t *r = NULL;
+ const node_t *chosen_exit =
+ state?build_state_get_exit_node(state) : NULL;
+ const node_t *node = NULL;
int need_uptime = state ? state->need_uptime : 0;
int need_capacity = state ? state->need_capacity : 0;
int preferred_min, consider_exit_family = 0;
if (chosen_exit) {
- routerlist_add_family(exit_family, chosen_exit);
+ nodelist_add_node_and_family(exit_family, chosen_exit);
consider_exit_family = 1;
}
@@ -4087,7 +4144,7 @@ choose_random_entry(cpath_build_state_t *state)
entry_guards = smartlist_create();
if (should_add_entry_nodes)
- entry_guards_prepend_from_config(options);
+ entry_guards_set_from_config(options);
if (!entry_list_is_constrained(options) &&
smartlist_len(entry_guards) < options->NumEntryGuards)
@@ -4095,25 +4152,24 @@ choose_random_entry(cpath_build_state_t *state)
retry:
smartlist_clear(live_entry_guards);
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry)
- {
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *msg;
- r = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
- if (!r)
+ node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
+ if (!node)
continue; /* down, no point */
- if (r == chosen_exit)
+ if (node == chosen_exit)
continue; /* don't pick the same node for entry and exit */
- if (consider_exit_family && smartlist_isin(exit_family, r))
+ if (consider_exit_family && smartlist_isin(exit_family, node))
continue; /* avoid relays that are family members of our exit */
#if 0 /* since EntryNodes is always strict now, this clause is moot */
if (options->EntryNodes &&
- !routerset_contains_router(options->EntryNodes, r)) {
+ !routerset_contains_node(options->EntryNodes, node)) {
/* We've come to the end of our preferred entry nodes. */
if (smartlist_len(live_entry_guards))
goto choose_and_finish; /* only choose from the ones we like */
if (options->StrictNodes) {
/* in theory this case should never happen, since
- * entry_guards_prepend_from_config() drops unwanted relays */
+ * entry_guards_set_from_config() drops unwanted relays */
tor_fragile_assert();
} else {
log_info(LD_CIRC,
@@ -4121,7 +4177,7 @@ choose_random_entry(cpath_build_state_t *state)
}
}
#endif
- smartlist_add(live_entry_guards, r);
+ smartlist_add(live_entry_guards, (void*)node);
if (!entry->made_contact) {
/* Always start with the first not-yet-contacted entry
* guard. Otherwise we might add several new ones, pick
@@ -4130,9 +4186,8 @@ choose_random_entry(cpath_build_state_t *state)
goto choose_and_finish;
}
if (smartlist_len(live_entry_guards) >= options->NumEntryGuards)
- break; /* we have enough */
- }
- SMARTLIST_FOREACH_END(entry);
+ goto choose_and_finish; /* we have enough */
+ } SMARTLIST_FOREACH_END(entry);
if (entry_list_is_constrained(options)) {
/* If we prefer the entry nodes we've got, and we have at least
@@ -4152,8 +4207,8 @@ choose_random_entry(cpath_build_state_t *state)
/* XXX if guard doesn't imply fast and stable, then we need
* to tell add_an_entry_guard below what we want, or it might
* be a long time til we get it. -RD */
- r = add_an_entry_guard(NULL, 0);
- if (r) {
+ node = add_an_entry_guard(NULL, 0, 0);
+ if (node) {
entry_guards_changed();
/* XXX we start over here in case the new node we added shares
* a family with our exit node. There's a chance that we'll just
@@ -4163,11 +4218,11 @@ choose_random_entry(cpath_build_state_t *state)
goto retry;
}
}
- if (!r && need_uptime) {
+ if (!node && need_uptime) {
need_uptime = 0; /* try without that requirement */
goto retry;
}
- if (!r && need_capacity) {
+ if (!node && need_capacity) {
/* still no? last attempt, try without requiring capacity */
need_capacity = 0;
goto retry;
@@ -4176,10 +4231,10 @@ choose_random_entry(cpath_build_state_t *state)
/* Removing this retry logic: if we only allow one exit, and it is in the
same family as all our entries, then we are just plain not going to win
here. */
- if (!r && entry_list_is_constrained(options) && consider_exit_family) {
- /* still no? if we're using bridges,
- * and our chosen exit is in the same family as all our
- * bridges, then be flexible about families. */
+ if (!node && entry_list_is_constrained(options) && consider_exit_family) {
+ /* still no? if we're using bridges or have strictentrynodes
+ * set, and our chosen exit is in the same family as all our
+ * bridges/entry guards, then be flexible about families. */
consider_exit_family = 0;
goto retry;
}
@@ -4191,16 +4246,16 @@ choose_random_entry(cpath_build_state_t *state)
if (entry_list_is_constrained(options)) {
/* We need to weight by bandwidth, because our bridges or entryguards
* were not already selected proportional to their bandwidth. */
- r = routerlist_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
+ node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
} else {
/* We choose uniformly at random here, because choose_good_entry_server()
* already weights its choices by bandwidth, so we don't want to
* *double*-weight our guard selection. */
- r = smartlist_choose(live_entry_guards);
+ node = smartlist_choose(live_entry_guards);
}
smartlist_free(live_entry_guards);
smartlist_free(exit_family);
- return r;
+ return node;
}
/** Parse <b>state</b> and learn about the entry guards it describes.
@@ -4447,7 +4502,7 @@ getinfo_helper_entry_guards(control_connection_t *conn,
char *c = tor_malloc(len);
const char *status = NULL;
time_t when = 0;
- routerinfo_t *ri;
+ const node_t *node;
if (!e->made_contact) {
status = "never-connected";
@@ -4458,9 +4513,9 @@ getinfo_helper_entry_guards(control_connection_t *conn,
status = "up";
}
- ri = router_get_by_digest(e->identity);
- if (ri) {
- router_get_verbose_nickname(nbuf, ri);
+ node = node_get_by_id(e->identity);
+ if (node) {
+ node_get_verbose_nickname(node, nbuf);
} else {
nbuf[0] = '$';
base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN);
@@ -4483,24 +4538,6 @@ getinfo_helper_entry_guards(control_connection_t *conn,
return 0;
}
-/** Information about a configured bridge. Currently this just matches the
- * ones in the torrc file, but one day we may be able to learn about new
- * bridges on our own, and remember them in the state file. */
-typedef struct {
- /** Address of the bridge. */
- tor_addr_t addr;
- /** TLS port for the bridge. */
- uint16_t port;
- /** Boolean: We are re-parsing our bridge list, and we are going to remove
- * this one if we don't find it in the list of configured bridges. */
- unsigned marked_for_removal : 1;
- /** Expected identity digest, or all zero bytes if we don't know what the
- * digest should be. */
- char identity[DIGEST_LEN];
- /** When should we next try to fetch a descriptor for this bridge? */
- download_status_t fetch_status;
-} bridge_info_t;
-
/** A list of configured bridges. Whenever we actually get a descriptor
* for one, we add it as an entry guard. Note that the order of bridges
* in this list does not necessarily correspond to the order of bridges
@@ -4528,7 +4565,7 @@ sweep_bridge_list(void)
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
if (b->marked_for_removal) {
SMARTLIST_DEL_CURRENT(bridge_list, b);
- tor_free(b);
+ bridge_free(b);
}
} SMARTLIST_FOREACH_END(b);
}
@@ -4539,10 +4576,243 @@ clear_bridge_list(void)
{
if (!bridge_list)
bridge_list = smartlist_create();
- SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, tor_free(b));
+ SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b));
smartlist_clear(bridge_list);
}
+/** Free the bridge <b>bridge</b>. */
+static void
+bridge_free(bridge_info_t *bridge)
+{
+ if (!bridge)
+ return;
+
+ tor_free(bridge->transport_name);
+ tor_free(bridge);
+}
+
+/** A list of pluggable transports found in torrc. */
+static smartlist_t *transport_list = NULL;
+
+/** Mark every entry of the transport list to be removed on our next call to
+ * sweep_transport_list unless it has first been un-marked. */
+void
+mark_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, transport_t *, t,
+ t->marked_for_removal = 1);
+}
+
+/** Remove every entry of the transport list that was marked with
+ * mark_transport_list if it has not subsequently been un-marked. */
+void
+sweep_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
+ if (t->marked_for_removal) {
+ SMARTLIST_DEL_CURRENT(transport_list, t);
+ transport_free(t);
+ }
+ } SMARTLIST_FOREACH_END(t);
+}
+
+/** Initialize the pluggable transports list to empty, creating it if
+ * needed. */
+void
+clear_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
+ smartlist_clear(transport_list);
+}
+
+/** Free the pluggable transport struct <b>transport</b>. */
+void
+transport_free(transport_t *transport)
+{
+ if (!transport)
+ return;
+
+ tor_free(transport->name);
+ tor_free(transport);
+}
+
+/** Returns the transport in our transport list that has the name <b>name</b>.
+ * Else returns NULL. */
+transport_t *
+transport_get_by_name(const char *name)
+{
+ tor_assert(name);
+
+ if (!transport_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
+ if (!strcmp(transport->name, name))
+ return transport;
+ } SMARTLIST_FOREACH_END(transport);
+
+ return NULL;
+}
+
+/** Returns a transport_t struct for a transport proxy supporting the
+ protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
+ SOCKS version <b>socks_ver</b>. */
+transport_t *
+transport_create(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_t *t = tor_malloc_zero(sizeof(transport_t));
+
+ tor_addr_copy(&t->addr, addr);
+ t->port = port;
+ t->name = tor_strdup(name);
+ t->socks_version = socks_ver;
+
+ return t;
+}
+
+/** Resolve any conflicts that the insertion of transport <b>t</b>
+ * might cause.
+ * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
+ * a transport identical to <b>t</b> already registered and -1 if
+ * <b>t</b> cannot be added due to conflicts. */
+static int
+transport_resolve_conflicts(transport_t *t)
+{
+ /* This is how we resolve transport conflicts:
+
+ If there is already a transport with the same name and addrport,
+ we either have duplicate torrc lines OR we are here post-HUP and
+ this transport was here pre-HUP as well. In any case, mark the
+ old transport so that it doesn't get removed and ignore the new
+ one. Our caller has to free the new transport so we return '1' to
+ signify this.
+
+ If there is already a transport with the same name but different
+ addrport:
+ * if it's marked for removal, it means that it either has a lower
+ priority than 't' in torrc (otherwise the mark would have been
+ cleared by the paragraph above), or it doesn't exist at all in
+ the post-HUP torrc. We destroy the old transport and register 't'.
+ * if it's *not* marked for removal, it means that it was newly
+ added in the post-HUP torrc or that it's of higher priority, in
+ this case we ignore 't'. */
+ transport_t *t_tmp = transport_get_by_name(t->name);
+ if (t_tmp) { /* same name */
+ if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
+ /* same name *and* addrport */
+ t_tmp->marked_for_removal = 0;
+ return 1;
+ } else { /* same name but different addrport */
+ if (t_tmp->marked_for_removal) { /* marked for removal */
+ log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
+ "but there was already a transport marked for deletion at "
+ "'%s:%u'. We deleted the old transport and registered the "
+ "new one.", t->name, fmt_addr(&t->addr), t->port,
+ fmt_addr(&t_tmp->addr), t_tmp->port);
+ smartlist_remove(transport_list, t_tmp);
+ transport_free(t_tmp);
+ } else { /* *not* marked for removal */
+ log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
+ "but the same transport already exists at '%s:%u'. "
+ "Skipping.", t->name, fmt_addr(&t->addr), t->port,
+ fmt_addr(&t_tmp->addr), t_tmp->port);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Add transport <b>t</b> to the internal list of pluggable
+ * transports.
+ * Returns 0 if the transport was added correctly, 1 if the same
+ * transport was already registered (in this case the caller must
+ * free the transport) and -1 if there was an error. */
+int
+transport_add(transport_t *t)
+{
+ int r;
+ tor_assert(t);
+
+ r = transport_resolve_conflicts(t);
+
+ switch (r) {
+ case 0: /* should register transport */
+ if (!transport_list)
+ transport_list = smartlist_create();
+ smartlist_add(transport_list, t);
+ return 0;
+ default: /* let our caller know the return code */
+ return r;
+ }
+}
+
+/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
+ * <b>name</b> is set to the name of the protocol this proxy uses.
+ * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
+int
+transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_t *t = transport_create(addr, port, name, socks_ver);
+
+ int r = transport_add(t);
+
+ switch (r) {
+ case -1:
+ default:
+ log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.",
+ t->name, fmt_addr(&t->addr), t->port);
+ transport_free(t);
+ return -1;
+ case 1:
+ log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
+ t->name, fmt_addr(&t->addr), t->port);
+ transport_free(t); /* falling */
+ return 0;
+ case 0:
+ log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
+ t->name, fmt_addr(&t->addr), t->port);
+ return 0;
+ }
+}
+
+/** Warn the user of possible pluggable transport misconfiguration.
+ * Return 0 if the validation happened, -1 if we should postpone the
+ * validation. */
+int
+validate_pluggable_transports_config(void)
+{
+ /* Don't validate if managed proxies are not yet fully configured. */
+ if (bridge_list && !pt_proxies_configuration_pending()) {
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
+ /* Skip bridges without transports. */
+ if (!b->transport_name)
+ continue;
+ /* See if the user has Bridges that specify nonexistent
+ pluggable transports. We should warn the user in such case,
+ since it's probably misconfiguration. */
+ if (!transport_get_by_name(b->transport_name))
+ log_warn(LD_CONFIG, "You have a Bridge line using the %s "
+ "pluggable transport, but there doesn't seem to be a "
+ "corresponding ClientTransportPlugin line.",
+ b->transport_name);
+ } SMARTLIST_FOREACH_END(b);
+
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
/** Return a bridge pointer if <b>ri</b> is one of our known bridges
* (either by comparing keys if possible, else by comparing addr/port).
* Else return NULL. */
@@ -4569,7 +4839,7 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
* it up via router descriptor <b>ri</b>. */
static bridge_info_t *
-get_configured_bridge_by_routerinfo(routerinfo_t *ri)
+get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -4579,11 +4849,29 @@ get_configured_bridge_by_routerinfo(routerinfo_t *ri)
/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
int
-routerinfo_is_a_configured_bridge(routerinfo_t *ri)
+routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
{
return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
}
+/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */
+int
+node_is_a_configured_bridge(const node_t *node)
+{
+ tor_addr_t addr;
+ uint16_t orport;
+ if (!node)
+ return 0;
+ if (node_get_addr(node, &addr) < 0)
+ return 0;
+ orport = node_get_orport(node);
+ if (orport == 0)
+ return 0;
+
+ return get_configured_bridge_by_addr_port_digest(
+ &addr, orport, node->identity) != NULL;
+}
+
/** We made a connection to a router at <b>addr</b>:<b>port</b>
* without knowing its digest. Its digest turned out to be <b>digest</b>.
* If it was a bridge, and we still don't know its digest, record it.
@@ -4603,10 +4891,12 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port,
/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
* is set, it tells us the identity key too. If we already had the
- * bridge in our list, unmark it, and don't actually add anything new. */
+ * bridge in our list, unmark it, and don't actually add anything new.
+ * If <b>transport_name</b> is non-NULL - the bridge is associated with a
+ * pluggable transport - we assign the transport to the bridge. */
void
bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *digest)
+ const char *digest, const char *transport_name)
{
bridge_info_t *b;
@@ -4620,6 +4910,8 @@ bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
b->port = port;
if (digest)
memcpy(b->identity, digest, DIGEST_LEN);
+ if (transport_name)
+ b->transport_name = tor_strdup(transport_name);
b->fetch_status.schedule = DL_SCHED_BRIDGE;
if (!bridge_list)
bridge_list = smartlist_create();
@@ -4657,19 +4949,54 @@ find_bridge_by_digest(const char *digest)
return NULL;
}
+/** If <b>addr</b> and <b>port</b> match the address and port of a
+ * bridge of ours that uses pluggable transports, place its transport
+ * in <b>transport</b>.
+ *
+ * Return 0 on success (found a transport, or found a bridge with no
+ * transport, or found no bridge); return -1 if we should be using a
+ * transport, but the transport could not be found.
+ */
+int
+find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
+ const transport_t **transport)
+{
+ *transport = NULL;
+ if (!bridge_list)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
+ if (tor_addr_eq(&bridge->addr, addr) &&
+ (bridge->port == port)) { /* bridge matched */
+ if (bridge->transport_name) { /* it also uses pluggable transports */
+ *transport = transport_get_by_name(bridge->transport_name);
+ if (*transport == NULL) { /* it uses pluggable transports, but
+ the transport could not be found! */
+ return -1;
+ }
+ return 0;
+ } else { /* bridge matched, but it doesn't use transports. */
+ break;
+ }
+ }
+ } SMARTLIST_FOREACH_END(bridge);
+
+ *transport = NULL;
+ return 0;
+}
+
/** We need to ask <b>bridge</b> for its server descriptor. */
static void
launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
{
char *address;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (connection_get_by_type_addr_port_purpose(
CONN_TYPE_DIR, &bridge->addr, bridge->port,
DIR_PURPOSE_FETCH_SERVERDESC))
return; /* it's already on the way */
- address = tor_dup_addr(&bridge->addr);
if (routerset_contains_bridge(options->ExcludeNodes, bridge)) {
download_status_mark_impossible(&bridge->fetch_status);
log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.",
@@ -4677,6 +5004,8 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
return;
}
+ address = tor_dup_addr(&bridge->addr);
+
directory_initiate_command(address, &bridge->addr,
bridge->port, 0,
0, /* does not matter */
@@ -4703,15 +5032,20 @@ retry_bridge_descriptor_fetch_directly(const char *digest)
* descriptor, fetch a new copy of its descriptor -- either directly
* from the bridge or via a bridge authority. */
void
-fetch_bridge_descriptors(or_options_t *options, time_t now)
+fetch_bridge_descriptors(const or_options_t *options, time_t now)
{
- int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY);
+ int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO);
int ask_bridge_directly;
int can_use_bridge_authority;
if (!bridge_list)
return;
+ /* If we still have unconfigured managed proxies, don't go and
+ connect to a bridge. */
+ if (pt_proxies_configuration_pending())
+ return;
+
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
{
if (!download_status_is_ready(&bridge->fetch_status, now,
@@ -4770,26 +5104,55 @@ fetch_bridge_descriptors(or_options_t *options, time_t now)
}
/** If our <b>bridge</b> is configured to be a different address than
- * the bridge gives in its routerinfo <b>ri</b>, rewrite the routerinfo
+ * the bridge gives in <b>node</b>, rewrite the routerinfo
* we received to use the address we meant to use. Now we handle
* multihomed bridges better.
*/
static void
-rewrite_routerinfo_address_for_bridge(bridge_info_t *bridge, routerinfo_t *ri)
+rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
{
+ /* XXXX move this function. */
+ /* XXXX overridden addresses should really live in the node_t, so that the
+ * routerinfo_t and the microdesc_t can be immutable. But we can only
+ * do that safely if we know that no function that connects to an OR
+ * does so through an address from any source other than node_get_addr().
+ */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
- if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == ri->or_port)
- return; /* they match, so no need to do anything */
+ if (node->ri) {
+ routerinfo_t *ri = node->ri;
+ tor_addr_from_ipv4h(&addr, ri->addr);
+
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == ri->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ ri->addr = tor_addr_to_ipv4h(&bridge->addr);
+ tor_free(ri->address);
+ ri->address = tor_dup_ip(ri->addr);
+ ri->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerinfo for '%s' to match configured "
+ "address %s:%d.",
+ ri->nickname, ri->address, ri->or_port);
+ }
+ }
+ if (node->rs) {
+ routerstatus_t *rs = node->rs;
+ tor_addr_from_ipv4h(&addr, rs->addr);
- ri->addr = tor_addr_to_ipv4h(&bridge->addr);
- tor_free(ri->address);
- ri->address = tor_dup_ip(ri->addr);
- ri->or_port = bridge->port;
- log_info(LD_DIR, "Adjusted bridge '%s' to match configured address %s:%d.",
- ri->nickname, ri->address, ri->or_port);
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == rs->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ rs->addr = tor_addr_to_ipv4h(&bridge->addr);
+ rs->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerstatus for '%s' to match "
+ "configured address %s:%d.",
+ rs->nickname, fmt_addr(&bridge->addr), rs->or_port);
+ }
+ }
}
/** We just learned a descriptor for a bridge. See if that
@@ -4803,16 +5166,19 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
int first = !any_bridge_descriptors_known();
bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
time_t now = time(NULL);
- ri->is_running = 1;
+ router_set_status(ri->cache_info.identity_digest, 1);
if (bridge) { /* if we actually want to use this one */
+ node_t *node;
/* it's here; schedule its re-fetch for a long time from now. */
if (!from_cache)
download_status_reset(&bridge->fetch_status);
- rewrite_routerinfo_address_for_bridge(bridge, ri);
+ node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
+ rewrite_node_address_for_bridge(bridge, node);
+ add_an_entry_guard(node, 1, 1);
- add_an_entry_guard(ri, 1);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
from_cache ? "cached" : "fresh");
/* set entry->made_contact so if it goes down we don't drop it from
@@ -4865,21 +5231,20 @@ any_pending_bridge_descriptor_fetches(void)
* down. Else return 0. If <b>act</b> is 1, then mark the down guards
* up; else just observe and report. */
static int
-entries_retry_helper(or_options_t *options, int act)
+entries_retry_helper(const or_options_t *options, int act)
{
- routerinfo_t *ri;
+ const node_t *node;
int any_known = 0;
int any_running = 0;
- int purpose = options->UseBridges ?
- ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
+ int need_bridges = options->UseBridges != 0;
if (!entry_guards)
entry_guards = smartlist_create();
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
- {
- ri = router_get_by_digest(e->identity);
- if (ri && ri->purpose == purpose) {
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ node = node_get_by_id(e->identity);
+ if (node && node_has_descriptor(node) &&
+ node_is_bridge(node) == need_bridges) {
any_known = 1;
- if (ri->is_running)
+ if (node->is_running)
any_running = 1; /* some entry is both known and running */
else if (act) {
/* Mark all current connections to this OR as unhealthy, since
@@ -4888,15 +5253,15 @@ entries_retry_helper(or_options_t *options, int act)
* the node down and undermine the retry attempt. We mark even
* the established conns, since if the network just came back
* we'll want to attach circuits to fresh conns. */
- connection_or_set_bad_connections(ri->cache_info.identity_digest, 1);
+ connection_or_set_bad_connections(node->identity, 1);
/* mark this entry node for retry */
- router_set_status(ri->cache_info.identity_digest, 1);
+ router_set_status(node->identity, 1);
e->can_retry = 1;
e->bad_since = 0;
}
}
- });
+ } SMARTLIST_FOREACH_END(e);
log_debug(LD_DIR, "%d: any_known %d, any_running %d",
act, any_known, any_running);
return any_known && !any_running;
@@ -4905,7 +5270,7 @@ entries_retry_helper(or_options_t *options, int act)
/** Do we know any descriptors for our bridges / entrynodes, and are
* all the ones we have descriptors for down? */
int
-entries_known_but_down(or_options_t *options)
+entries_known_but_down(const or_options_t *options)
{
tor_assert(entry_list_is_constrained(options));
return entries_retry_helper(options, 0);
@@ -4913,7 +5278,7 @@ entries_known_but_down(or_options_t *options)
/** Mark all down known bridges / entrynodes up. */
void
-entries_retry_all(or_options_t *options)
+entries_retry_all(const or_options_t *options)
{
tor_assert(entry_list_is_constrained(options));
entries_retry_helper(options, 1);
@@ -4931,7 +5296,10 @@ entry_guards_free_all(void)
entry_guards = NULL;
}
clear_bridge_list();
+ clear_transport_list();
smartlist_free(bridge_list);
+ smartlist_free(transport_list);
bridge_list = NULL;
+ transport_list = NULL;
}
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 0e673e1c05..1052db6153 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -12,6 +12,21 @@
#ifndef _TOR_CIRCUITBUILD_H
#define _TOR_CIRCUITBUILD_H
+/** Represents a pluggable transport proxy used by a bridge. */
+typedef struct {
+ /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */
+ int socks_version;
+ /** Name of pluggable transport protocol */
+ char *name;
+ /** Address of proxy */
+ tor_addr_t addr;
+ /** Port of proxy */
+ uint16_t port;
+ /** Boolean: We are re-parsing our transport list, and we are going to remove
+ * this one if we don't find it in the list of configured transports. */
+ unsigned marked_for_removal : 1;
+} transport_t;
+
char *circuit_list_path(origin_circuit_t *circ, int verbose);
char *circuit_list_path_for_controller(origin_circuit_t *circ);
void circuit_log_path(int severity, unsigned int domain,
@@ -44,18 +59,19 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
crypto_pk_env_t *onion_key,
const tor_addr_t *addr, uint16_t port);
-extend_info_t *extend_info_from_router(routerinfo_t *r);
+extend_info_t *extend_info_from_router(const routerinfo_t *r);
+extend_info_t *extend_info_from_node(const node_t *node);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
-routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
+const node_t *build_state_get_exit_node(cpath_build_state_t *state);
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
-void entry_guards_compute_status(or_options_t *options, time_t now);
+void entry_guards_compute_status(const or_options_t *options, time_t now);
int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);
void entry_nodes_should_be_added(void);
-int entry_list_is_constrained(or_options_t *options);
-routerinfo_t *choose_random_entry(cpath_build_state_t *state);
+int entry_list_is_constrained(const or_options_t *options);
+const node_t *choose_random_entry(cpath_build_state_t *state);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
@@ -64,18 +80,23 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
void mark_bridge_list(void);
void sweep_bridge_list(void);
-int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
+void mark_transport_list(void);
+void sweep_transport_list(void);
+
+int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
+int node_is_a_configured_bridge(const node_t *node);
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest);
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *digest);
+ const char *digest,
+ const char *transport_name);
void retry_bridge_descriptor_fetch_directly(const char *digest);
-void fetch_bridge_descriptors(or_options_t *options, time_t now);
+void fetch_bridge_descriptors(const or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
int any_bridge_descriptors_known(void);
int any_pending_bridge_descriptor_fetches(void);
-int entries_known_but_down(or_options_t *options);
-void entries_retry_all(or_options_t *options);
+int entries_known_but_down(const or_options_t *options);
+void entries_retry_all(const or_options_t *options);
void entry_guards_free_all(void);
@@ -124,5 +145,19 @@ void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
int circuit_build_times_get_bw_scale(networkstatus_t *ns);
+void clear_transport_list(void);
+int transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver);
+int transport_add(transport_t *t);
+void transport_free(transport_t *transport);
+transport_t *transport_create(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver);
+
+int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
+ const transport_t **transport);
+transport_t *transport_get_by_name(const char *name);
+
+int validate_pluggable_transports_config(void);
+
#endif
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index b25a71e6bd..25b80f11f3 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -19,6 +19,7 @@
#include "connection_or.h"
#include "control.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "rendclient.h"
@@ -86,10 +87,7 @@ orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
/** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID
* and/or or_connection for circ has just changed from <b>old_conn, old_id</b>
* to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing
- * the old entry (if any) and adding a new one. If <b>active</b> is true,
- * remove the circuit from the list of active circuits on old_conn and add it
- * to the list of active circuits on conn.
- * XXX "active" isn't an arg anymore */
+ * the old entry (if any) and adding a new one. */
static void
circuit_set_circid_orconn_helper(circuit_t *circ, int direction,
circid_t id,
@@ -552,6 +550,16 @@ circuit_free(circuit_t *circ)
crypto_free_pk_env(ocirc->intro_key);
rend_data_free(ocirc->rend_data);
+
+ tor_free(ocirc->dest_address);
+ if (ocirc->socks_username) {
+ memset(ocirc->socks_username, 0x12, ocirc->socks_username_len);
+ tor_free(ocirc->socks_username);
+ }
+ if (ocirc->socks_password) {
+ memset(ocirc->socks_password, 0x06, ocirc->socks_password_len);
+ tor_free(ocirc->socks_password);
+ }
} else {
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
/* Remember cell statistics for this circuit before deallocating. */
@@ -981,7 +989,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0;
int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0;
int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* Make sure we're not trying to create a onehop circ by
* cannibalization. */
@@ -1003,19 +1011,20 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
(!need_capacity || circ->build_state->need_capacity) &&
(internal == circ->build_state->is_internal) &&
circ->remaining_relay_early_cells &&
- !circ->build_state->onehop_tunnel) {
+ !circ->build_state->onehop_tunnel &&
+ !circ->isolation_values_set) {
if (info) {
/* need to make sure we don't duplicate hops */
crypt_path_t *hop = circ->cpath;
- routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
+ const node_t *ri1 = node_get_by_id(info->identity_digest);
do {
- routerinfo_t *ri2;
+ const node_t *ri2;
if (tor_memeq(hop->extend_info->identity_digest,
info->identity_digest, DIGEST_LEN))
goto next;
if (ri1 &&
- (ri2 = router_get_by_digest(hop->extend_info->identity_digest))
- && routers_in_same_family(ri1, ri2))
+ (ri2 = node_get_by_id(hop->extend_info->identity_digest))
+ && nodes_in_same_family(ri1, ri2))
goto next;
hop=hop->next;
} while (hop!=circ->cpath);
@@ -1100,7 +1109,7 @@ void
circuit_expire_all_dirty_circs(void)
{
circuit_t *circ;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
for (circ=global_circuitlist; circ; circ = circ->next) {
if (CIRCUIT_IS_ORIGIN(circ) &&
@@ -1192,7 +1201,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
}
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- int timed_out = (reason == END_STREAM_REASON_TIMEOUT);
+ int timed_out = (reason == END_CIRC_REASON_TIMEOUT);
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
tor_assert(ocirc->build_state->chosen_exit);
tor_assert(ocirc->rend_data);
@@ -1207,7 +1216,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
INTRO_POINT_FAILURE_TIMEOUT :
INTRO_POINT_FAILURE_GENERIC);
} else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
- reason != END_STREAM_REASON_TIMEOUT) {
+ reason != END_CIRC_REASON_TIMEOUT) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
tor_assert(ocirc->build_state->chosen_exit);
tor_assert(ocirc->rend_data);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index f2fd6fe3b4..23efe05348 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -17,6 +17,8 @@
#include "connection.h"
#include "connection_edge.h"
#include "control.h"
+#include "nodelist.h"
+#include "networkstatus.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -38,19 +40,19 @@ static void circuit_increment_failure_count(void);
* Else return 0.
*/
static int
-circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
+circuit_is_acceptable(const origin_circuit_t *origin_circ,
+ const entry_connection_t *conn,
int must_be_open, uint8_t purpose,
int need_uptime, int need_internal,
time_t now)
{
- routerinfo_t *exitrouter;
+ const circuit_t *circ = TO_CIRCUIT(origin_circ);
+ const node_t *exitnode;
cpath_build_state_t *build_state;
tor_assert(circ);
tor_assert(conn);
tor_assert(conn->socks_request);
- if (!CIRCUIT_IS_ORIGIN(circ))
- return 0; /* this circ doesn't start at us */
if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
return 0; /* ignore non-open circs */
if (circ->marked_for_close)
@@ -85,8 +87,8 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
* circuit, it's the magical extra bob hop. so just check the nickname
* of the one we meant to finish at.
*/
- build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- exitrouter = build_state_get_exit_router(build_state);
+ build_state = origin_circ->build_state;
+ exitnode = build_state_get_exit_node(build_state);
if (need_uptime && !build_state->need_uptime)
return 0;
@@ -94,7 +96,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
- if (!exitrouter && !build_state->onehop_tunnel) {
+ if (!exitnode && !build_state->onehop_tunnel) {
log_debug(LD_CIRC,"Not considering circuit with unknown router.");
return 0; /* this circuit is screwed and doesn't know it yet,
* or is a rendezvous circuit. */
@@ -115,7 +117,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
if (tor_digest_is_zero(digest)) {
/* we don't know the digest; have to compare addr:port */
tor_addr_t addr;
- int r = tor_addr_from_str(&addr, conn->socks_request->address);
+ int r = tor_addr_parse(&addr, conn->socks_request->address);
if (r < 0 ||
!tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
build_state->chosen_exit->port != conn->socks_request->port)
@@ -128,30 +130,43 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
}
}
- if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) {
+ if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
/* can't exit from this router */
return 0;
}
} else { /* not general */
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- if ((conn->rend_data && !ocirc->rend_data) ||
- (!conn->rend_data && ocirc->rend_data) ||
- (conn->rend_data && ocirc->rend_data &&
- rend_cmp_service_ids(conn->rend_data->onion_address,
- ocirc->rend_data->onion_address))) {
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ if ((edge_conn->rend_data && !origin_circ->rend_data) ||
+ (!edge_conn->rend_data && origin_circ->rend_data) ||
+ (edge_conn->rend_data && origin_circ->rend_data &&
+ rend_cmp_service_ids(edge_conn->rend_data->onion_address,
+ origin_circ->rend_data->onion_address))) {
/* this circ is not for this conn */
return 0;
}
}
+
+ if (!connection_edge_compatible_with_circuit(conn, origin_circ)) {
+ /* conn needs to be isolated from other conns that have already used
+ * origin_circ */
+ return 0;
+ }
+
return 1;
}
/** Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for
- * <b>purpose</b>, and return 0 otherwise. Used by circuit_get_best.
+ * <b>conn</b>, and return 0 otherwise. Used by circuit_get_best.
*/
static int
-circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
+circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
+ const entry_connection_t *conn)
{
+ const circuit_t *a = TO_CIRCUIT(oa);
+ const circuit_t *b = TO_CIRCUIT(ob);
+ const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose;
+ int a_bits, b_bits;
+
switch (purpose) {
case CIRCUIT_PURPOSE_C_GENERAL:
/* if it's used but less dirty it's best;
@@ -165,8 +180,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
if (a->timestamp_dirty ||
timercmp(&a->timestamp_created, &b->timestamp_created, >))
return 1;
- if (CIRCUIT_IS_ORIGIN(b) &&
- TO_ORIGIN_CIRCUIT(b)->build_state->is_internal)
+ if (ob->build_state->is_internal)
/* XXX023 what the heck is this internal thing doing here. I
* think we can get rid of it. circuit_is_acceptable() already
* makes sure that is_internal is exactly what we need it to
@@ -185,6 +199,29 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
return 1;
break;
}
+
+ /* XXXX023 Maybe this check should get a higher priority to avoid
+ * using up circuits too rapidly. */
+
+ a_bits = connection_edge_update_circuit_isolation(conn,
+ (origin_circuit_t*)oa, 1);
+ b_bits = connection_edge_update_circuit_isolation(conn,
+ (origin_circuit_t*)ob, 1);
+ /* if x_bits < 0, then we have not used x for anything; better not to dirty
+ * a connection if we can help it. */
+ if (a_bits < 0) {
+ return 0;
+ } else if (b_bits < 0) {
+ return 1;
+ }
+ a_bits &= ~ oa->isolation_flags_mixed;
+ a_bits &= ~ ob->isolation_flags_mixed;
+ if (n_bits_set_u8(a_bits) < n_bits_set_u8(b_bits)) {
+ /* The fewer new restrictions we need to make on a circuit for stream
+ * isolation, the better. */
+ return 1;
+ }
+
return 0;
}
@@ -205,10 +242,12 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
* closest introduce-purposed circuit that you can find.
*/
static origin_circuit_t *
-circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
+circuit_get_best(const entry_connection_t *conn,
+ int must_be_open, uint8_t purpose,
int need_uptime, int need_internal)
{
- circuit_t *circ, *best=NULL;
+ circuit_t *circ;
+ origin_circuit_t *best=NULL;
struct timeval now;
int intro_going_on_but_too_old = 0;
@@ -221,7 +260,11 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
tor_gettimeofday(&now);
for (circ=global_circuitlist;circ;circ = circ->next) {
- if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,
+ origin_circuit_t *origin_circ;
+ if (!CIRCUIT_IS_ORIGIN(circ))
+ continue;
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose,
need_uptime,need_internal,now.tv_sec))
continue;
@@ -235,8 +278,8 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
/* now this is an acceptable circ to hand back. but that doesn't
* mean it's the *best* circ to hand back. try to decide.
*/
- if (!best || circuit_is_better(circ,best,purpose))
- best = circ;
+ if (!best || circuit_is_better(origin_circ,best,conn))
+ best = origin_circ;
}
if (!best && intro_going_on_but_too_old)
@@ -244,7 +287,28 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
"right now, but it has already taken quite a while. Starting "
"one in parallel.");
- return best ? TO_ORIGIN_CIRCUIT(best) : NULL;
+ return best;
+}
+
+/** Return the number of not-yet-open general-purpose origin circuits. */
+static int
+count_pending_general_client_circuits(void)
+{
+ const circuit_t *circ;
+
+ int count = 0;
+
+ for (circ = global_circuitlist; circ; circ = circ->next) {
+ if (circ->marked_for_close ||
+ circ->state == CIRCUIT_STATE_OPEN ||
+ circ->purpose != CIRCUIT_PURPOSE_C_GENERAL ||
+ !CIRCUIT_IS_ORIGIN(circ))
+ continue;
+
+ ++count;
+ }
+
+ return count;
}
#if 0
@@ -481,11 +545,11 @@ circuit_remove_handled_ports(smartlist_t *needed_ports)
* Else return 0.
*/
int
-circuit_stream_is_being_handled(edge_connection_t *conn,
+circuit_stream_is_being_handled(entry_connection_t *conn,
uint16_t port, int min)
{
circuit_t *circ;
- routerinfo_t *exitrouter;
+ const node_t *exitnode;
int num=0;
time_t now = time(NULL);
int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
@@ -501,14 +565,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
if (build_state->is_internal || build_state->onehop_tunnel)
continue;
- exitrouter = build_state_get_exit_router(build_state);
- if (exitrouter && (!need_uptime || build_state->need_uptime)) {
+ exitnode = build_state_get_exit_node(build_state);
+ if (exitnode && (!need_uptime || build_state->need_uptime)) {
int ok;
if (conn) {
- ok = connection_ap_can_use_exit(conn, exitrouter);
+ ok = connection_ap_can_use_exit(conn, exitnode);
} else {
- addr_policy_result_t r = compare_addr_to_addr_policy(
- 0, port, exitrouter->exit_policy);
+ addr_policy_result_t r;
+ r = compare_tor_addr_to_node_policy(NULL, port, exitnode);
ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
}
if (ok) {
@@ -575,7 +639,7 @@ circuit_predict_and_launch_new(void)
log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another exit circ.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -587,7 +651,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d internal), need another internal "
"circ for my hidden service.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -605,7 +669,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d uptime-internal, %d internal), need"
" another hidden service circ.",
num, num_uptime_internal, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -618,7 +682,7 @@ circuit_predict_and_launch_new(void)
flags = CIRCLAUNCH_NEED_CAPACITY;
log_info(LD_CIRC,
"Have %d clean circs need another buildtime test circ.", num);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
}
@@ -635,7 +699,7 @@ void
circuit_build_needed_circs(time_t now)
{
static time_t time_to_new_circuit = 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* launch a new circ for any pending streams that need one */
connection_ap_attach_pending();
@@ -654,9 +718,9 @@ circuit_build_needed_circs(time_t now)
circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL);
if (get_options()->RunTesting &&
circ &&
- circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
+ circ->timestamp_created.tv_sec + TESTING_CIRCUIT_INTERVAL < now) {
log_fn(LOG_INFO,"Creating a new testing circuit.");
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0);
}
#endif
}
@@ -675,7 +739,11 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
tor_assert(circ);
tor_assert(conn);
- conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
+ if (conn->_base.type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ entry_conn->may_use_optimistic_data = 0;
+ }
+ conn->cpath_layer = NULL; /* don't keep a stale pointer */
conn->on_circuit = NULL;
if (CIRCUIT_IS_ORIGIN(circ)) {
@@ -936,6 +1004,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
void
circuit_has_opened(origin_circuit_t *circ)
{
+ int can_try_clearing_isolation = 0, tried_clearing_isolation = 0;
control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0);
/* Remember that this circuit has finished building. Now if we start
@@ -943,9 +1012,12 @@ circuit_has_opened(origin_circuit_t *circ)
* to consider its build time. */
circ->has_opened = 1;
+ again:
+
switch (TO_CIRCUIT(circ)->purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
rend_client_rendcirc_has_opened(circ);
+ can_try_clearing_isolation = 1;
connection_ap_attach_pending();
break;
case CIRCUIT_PURPOSE_C_INTRODUCING:
@@ -954,6 +1026,7 @@ circuit_has_opened(origin_circuit_t *circ)
case CIRCUIT_PURPOSE_C_GENERAL:
/* Tell any AP connections that have been waiting for a new
* circuit that one is ready. */
+ can_try_clearing_isolation = 1;
connection_ap_attach_pending();
break;
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
@@ -971,6 +1044,24 @@ circuit_has_opened(origin_circuit_t *circ)
* This won't happen in normal operation, but might happen if the
* controller did it. Just let it slide. */
}
+
+ if (/* The circuit may have become non-open if it was cannibalized.*/
+ circ->_base.state == CIRCUIT_STATE_OPEN &&
+ /* Only if the purpose is clearable, and only if we haven't tried
+ * to clear isolation yet, do we try. */
+ can_try_clearing_isolation && !tried_clearing_isolation &&
+ /* If !isolation_values_set, there is nothing to clear. */
+ circ->isolation_values_set &&
+ /* It's not legal to clear a circuit's isolation info if it's ever had
+ * streams attached */
+ !circ->isolation_any_streams_attached) {
+ /* If we have any isolation information set on this circuit, and
+ * we didn't manage to attach any streams to it, then we can
+ * and should clear it and try again. */
+ circuit_clear_isolation(circ);
+ tried_clearing_isolation = 1;
+ goto again;
+ }
}
/** Called whenever a circuit could not be successfully built.
@@ -1091,17 +1182,9 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
origin_circuit_t *
-circuit_launch_by_router(uint8_t purpose,
- routerinfo_t *exit, int flags)
+circuit_launch(uint8_t purpose, int flags)
{
- origin_circuit_t *circ;
- extend_info_t *info = NULL;
- if (exit)
- info = extend_info_from_router(exit);
- circ = circuit_launch_by_extend_info(purpose, info, flags);
-
- extend_info_free(info);
- return circ;
+ return circuit_launch_by_extend_info(purpose, NULL, flags);
}
/** Launch a new circuit with purpose <b>purpose</b> and exit node
@@ -1207,7 +1290,7 @@ circuit_reset_failure_count(int timeout)
* Write the found or in-progress or launched circ into *circp.
*/
static int
-circuit_get_open_circ_or_launch(edge_connection_t *conn,
+circuit_get_open_circ_or_launch(entry_connection_t *conn,
uint8_t desired_circuit_purpose,
origin_circuit_t **circp)
{
@@ -1215,15 +1298,15 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
int check_exit_policy;
int need_uptime, need_internal;
int want_onehop;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
tor_assert(circp);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_CIRCUIT_WAIT);
check_exit_policy =
conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir &&
- !connection_edge_is_rendezvous_stream(conn);
+ !connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn));
want_onehop = conn->want_onehop;
need_uptime = !conn->want_onehop && !conn->use_begindir &&
@@ -1269,12 +1352,14 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (check_exit_policy) {
if (!conn->chosen_exit_name) {
struct in_addr in;
- uint32_t addr = 0;
- if (tor_inet_aton(conn->socks_request->address, &in))
- addr = ntohl(in.s_addr);
- if (router_exit_policy_all_routers_reject(addr,
- conn->socks_request->port,
- need_uptime)) {
+ tor_addr_t addr, *addrp=NULL;
+ if (tor_inet_aton(conn->socks_request->address, &in)) {
+ tor_addr_from_in(&addr, &in);
+ addrp = &addr;
+ }
+ if (router_exit_policy_all_nodes_reject(addrp,
+ conn->socks_request->port,
+ need_uptime)) {
log_notice(LD_APP,
"No Tor server allows exit to %s:%d. Rejecting.",
safe_str_client(conn->socks_request->address),
@@ -1284,9 +1369,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
} else {
/* XXXX023 Duplicates checks in connection_ap_handshake_attach_circuit:
* refactor into a single function? */
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (router && !connection_ap_can_use_exit(conn, router)) {
+ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' is excluded or "
"would refuse request. %s.",
@@ -1312,22 +1397,37 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (!circ) {
extend_info_t *extend_info=NULL;
uint8_t new_circ_purpose;
+ const int n_pending = count_pending_general_client_circuits();
+
+ if (n_pending >= options->MaxClientCircuitsPending) {
+ static ratelim_t delay_limit = RATELIM_INIT(10*60);
+ char *m;
+ if ((m = rate_limit_log(&delay_limit, approx_time()))) {
+ log_notice(LD_APP, "We'd like to launch a circuit to handle a "
+ "connection, but we already have %d general-purpose client "
+ "circuits pending. Waiting until some finish.",
+ n_pending);
+ tor_free(m);
+ }
+ return 0;
+ }
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */
- tor_assert(conn->rend_data);
- extend_info = rend_client_get_random_intro(conn->rend_data);
+ rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
+ tor_assert(rend_data);
+ extend_info = rend_client_get_random_intro(rend_data);
if (!extend_info) {
log_info(LD_REND,
"No intro points for '%s': re-fetching service descriptor.",
- safe_str_client(conn->rend_data->onion_address));
- rend_client_refetch_v2_renddesc(conn->rend_data);
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ safe_str_client(rend_data->onion_address));
+ rend_client_refetch_v2_renddesc(rend_data);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_RENDDESC_WAIT;
return 0;
}
log_info(LD_REND,"Chose %s as intro point for '%s'.",
extend_info_describe(extend_info),
- safe_str_client(conn->rend_data->onion_address));
+ safe_str_client(rend_data->onion_address));
}
/* If we have specified a particular exit node for our
@@ -1335,11 +1435,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
*/
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
- routerinfo_t *r;
+ const node_t *r;
int opt = conn->chosen_exit_optional;
- r = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (r) {
- extend_info = extend_info_from_router(r);
+ r = node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (r && node_has_descriptor(r)) {
+ extend_info = extend_info_from_node(r);
} else {
log_debug(LD_DIR, "considering %d, %s",
want_onehop, conn->chosen_exit_name);
@@ -1354,7 +1454,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
log_info(LD_DIR, "Broken exit digest on tunnel conn. Closing.");
return -1;
}
- if (tor_addr_from_str(&addr, conn->socks_request->address) < 0) {
+ if (tor_addr_parse(&addr, conn->socks_request->address) < 0) {
log_info(LD_DIR, "Broken address %s on tunnel conn. Closing.",
escaped_safe_str_client(conn->socks_request->address));
return -1;
@@ -1416,18 +1516,26 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
rep_hist_note_used_internal(time(NULL), need_uptime, 1);
if (circ) {
/* write the service_id into circ */
- circ->rend_data = rend_data_dup(conn->rend_data);
+ circ->rend_data = rend_data_dup(ENTRY_TO_EDGE_CONN(conn)->rend_data);
if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
circ->_base.state == CIRCUIT_STATE_OPEN)
rend_client_rendcirc_has_opened(circ);
}
}
- }
- if (!circ)
+ } /* endif (!circ) */
+ if (circ) {
+ /* Mark the circuit with the isolation fields for this connection.
+ * When the circuit arrives, we'll clear these flags: this is
+ * just some internal bookkeeping to make sure that we have
+ * launched enough circuits.
+ */
+ connection_edge_update_circuit_isolation(conn, circ, 0);
+ } else {
log_info(LD_APP,
"No safe circuit (purpose %d) ready for edge "
"connection; delaying.",
desired_circuit_purpose);
+ }
*circp = circ;
return 0;
}
@@ -1446,46 +1554,86 @@ cpath_is_on_circuit(origin_circuit_t *circ, crypt_path_t *crypt_path)
return 0;
}
+/** Return true iff client-side optimistic data is supported. */
+static int
+optimistic_data_enabled(void)
+{
+ const or_options_t *options = get_options();
+ if (options->OptimisticData < 0) {
+ /* XXX023 consider having auto default to 1 rather than 0 before
+ * the 0.2.3 branch goes stable. See bug 3617. -RD */
+ const int32_t enabled =
+ networkstatus_get_param(NULL, "UseOptimisticData", 0, 0, 1);
+ return (int)enabled;
+ }
+ return options->OptimisticData;
+}
+
/** Attach the AP stream <b>apconn</b> to circ's linked list of
* p_streams. Also set apconn's cpath_layer to <b>cpath</b>, or to the last
* hop in circ's cpath if <b>cpath</b> is NULL.
*/
static void
-link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
+link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
crypt_path_t *cpath)
{
+ const node_t *exitnode;
+
/* add it into the linked list of streams on this circuit */
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
circ->_base.n_circ_id);
/* reset it, so we can measure circ timeouts */
- apconn->_base.timestamp_lastread = time(NULL);
- apconn->next_stream = circ->p_streams;
- apconn->on_circuit = TO_CIRCUIT(circ);
+ ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL);
+ ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams;
+ ENTRY_TO_EDGE_CONN(apconn)->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */
- circ->p_streams = apconn;
+ circ->p_streams = ENTRY_TO_EDGE_CONN(apconn);
- if (connection_edge_is_rendezvous_stream(apconn)) {
+ if (connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(apconn))) {
/* We are attaching a stream to a rendezvous circuit. That means
* that an attempt to connect to a hidden service just
* succeeded. Tell rendclient.c. */
- rend_client_note_connection_attempt_ended(apconn->rend_data->onion_address);
+ rend_client_note_connection_attempt_ended(
+ ENTRY_TO_EDGE_CONN(apconn)->rend_data->onion_address);
}
if (cpath) { /* we were given one; use it */
tor_assert(cpath_is_on_circuit(circ, cpath));
- apconn->cpath_layer = cpath;
- } else { /* use the last hop in the circuit */
+ } else {
+ /* use the last hop in the circuit */
tor_assert(circ->cpath);
tor_assert(circ->cpath->prev);
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
- apconn->cpath_layer = circ->cpath->prev;
+ cpath = circ->cpath->prev;
+ }
+ ENTRY_TO_EDGE_CONN(apconn)->cpath_layer = cpath;
+
+ circ->isolation_any_streams_attached = 1;
+ connection_edge_update_circuit_isolation(apconn, circ, 0);
+
+ /* See if we can use optimistic data on this circuit */
+ if (cpath->extend_info &&
+ (exitnode = node_get_by_id(cpath->extend_info->identity_digest)) &&
+ exitnode->rs) {
+ /* Okay; we know what exit node this is. */
+ if (optimistic_data_enabled() &&
+ circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL &&
+ exitnode->rs->version_supports_optimistic_data)
+ apconn->may_use_optimistic_data = 1;
+ else
+ apconn->may_use_optimistic_data = 0;
+ log_info(LD_APP, "Looks like completed circuit to %s %s allow "
+ "optimistic data for connection to %s",
+ safe_str_client(node_describe(exitnode)),
+ apconn->may_use_optimistic_data ? "does" : "doesn't",
+ safe_str_client(apconn->socks_request->address));
}
}
/** Return true iff <b>address</b> is matched by one of the entries in
* TrackHostExits. */
int
-hostname_in_track_host_exits(or_options_t *options, const char *address)
+hostname_in_track_host_exits(const or_options_t *options, const char *address)
{
if (!options->TrackHostExits)
return 0;
@@ -1507,9 +1655,10 @@ hostname_in_track_host_exits(or_options_t *options, const char *address)
* <b>conn</b>'s destination.
*/
static void
-consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
+consider_recording_trackhost(const entry_connection_t *conn,
+ const origin_circuit_t *circ)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *new_address = NULL;
char fp[HEX_DIGEST_LEN+1];
@@ -1544,18 +1693,19 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
* indicated by <b>cpath</b>, or from the last hop in circ's cpath if
* <b>cpath</b> is NULL. */
int
-connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
+connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_assert(conn);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT ||
- conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT ||
+ base_conn->state == AP_CONN_STATE_CONTROLLER_WAIT);
tor_assert(conn->socks_request);
tor_assert(circ);
tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN);
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if (!circ->_base.timestamp_dirty)
circ->_base.timestamp_dirty = time(NULL);
@@ -1585,21 +1735,22 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
/* XXXX this function should mark for close whenever it returns -1;
* its callers shouldn't have to worry about that. */
int
-connection_ap_handshake_attach_circuit(edge_connection_t *conn)
+connection_ap_handshake_attach_circuit(entry_connection_t *conn)
{
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
int retval;
int conn_age;
int want_onehop;
tor_assert(conn);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->socks_request);
want_onehop = conn->want_onehop;
- conn_age = (int)(time(NULL) - conn->_base.timestamp_created);
+ conn_age = (int)(time(NULL) - base_conn->timestamp_created);
if (conn_age >= get_options()->SocksTimeout) {
- int severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) ?
+ int severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port) ?
LOG_INFO : LOG_NOTICE;
log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. Giving up.",
@@ -1608,13 +1759,14 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
return -1;
}
- if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */
+ if (!connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn))) {
+ /* we're a general conn */
origin_circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (!router && !want_onehop) {
+ if (!node && !want_onehop) {
/* We ran into this warning when trying to extend a circuit to a
* hidden service directory for which we didn't have a router
* descriptor. See flyspray task 767 for more details. We should
@@ -1630,7 +1782,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
}
return -1;
}
- if (router && !connection_ap_can_use_exit(conn, router)) {
+ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' is excluded or "
"would refuse request. %s.",
@@ -1663,7 +1815,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
} else { /* we're a rendezvous conn */
origin_circuit_t *rendcirc=NULL, *introcirc=NULL;
- tor_assert(!conn->cpath_layer);
+ tor_assert(!ENTRY_TO_EDGE_CONN(conn)->cpath_layer);
/* start by finding a rendezvous circuit for us */
@@ -1719,8 +1871,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
!c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) {
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c);
if (oc->rend_data &&
- !rend_cmp_service_ids(conn->rend_data->onion_address,
- oc->rend_data->onion_address)) {
+ !rend_cmp_service_ids(
+ ENTRY_TO_EDGE_CONN(conn)->rend_data->onion_address,
+ oc->rend_data->onion_address)) {
log_info(LD_REND|LD_CIRC, "Closing introduction circuit that we "
"built in parallel.");
circuit_mark_for_close(c, END_CIRC_REASON_TIMEOUT);
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index bfeaea20dc..9867fd8205 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -14,7 +14,7 @@
void circuit_expire_building(void);
void circuit_remove_handled_ports(smartlist_t *needed_ports);
-int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port,
+int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port,
int min);
#if 0
int circuit_conforms_to_options(const origin_circuit_t *circ,
@@ -43,15 +43,15 @@ void circuit_build_failed(origin_circuit_t *circ);
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
-origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
- routerinfo_t *exit, int flags);
+origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
void circuit_reset_failure_count(int timeout);
-int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
+int connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
+int connection_ap_handshake_attach_circuit(entry_connection_t *conn);
-int hostname_in_track_host_exits(or_options_t *options, const char *address);
+int hostname_in_track_host_exits(const or_options_t *options,
+ const char *address);
#endif
diff --git a/src/or/command.c b/src/or/command.c
index 12b4c30f5c..023f2bead5 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -25,6 +25,7 @@
#include "control.h"
#include "cpuworker.h"
#include "hibernate.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "router.h"
@@ -45,6 +46,15 @@ uint64_t stats_n_versions_cells_processed = 0;
/** How many CELL_NETINFO cells have we received, ever? */
uint64_t stats_n_netinfo_cells_processed = 0;
+/** How many CELL_VPADDING cells have we received, ever? */
+uint64_t stats_n_vpadding_cells_processed = 0;
+/** How many CELL_CERTS cells have we received, ever? */
+uint64_t stats_n_certs_cells_processed = 0;
+/** How many CELL_AUTH_CHALLENGE cells have we received, ever? */
+uint64_t stats_n_auth_challenge_cells_processed = 0;
+/** How many CELL_AUTHENTICATE cells have we received, ever? */
+uint64_t stats_n_authenticate_cells_processed = 0;
+
/* These are the main functions for processing cells */
static void command_process_create_cell(cell_t *cell, or_connection_t *conn);
static void command_process_created_cell(cell_t *cell, or_connection_t *conn);
@@ -53,6 +63,12 @@ static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
static void command_process_versions_cell(var_cell_t *cell,
or_connection_t *conn);
static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn);
+static void command_process_certs_cell(var_cell_t *cell,
+ or_connection_t *conn);
+static void command_process_auth_challenge_cell(var_cell_t *cell,
+ or_connection_t *conn);
+static void command_process_authenticate_cell(var_cell_t *cell,
+ or_connection_t *conn);
#ifdef KEEP_TIMING_STATS
/** This is a wrapper function around the actual function that processes the
@@ -92,7 +108,7 @@ command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time,
void
command_process_cell(cell_t *cell, or_connection_t *conn)
{
- int handshaking = (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING);
+ int handshaking = (conn->_base.state != OR_CONN_STATE_OPEN);
#ifdef KEEP_TIMING_STATS
/* how many of each cell have we seen so far this second? needs better
* name. */
@@ -132,10 +148,22 @@ command_process_cell(cell_t *cell, or_connection_t *conn)
#define PROCESS_CELL(tp, cl, cn) command_process_ ## tp ## _cell(cl, cn)
#endif
+ if (conn->_base.marked_for_close)
+ return;
+
/* Reject all but VERSIONS and NETINFO when handshaking. */
+ /* (VERSIONS should actually be impossible; it's variable-length.) */
if (handshaking && cell->command != CELL_VERSIONS &&
- cell->command != CELL_NETINFO)
+ cell->command != CELL_NETINFO) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received unexpected cell command %d in state %s; ignoring it.",
+ (int)cell->command,
+ conn_state_to_string(CONN_TYPE_OR,conn->_base.state));
return;
+ }
+
+ if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
+ or_handshake_state_record_cell(conn->handshake_state, cell, 1);
switch (cell->command) {
case CELL_PADDING:
@@ -186,39 +214,101 @@ command_process_var_cell(var_cell_t *cell, or_connection_t *conn)
#ifdef KEEP_TIMING_STATS
/* how many of each cell have we seen so far this second? needs better
* name. */
- static int num_versions=0, num_cert=0;
+ static int num_versions=0, num_certs=0;
time_t now = time(NULL);
if (now > current_second) { /* the second has rolled over */
/* print stats */
log_info(LD_OR,
- "At end of second: %d versions (%d ms), %d cert (%d ms)",
+ "At end of second: %d versions (%d ms), %d certs (%d ms)",
num_versions, versions_time/1000,
- cert, cert_time/1000);
+ num_certs, certs_time/1000);
- num_versions = num_cert = 0;
- versions_time = cert_time = 0;
+ num_versions = num_certs = 0;
+ versions_time = certs_time = 0;
/* remember which second it is, for next time */
current_second = now;
}
#endif
- /* reject all when not handshaking. */
- if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING)
+ if (conn->_base.marked_for_close)
return;
+ switch (conn->_base.state)
+ {
+ case OR_CONN_STATE_OR_HANDSHAKING_V2:
+ if (cell->command != CELL_VERSIONS)
+ return;
+ break;
+ case OR_CONN_STATE_TLS_HANDSHAKING:
+ /* If we're using bufferevents, it's entirely possible for us to
+ * notice "hey, data arrived!" before we notice "hey, the handshake
+ * finished!" And we need to be accepting both at once to handle both
+ * the v2 and v3 handshakes. */
+
+ /* fall through */
+ case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
+ if (cell->command != CELL_VERSIONS) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received a non-VERSIONS cell with command %d in state %s; "
+ "ignoring it.",
+ (int)cell->command,
+ conn_state_to_string(CONN_TYPE_OR,conn->_base.state));
+ return;
+ }
+ break;
+ case OR_CONN_STATE_OR_HANDSHAKING_V3:
+ if (cell->command != CELL_AUTHENTICATE)
+ or_handshake_state_record_var_cell(conn->handshake_state, cell, 1);
+ break; /* Everything is allowed */
+ case OR_CONN_STATE_OPEN:
+ if (conn->link_proto < 3) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received a variable-length cell with command %d in state %s "
+ "with link protocol %d; ignoring it.",
+ (int)cell->command,
+ conn_state_to_string(CONN_TYPE_OR,conn->_base.state),
+ (int)conn->link_proto);
+ return;
+ }
+ break;
+ default:
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received var-length cell with command %d in unexpected state "
+ "%s [%d]; ignoring it.",
+ (int)cell->command,
+ conn_state_to_string(CONN_TYPE_OR,conn->_base.state),
+ (int)conn->_base.state);
+ return;
+ }
+
switch (cell->command) {
case CELL_VERSIONS:
++stats_n_versions_cells_processed;
PROCESS_CELL(versions, cell, conn);
break;
+ case CELL_VPADDING:
+ ++stats_n_vpadding_cells_processed;
+ /* Do nothing */
+ break;
+ case CELL_CERTS:
+ ++stats_n_certs_cells_processed;
+ PROCESS_CELL(certs, cell, conn);
+ break;
+ case CELL_AUTH_CHALLENGE:
+ ++stats_n_auth_challenge_cells_processed;
+ PROCESS_CELL(auth_challenge, cell, conn);
+ break;
+ case CELL_AUTHENTICATE:
+ ++stats_n_authenticate_cells_processed;
+ PROCESS_CELL(authenticate, cell, conn);
+ break;
default:
- log_warn(LD_BUG,
+ log_fn(LOG_INFO, LD_PROTOCOL,
"Variable-length cell of unknown type (%d) received.",
cell->command);
- tor_fragile_assert();
break;
}
}
@@ -232,6 +322,7 @@ static void
command_process_create_cell(cell_t *cell, or_connection_t *conn)
{
or_circuit_t *circ;
+ const or_options_t *options = get_options();
int id_is_high;
if (we_are_hibernating()) {
@@ -243,9 +334,11 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
return;
}
- if (!server_mode(get_options())) {
+ if (!server_mode(options) ||
+ (!public_server_mode(options) && conn->is_outgoing)) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received create cell (type %d) from %s:%d, but we're a client. "
+ "Received create cell (type %d) from %s:%d, but we're connected "
+ "to it as a client. "
"Sending back a destroy.",
(int)cell->command, conn->_base.address, conn->_base.port);
connection_or_send_destroy(cell->circ_id, conn,
@@ -267,15 +360,18 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
}
if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
- routerinfo_t *router = router_get_by_digest(conn->identity_digest);
+ const node_t *node = node_get_by_id(conn->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).",
cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
- if (router)
+ if (node) {
+ char *p = esc_for_log(node_get_platform(node));
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Details: router %s, platform %s.",
- router_describe(router), escaped(router->platform));
+ node_describe(node), p);
+ tor_free(p);
+ }
return;
}
@@ -305,7 +401,13 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
* a CPU worker. */
char keys[CPATH_KEY_MATERIAL_LEN];
char reply[DIGEST_LEN*2];
+
tor_assert(cell->command == CELL_CREATE_FAST);
+
+ /* Make sure we never try to use the OR connection on which we
+ * received this cell to satisfy an EXTEND request, */
+ conn->is_connection_with_client = 1;
+
if (fast_server_handshake(cell->payload, (uint8_t*)reply,
(uint8_t*)keys, sizeof(keys))<0) {
log_warn(LD_OR,"Failed to generate key material. Closing.");
@@ -501,14 +603,40 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn)
{
int highest_supported_version = 0;
const uint8_t *cp, *end;
+ const int started_here = connection_or_nonopen_was_started_here(conn);
if (conn->link_proto != 0 ||
- conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING ||
(conn->handshake_state && conn->handshake_state->received_versions)) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
"Received a VERSIONS cell on a connection with its version "
"already set to %d; dropping", (int) conn->link_proto);
return;
}
+ switch (conn->_base.state)
+ {
+ case OR_CONN_STATE_OR_HANDSHAKING_V2:
+ break;
+ case OR_CONN_STATE_TLS_HANDSHAKING:
+ case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
+ if (started_here) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Received a versions cell while TLS-handshaking not in "
+ "OR_HANDSHAKING_V3 on a connection we originated.");
+ }
+ conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
+ if (connection_init_or_handshake_state(conn, started_here) < 0) {
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ or_handshake_state_record_var_cell(conn->handshake_state, cell, 1);
+ break;
+ case OR_CONN_STATE_OR_HANDSHAKING_V3:
+ break;
+ default:
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "VERSIONS cell while in unexpected state");
+ return;
+ }
+
tor_assert(conn->handshake_state);
end = cell->payload + cell->payload_len;
for (cp = cell->payload; cp+1 < end; ++cp) {
@@ -530,19 +658,87 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn)
"That's crazily non-compliant. Closing connection.");
connection_mark_for_close(TO_CONN(conn));
return;
+ } else if (highest_supported_version < 3 &&
+ conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Negotiated link protocol 2 or lower after doing a v3 TLS "
+ "handshake. Closing connection.");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
}
+
conn->link_proto = highest_supported_version;
conn->handshake_state->received_versions = 1;
- log_info(LD_OR, "Negotiated version %d with %s:%d; sending NETINFO.",
- highest_supported_version,
- safe_str_client(conn->_base.address),
- conn->_base.port);
- tor_assert(conn->link_proto >= 2);
+ if (conn->link_proto == 2) {
+ log_info(LD_OR, "Negotiated version %d with %s:%d; sending NETINFO.",
+ highest_supported_version,
+ safe_str_client(conn->_base.address),
+ conn->_base.port);
- if (connection_or_send_netinfo(conn) < 0) {
- connection_mark_for_close(TO_CONN(conn));
- return;
+ if (connection_or_send_netinfo(conn) < 0) {
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ } else {
+ const int send_versions = !started_here;
+ /* If we want to authenticate, send a CERTS cell */
+ const int send_certs = !started_here || public_server_mode(get_options());
+ /* If we're a relay that got a connection, ask for authentication. */
+ const int send_chall = !started_here && public_server_mode(get_options());
+ /* If our certs cell will authenticate us, or if we have no intention of
+ * authenticating, send a netinfo cell right now. */
+ const int send_netinfo =
+ !(started_here && public_server_mode(get_options()));
+ const int send_any =
+ send_versions || send_certs || send_chall || send_netinfo;
+ tor_assert(conn->link_proto >= 3);
+
+ log_info(LD_OR, "Negotiated version %d with %s:%d; %s%s%s%s%s",
+ highest_supported_version,
+ safe_str_client(conn->_base.address),
+ conn->_base.port,
+ send_any ? "Sending cells:" : "Waiting for CERTS cell",
+ send_versions ? " VERSIONS" : "",
+ send_certs ? " CERTS" : "",
+ send_chall ? " AUTH_CHALLENGE" : "",
+ send_netinfo ? " NETINFO" : "");
+
+#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE
+ if (1) {
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+#endif
+
+ if (send_versions) {
+ if (connection_or_send_versions(conn, 1) < 0) {
+ log_warn(LD_OR, "Couldn't send versions cell");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+ if (send_certs) {
+ if (connection_or_send_certs_cell(conn) < 0) {
+ log_warn(LD_OR, "Couldn't send certs cell");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+ if (send_chall) {
+ if (connection_or_send_auth_challenge_cell(conn) < 0) {
+ log_warn(LD_OR, "Couldn't send auth_challenge cell");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+ if (send_netinfo) {
+ if (connection_or_send_netinfo(conn) < 0) {
+ log_warn(LD_OR, "Couldn't send netinfo cell");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
}
}
@@ -568,13 +764,41 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
conn->link_proto == 0 ? "non-versioned" : "a v1");
return;
}
- if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) {
+ if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
+ conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
"Received a NETINFO cell on non-handshaking connection; dropping.");
return;
}
tor_assert(conn->handshake_state &&
conn->handshake_state->received_versions);
+
+ if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) {
+ tor_assert(conn->link_proto >= 3);
+ if (conn->handshake_state->started_here) {
+ if (!conn->handshake_state->authenticated) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got a NETINFO cell from server, "
+ "but no authentication. Closing the connection.");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ } else {
+ /* we're the server. If the client never authenticated, we have
+ some housekeeping to do.*/
+ if (!conn->handshake_state->authenticated) {
+ tor_assert(tor_digest_is_zero(
+ (const char*)conn->handshake_state->authenticated_peer_id));
+ connection_or_set_circid_type(conn, NULL);
+
+ connection_or_init_conn_from_address(conn,
+ &conn->_base.addr,
+ conn->_base.port,
+ (const char*)conn->handshake_state->authenticated_peer_id,
+ 0);
+ }
+ }
+ }
+
/* Decode the cell. */
timestamp = ntohl(get_uint32(cell->payload));
if (labs(now - conn->handshake_state->sent_versions_at) < 180) {
@@ -620,7 +844,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
/** Warn when we get a netinfo skew with at least this value. */
#define NETINFO_NOTICE_SKEW 3600
if (labs(apparent_skew) > NETINFO_NOTICE_SKEW &&
- router_get_by_digest(conn->identity_digest)) {
+ router_get_by_id_digest(conn->identity_digest)) {
char dbuf[64];
int severity;
/*XXXX be smarter about when everybody says we are skewed. */
@@ -647,13 +871,409 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
* trustworthy. */
(void)my_apparent_addr;
- if (connection_or_set_state_open(conn)<0)
+ if (connection_or_set_state_open(conn)<0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got good NETINFO cell from %s:%d; but "
+ "was unable to make the OR connection become open.",
+ safe_str_client(conn->_base.address),
+ conn->_base.port);
connection_mark_for_close(TO_CONN(conn));
- else
+ } else {
log_info(LD_OR, "Got good NETINFO cell from %s:%d; OR connection is now "
- "open, using protocol version %d",
+ "open, using protocol version %d. Its ID digest is %s",
safe_str_client(conn->_base.address),
- conn->_base.port, (int)conn->link_proto);
+ conn->_base.port, (int)conn->link_proto,
+ hex_str(conn->identity_digest, DIGEST_LEN));
+ }
assert_connection_ok(TO_CONN(conn),time(NULL));
}
+/** Process a CERTS cell from an OR connection.
+ *
+ * If the other side should not have sent us a CERTS cell, or the cell is
+ * malformed, or it is supposed to authenticate the TLS key but it doesn't,
+ * then mark the connection.
+ *
+ * If the cell has a good cert chain and we're doing a v3 handshake, then
+ * store the certificates in or_handshake_state. If this is the client side
+ * of the connection, we then authenticate the server or mark the connection.
+ * If it's the server side, wait for an AUTHENTICATE cell.
+ */
+static void
+command_process_certs_cell(var_cell_t *cell, or_connection_t *conn)
+{
+#define ERR(s) \
+ do { \
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
+ "Received a bad CERTS cell from %s:%d: %s", \
+ safe_str(conn->_base.address), conn->_base.port, (s)); \
+ connection_mark_for_close(TO_CONN(conn)); \
+ goto err; \
+ } while (0)
+
+ tor_cert_t *link_cert = NULL;
+ tor_cert_t *id_cert = NULL;
+ tor_cert_t *auth_cert = NULL;
+
+ uint8_t *ptr;
+ int n_certs, i;
+
+ if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3)
+ ERR("We're not doing a v3 handshake!");
+ if (conn->link_proto < 3)
+ ERR("We're not using link protocol >= 3");
+ if (conn->handshake_state->received_certs_cell)
+ ERR("We already got one");
+ if (conn->handshake_state->authenticated) {
+ /* Should be unreachable, but let's make sure. */
+ ERR("We're already authenticated!");
+ }
+ if (cell->payload_len < 1)
+ ERR("It had no body");
+ if (cell->circ_id)
+ ERR("It had a nonzero circuit ID");
+
+ n_certs = cell->payload[0];
+ ptr = cell->payload + 1;
+ for (i = 0; i < n_certs; ++i) {
+ uint8_t cert_type;
+ uint16_t cert_len;
+ if (ptr + 3 > cell->payload + cell->payload_len) {
+ goto truncated;
+ }
+ cert_type = *ptr;
+ cert_len = ntohs(get_uint16(ptr+1));
+ if (ptr + 3 + cert_len > cell->payload + cell->payload_len) {
+ goto truncated;
+ }
+ if (cert_type == OR_CERT_TYPE_TLS_LINK ||
+ cert_type == OR_CERT_TYPE_ID_1024 ||
+ cert_type == OR_CERT_TYPE_AUTH_1024) {
+ tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len);
+ if (!cert) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received undecodable certificate in CERTS cell from %s:%d",
+ safe_str(conn->_base.address), conn->_base.port);
+ } else {
+ if (cert_type == OR_CERT_TYPE_TLS_LINK) {
+ if (link_cert) {
+ tor_cert_free(cert);
+ ERR("Too many TLS_LINK certificates");
+ }
+ link_cert = cert;
+ } else if (cert_type == OR_CERT_TYPE_ID_1024) {
+ if (id_cert) {
+ tor_cert_free(cert);
+ ERR("Too many ID_1024 certificates");
+ }
+ id_cert = cert;
+ } else if (cert_type == OR_CERT_TYPE_AUTH_1024) {
+ if (auth_cert) {
+ tor_cert_free(cert);
+ ERR("Too many AUTH_1024 certificates");
+ }
+ auth_cert = cert;
+ } else {
+ tor_cert_free(cert);
+ }
+ }
+ }
+ ptr += 3 + cert_len;
+ continue;
+
+ truncated:
+ ERR("It ends in the middle of a certificate");
+ }
+
+ if (conn->handshake_state->started_here) {
+ int severity;
+ if (! (id_cert && link_cert))
+ ERR("The certs we wanted were missing");
+ /* Okay. We should be able to check the certificates now. */
+ if (! tor_tls_cert_matches_key(conn->tls, link_cert)) {
+ ERR("The link certificate didn't match the TLS public key");
+ }
+ /* Note that this warns more loudly about time and validity if we were
+ * _trying_ to connect to an authority, not necessarily if we _did_ connect
+ * to one. */
+ if (router_digest_is_trusted_dir(conn->identity_digest))
+ severity = LOG_WARN;
+ else
+ severity = LOG_PROTOCOL_WARN;
+
+ if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0))
+ ERR("The link certificate was not valid");
+ if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1))
+ ERR("The ID certificate was not valid");
+
+ conn->handshake_state->authenticated = 1;
+ {
+ const digests_t *id_digests = tor_cert_get_id_digests(id_cert);
+ crypto_pk_env_t *identity_rcvd;
+ if (!id_digests)
+ ERR("Couldn't compute digests for key in ID cert");
+
+ identity_rcvd = tor_tls_cert_get_key(id_cert);
+ if (!identity_rcvd)
+ ERR("Internal error: Couldn't get RSA key from ID cert.");
+ memcpy(conn->handshake_state->authenticated_peer_id,
+ id_digests->d[DIGEST_SHA1], DIGEST_LEN);
+ connection_or_set_circid_type(conn, identity_rcvd);
+ crypto_free_pk_env(identity_rcvd);
+ }
+
+ if (connection_or_client_learned_peer_id(conn,
+ conn->handshake_state->authenticated_peer_id) < 0)
+ ERR("Problem setting or checking peer id");
+
+ log_info(LD_OR, "Got some good certificates from %s:%d: Authenticated it.",
+ safe_str(conn->_base.address), conn->_base.port);
+
+ conn->handshake_state->id_cert = id_cert;
+ id_cert = NULL;
+ } else {
+ if (! (id_cert && auth_cert))
+ ERR("The certs we wanted were missing");
+
+ /* Remember these certificates so we can check an AUTHENTICATE cell */
+ if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1))
+ ERR("The authentication certificate was not valid");
+ if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1))
+ ERR("The ID certificate was not valid");
+
+ log_info(LD_OR, "Got some good certificates from %s:%d: "
+ "Waiting for AUTHENTICATE.",
+ safe_str(conn->_base.address), conn->_base.port);
+ /* XXXX check more stuff? */
+
+ conn->handshake_state->id_cert = id_cert;
+ conn->handshake_state->auth_cert = auth_cert;
+ id_cert = auth_cert = NULL;
+ }
+
+ conn->handshake_state->received_certs_cell = 1;
+ err:
+ tor_cert_free(id_cert);
+ tor_cert_free(link_cert);
+ tor_cert_free(auth_cert);
+#undef ERR
+}
+
+/** Process an AUTH_CHALLENGE cell from an OR connection.
+ *
+ * If we weren't supposed to get one (for example, because we're not the
+ * originator of the connection), or it's ill-formed, or we aren't doing a v3
+ * handshake, mark the connection. If the cell is well-formed but we don't
+ * want to authenticate, just drop it. If the cell is well-formed *and* we
+ * want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell. */
+static void
+command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn)
+{
+ int n_types, i, use_type = -1;
+ uint8_t *cp;
+
+#define ERR(s) \
+ do { \
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
+ "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \
+ safe_str(conn->_base.address), conn->_base.port, (s)); \
+ connection_mark_for_close(TO_CONN(conn)); \
+ return; \
+ } while (0)
+
+ if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3)
+ ERR("We're not currently doing a v3 handshake");
+ if (conn->link_proto < 3)
+ ERR("We're not using link protocol >= 3");
+ if (! conn->handshake_state->started_here)
+ ERR("We didn't originate this connection");
+ if (conn->handshake_state->received_auth_challenge)
+ ERR("We already received one");
+ if (! conn->handshake_state->received_certs_cell)
+ ERR("We haven't gotten a CERTS cell yet");
+ if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2)
+ ERR("It was too short");
+ if (cell->circ_id)
+ ERR("It had a nonzero circuit ID");
+
+ n_types = ntohs(get_uint16(cell->payload + OR_AUTH_CHALLENGE_LEN));
+ if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2 + 2*n_types)
+ ERR("It looks truncated");
+
+ /* Now see if there is an authentication type we can use */
+ cp=cell->payload+OR_AUTH_CHALLENGE_LEN+2;
+ for (i=0; i < n_types; ++i, cp += 2) {
+ uint16_t authtype = ntohs(get_uint16(cp));
+ if (authtype == AUTHTYPE_RSA_SHA256_TLSSECRET)
+ use_type = authtype;
+ }
+
+ conn->handshake_state->received_auth_challenge = 1;
+
+ if (! public_server_mode(get_options())) {
+ /* If we're not a public server then we don't want to authenticate on a
+ connection we originated, and we already sent a NETINFO cell when we
+ got the CERTS cell. We have nothing more to do. */
+ return;
+ }
+
+ if (use_type >= 0) {
+ log_info(LD_OR, "Got an AUTH_CHALLENGE cell from %s:%d: Sending "
+ "authentication",
+ safe_str(conn->_base.address), conn->_base.port);
+
+ if (connection_or_send_authenticate_cell(conn, use_type) < 0) {
+ log_warn(LD_OR, "Couldn't send authenticate cell");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ } else {
+ log_info(LD_OR, "Got an AUTH_CHALLENGE cell from %s:%d, but we don't "
+ "know any of its authentication types. Not authenticating.",
+ safe_str(conn->_base.address), conn->_base.port);
+ }
+
+ if (connection_or_send_netinfo(conn) < 0) {
+ log_warn(LD_OR, "Couldn't send netinfo cell");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+
+#undef ERR
+}
+
+/** Process an AUTHENTICATE cell from an OR connection.
+ *
+ * If it's ill-formed or we weren't supposed to get one or we're not doing a
+ * v3 handshake, then mark the connection. If it does not authenticate the
+ * other side of the connection successfully (because it isn't signed right,
+ * we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept
+ * the identity of the router on the other side of the connection.
+ */
+static void
+command_process_authenticate_cell(var_cell_t *cell, or_connection_t *conn)
+{
+ uint8_t expected[V3_AUTH_FIXED_PART_LEN];
+ const uint8_t *auth;
+ int authlen;
+
+#define ERR(s) \
+ do { \
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
+ "Received a bad AUTHENTICATE cell from %s:%d: %s", \
+ safe_str(conn->_base.address), conn->_base.port, (s)); \
+ connection_mark_for_close(TO_CONN(conn)); \
+ return; \
+ } while (0)
+
+ if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3)
+ ERR("We're not doing a v3 handshake");
+ if (conn->link_proto < 3)
+ ERR("We're not using link protocol >= 3");
+ if (conn->handshake_state->started_here)
+ ERR("We originated this connection");
+ if (conn->handshake_state->received_authenticate)
+ ERR("We already got one!");
+ if (conn->handshake_state->authenticated) {
+ /* Should be impossible given other checks */
+ ERR("The peer is already authenticated");
+ }
+ if (! conn->handshake_state->received_certs_cell)
+ ERR("We never got a certs cell");
+ if (conn->handshake_state->auth_cert == NULL)
+ ERR("We never got an authentication certificate");
+ if (conn->handshake_state->id_cert == NULL)
+ ERR("We never got an identity certificate");
+ if (cell->payload_len < 4)
+ ERR("Cell was way too short");
+
+ auth = cell->payload;
+ {
+ uint16_t type = ntohs(get_uint16(auth));
+ uint16_t len = ntohs(get_uint16(auth+2));
+ if (4 + len > cell->payload_len)
+ ERR("Authenticator was truncated");
+
+ if (type != AUTHTYPE_RSA_SHA256_TLSSECRET)
+ ERR("Authenticator type was not recognized");
+
+ auth += 4;
+ authlen = len;
+ }
+
+ if (authlen < V3_AUTH_BODY_LEN + 1)
+ ERR("Authenticator was too short");
+
+ if (connection_or_compute_authenticate_cell_body(
+ conn, expected, sizeof(expected), NULL, 1) < 0)
+ ERR("Couldn't compute expected AUTHENTICATE cell body");
+
+ if (tor_memneq(expected, auth, sizeof(expected)))
+ ERR("Some field in the AUTHENTICATE cell body was not as expected");
+
+ {
+ crypto_pk_env_t *pk = tor_tls_cert_get_key(
+ conn->handshake_state->auth_cert);
+ char d[DIGEST256_LEN];
+ char *signed_data;
+ size_t keysize;
+ int signed_len;
+
+ if (!pk)
+ ERR("Internal error: couldn't get RSA key from AUTH cert.");
+ crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256);
+
+ keysize = crypto_pk_keysize(pk);
+ signed_data = tor_malloc(keysize);
+ signed_len = crypto_pk_public_checksig(pk, signed_data, keysize,
+ (char*)auth + V3_AUTH_BODY_LEN,
+ authlen - V3_AUTH_BODY_LEN);
+ crypto_free_pk_env(pk);
+ if (signed_len < 0) {
+ tor_free(signed_data);
+ ERR("Signature wasn't valid");
+ }
+ if (signed_len < DIGEST256_LEN) {
+ tor_free(signed_data);
+ ERR("Not enough data was signed");
+ }
+ /* Note that we deliberately allow *more* than DIGEST256_LEN bytes here,
+ * in case they're later used to hold a SHA3 digest or something. */
+ if (tor_memneq(signed_data, d, DIGEST256_LEN)) {
+ tor_free(signed_data);
+ ERR("Signature did not match data to be signed.");
+ }
+ tor_free(signed_data);
+ }
+
+ /* Okay, we are authenticated. */
+ conn->handshake_state->received_authenticate = 1;
+ conn->handshake_state->authenticated = 1;
+ conn->handshake_state->digest_received_data = 0;
+ {
+ crypto_pk_env_t *identity_rcvd =
+ tor_tls_cert_get_key(conn->handshake_state->id_cert);
+ const digests_t *id_digests =
+ tor_cert_get_id_digests(conn->handshake_state->id_cert);
+
+ /* This must exist; we checked key type when reading the cert. */
+ tor_assert(id_digests);
+
+ memcpy(conn->handshake_state->authenticated_peer_id,
+ id_digests->d[DIGEST_SHA1], DIGEST_LEN);
+
+ connection_or_set_circid_type(conn, identity_rcvd);
+ crypto_free_pk_env(identity_rcvd);
+
+ connection_or_init_conn_from_address(conn,
+ &conn->_base.addr,
+ conn->_base.port,
+ (const char*)conn->handshake_state->authenticated_peer_id,
+ 0);
+
+ log_info(LD_OR, "Got an AUTHENTICATE cell from %s:%d: Looks good.",
+ safe_str(conn->_base.address), conn->_base.port);
+ }
+
+#undef ERR
+}
+
diff --git a/src/or/config.c b/src/or/config.c
index 8972506477..a0cf3c80ad 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -33,13 +33,18 @@
#include "rendservice.h"
#include "rephist.h"
#include "router.h"
+#include "util.h"
#include "routerlist.h"
+#include "transports.h"
#ifdef MS_WINDOWS
#include <shlobj.h>
#endif
#include "procmon.h"
+/* From main.c */
+extern int quiet_level;
+
/** Enumeration of types which option values can take */
typedef enum config_type_t {
CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
@@ -48,9 +53,13 @@ typedef enum config_type_t {
CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or
* "auto". */
CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
+ CONFIG_TYPE_MSEC_INTERVAL,/**< A number of milliseconds, with optional
+ * units */
CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
CONFIG_TYPE_DOUBLE, /**< A floating-point value */
CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
+ CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false,
+ * 1 for true, and -1 for auto */
CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */
CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
* optional whitespace. */
@@ -175,6 +184,8 @@ static config_var_t _option_vars[] = {
V(AuthDirBadDir, LINELIST, NULL),
V(AuthDirBadExit, LINELIST, NULL),
V(AuthDirInvalid, LINELIST, NULL),
+ V(AuthDirFastGuarantee, MEMUNIT, "100 KB"),
+ V(AuthDirGuardBWGuarantee, MEMUNIT, "250 KB"),
V(AuthDirReject, LINELIST, NULL),
V(AuthDirRejectUnlisted, BOOL, "0"),
V(AuthDirListBadDirs, BOOL, "0"),
@@ -199,10 +210,12 @@ static config_var_t _option_vars[] = {
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
- V(ClientRejectInternalAddresses, BOOL, "1"),
V(ClientOnly, BOOL, "0"),
+ V(ClientRejectInternalAddresses, BOOL, "1"),
+ V(ClientTransportPlugin, LINELIST, NULL),
V(ConsensusParams, STRING, NULL),
V(ConnLimit, UINT, "1000"),
+ V(ConnDirectionStatistics, BOOL, "0"),
V(ConstrainedSockets, BOOL, "0"),
V(ConstrainedSockSize, MEMUNIT, "8192"),
V(ContactInfo, STRING, NULL),
@@ -215,8 +228,10 @@ static config_var_t _option_vars[] = {
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
V(CookieAuthFile, STRING, NULL),
+ V(CountPrivateBandwidth, BOOL, "0"),
V(DataDirectory, FILENAME, NULL),
OBSOLETE("DebugLogFile"),
+ V(DisableNetwork, BOOL, "0"),
V(DirAllowPrivateAddresses, BOOL, NULL),
V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
V(DirListenAddress, LINELIST, NULL),
@@ -229,10 +244,13 @@ static config_var_t _option_vars[] = {
OBSOLETE("DirRecordUsageGranularity"),
OBSOLETE("DirRecordUsageRetainIPs"),
OBSOLETE("DirRecordUsageSaveInterval"),
- V(DirReqStatistics, BOOL, "0"),
+ V(DirReqStatistics, BOOL, "1"),
VAR("DirServer", LINELIST, DirServers, NULL),
V(DisableAllSwap, BOOL, "0"),
- V(DNSPort, PORT, "0"),
+ V(DisableDebuggerAttachment, BOOL, "1"),
+ V(DisableIOCP, BOOL, "1"),
+ V(DynamicDHGroups, BOOL, "1"),
+ V(DNSPort, LINELIST, NULL),
V(DNSListenAddress, LINELIST, NULL),
V(DownloadExtraInfo, BOOL, "0"),
V(EnforceDistinctSubnets, BOOL, "1"),
@@ -246,7 +264,7 @@ static config_var_t _option_vars[] = {
V(ExitPolicy, LINELIST, NULL),
V(ExitPolicyRejectPrivate, BOOL, "1"),
V(ExitPortStatistics, BOOL, "0"),
- V(ExtraInfoStatistics, BOOL, "0"),
+ V(ExtraInfoStatistics, BOOL, "1"),
#if defined (WINCE)
V(FallbackNetworkstatusFile, FILENAME, "fallback-consensus"),
@@ -269,8 +287,11 @@ static config_var_t _option_vars[] = {
V(GeoIPFile, FILENAME,
SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
#endif
+ V(GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays,
+ BOOL, "0"),
OBSOLETE("Group"),
V(HardwareAccel, BOOL, "0"),
+ V(HeartbeatPeriod, INTERVAL, "6 hours"),
V(AccelName, STRING, NULL),
V(AccelDir, FILENAME, NULL),
V(HashedControlPassword, LINELIST, NULL),
@@ -289,6 +310,7 @@ static config_var_t _option_vars[] = {
V(HTTPProxyAuthenticator, STRING, NULL),
V(HTTPSProxy, STRING, NULL),
V(HTTPSProxyAuthenticator, STRING, NULL),
+ VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL),
V(Socks4Proxy, STRING, NULL),
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
@@ -300,23 +322,25 @@ static config_var_t _option_vars[] = {
OBSOLETE("LinkPadding"),
OBSOLETE("LogLevel"),
OBSOLETE("LogFile"),
+ V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(LongLivedPorts, CSV,
- "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"),
+ "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
+ V(MaxClientCircuitsPending, UINT, "32"),
V(MaxOnionsPending, UINT, "100"),
OBSOLETE("MonthlyAccountingStart"),
V(MyFamily, STRING, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
V(NATDListenAddress, LINELIST, NULL),
- V(NATDPort, PORT, "0"),
+ V(NATDPort, LINELIST, NULL),
V(Nickname, STRING, NULL),
V(WarnUnsafeSocks, BOOL, "1"),
OBSOLETE("NoPublish"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
- V(NumCPUs, UINT, "1"),
+ V(NumCPUs, UINT, "0"),
V(NumEntryGuards, UINT, "3"),
V(ORListenAddress, LINELIST, NULL),
V(ORPort, PORT, "0"),
@@ -326,6 +350,9 @@ static config_var_t _option_vars[] = {
V(PerConnBWRate, MEMUNIT, "0"),
V(PidFile, STRING, NULL),
V(TestingTorNetwork, BOOL, "0"),
+ V(OptimisticData, AUTOBOOL, "auto"),
+ V(PortForwarding, BOOL, "0"),
+ V(PortForwardingHelper, FILENAME, "tor-fw-helper"),
V(PreferTunneledDirConns, BOOL, "1"),
V(ProtocolWarnings, BOOL, "0"),
V(PublishServerDescriptor, CSV, "1"),
@@ -337,7 +364,7 @@ static config_var_t _option_vars[] = {
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
OBSOLETE("RedirectExit"),
- V(RefuseUnknownExits, STRING, "auto"),
+ V(RefuseUnknownExits, AUTOBOOL, "auto"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
V(RelayBandwidthRate, MEMUNIT, "0"),
@@ -362,23 +389,26 @@ static config_var_t _option_vars[] = {
V(ShutdownWaitLength, INTERVAL, "30 seconds"),
V(SocksListenAddress, LINELIST, NULL),
V(SocksPolicy, LINELIST, NULL),
- V(SocksPort, PORT, "9050"),
+ V(SocksPort, LINELIST, NULL),
V(SocksTimeout, INTERVAL, "2 minutes"),
OBSOLETE("StatusFetchPeriod"),
V(StrictNodes, BOOL, "0"),
OBSOLETE("SysLog"),
V(TestSocks, BOOL, "0"),
OBSOLETE("TestVia"),
+ V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
V(TrackHostExits, CSV, NULL),
V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
OBSOLETE("TrafficShaping"),
V(TransListenAddress, LINELIST, NULL),
- V(TransPort, PORT, "0"),
+ V(TransPort, LINELIST, NULL),
V(TunnelDirConns, BOOL, "1"),
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
V(UseEntryGuards, BOOL, "1"),
+ V(UseMicrodescriptors, AUTOBOOL, "auto"),
V(User, STRING, NULL),
+ V(UserspaceIOCPBuffers, BOOL, "0"),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
@@ -394,6 +424,7 @@ static config_var_t _option_vars[] = {
VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
V(VirtualAddrNetwork, STRING, "127.192.0.0/10"),
V(WarnPlaintextPorts, CSV, "23,109,110,143"),
+ V(_UseFilteringSSLBufferevents, BOOL, "0"),
VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
@@ -410,7 +441,7 @@ static config_var_t _option_vars[] = {
/** Override default values with these if the user sets the TestingTorNetwork
* option. */
-static config_var_t testing_tor_network_defaults[] = {
+static const config_var_t testing_tor_network_defaults[] = {
V(ServerDNSAllowBrokenConfig, BOOL, "1"),
V(DirAllowPrivateAddresses, BOOL, "1"),
V(EnforceDistinctSubnets, BOOL, "0"),
@@ -419,6 +450,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(AuthDirMaxServersPerAuthAddr,UINT, "0"),
V(ClientDNSRejectInternalAddresses, BOOL,"0"),
V(ClientRejectInternalAddresses, BOOL, "0"),
+ V(CountPrivateBandwidth, BOOL, "1"),
V(ExitPolicyRejectPrivate, BOOL, "0"),
V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
@@ -430,6 +462,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
V(_UsingTestNetworkDefaults, BOOL, "1"),
+
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
};
#undef VAR
@@ -455,6 +488,9 @@ static config_var_t _state_vars[] = {
VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL),
V(EntryGuards, LINELIST_V, NULL),
+ VAR("TransportProxy", LINELIST_S, TransportProxies, NULL),
+ V(TransportProxies, LINELIST_V, NULL),
+
V(BWHistoryReadEnds, ISOTIME, NULL),
V(BWHistoryReadInterval, UINT, "900"),
V(BWHistoryReadValues, CSV, ""),
@@ -481,7 +517,6 @@ static config_var_t _state_vars[] = {
V(CircuitBuildAbandonedCount, UINT, "0"),
VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL),
VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL),
-
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
};
@@ -532,39 +567,48 @@ static char *get_windows_conf_root(void);
#endif
static void config_line_append(config_line_t **lst,
const char *key, const char *val);
-static void option_clear(config_format_t *fmt, or_options_t *options,
- config_var_t *var);
-static void option_reset(config_format_t *fmt, or_options_t *options,
- config_var_t *var, int use_defaults);
-static void config_free(config_format_t *fmt, void *options);
+static void option_clear(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var);
+static void option_reset(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var, int use_defaults);
+static void config_free(const config_format_t *fmt, void *options);
static int config_lines_eq(config_line_t *a, config_line_t *b);
-static int option_is_same(config_format_t *fmt,
- or_options_t *o1, or_options_t *o2,
+static int option_is_same(const config_format_t *fmt,
+ const or_options_t *o1, const or_options_t *o2,
const char *name);
-static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
-static int options_validate(or_options_t *old_options, or_options_t *options,
+static or_options_t *options_dup(const config_format_t *fmt,
+ const or_options_t *old);
+static int options_validate(or_options_t *old_options,
+ or_options_t *options,
int from_setconf, char **msg);
-static int options_act_reversible(or_options_t *old_options, char **msg);
-static int options_act(or_options_t *old_options);
-static int options_transition_allowed(or_options_t *old, or_options_t *new,
+static int options_act_reversible(const or_options_t *old_options, char **msg);
+static int options_act(const or_options_t *old_options);
+static int options_transition_allowed(const or_options_t *old,
+ const or_options_t *new,
char **msg);
-static int options_transition_affects_workers(or_options_t *old_options,
- or_options_t *new_options);
-static int options_transition_affects_descriptor(or_options_t *old_options,
- or_options_t *new_options);
+static int options_transition_affects_workers(
+ const or_options_t *old_options, const or_options_t *new_options);
+static int options_transition_affects_descriptor(
+ const or_options_t *old_options, const or_options_t *new_options);
static int check_nickname_list(const char *lst, const char *name, char **msg);
-static void config_register_addressmaps(or_options_t *options);
static int parse_bridge_line(const char *line, int validate_only);
+static int parse_client_transport_line(const char *line, int validate_only);
+
+static int parse_server_transport_line(const char *line, int validate_only);
static int parse_dir_server_line(const char *line,
- authority_type_t required_type,
+ dirinfo_type_t required_type,
int validate_only);
+static void port_cfg_free(port_cfg_t *port);
+static int parse_client_ports(const or_options_t *options, int validate_only,
+ char **msg_out, int *n_ports_out);
static int validate_data_directory(or_options_t *options);
-static int write_configuration_file(const char *fname, or_options_t *options);
-static config_line_t *get_assigned_option(config_format_t *fmt,
- void *options, const char *key,
- int escape_val);
-static void config_init(config_format_t *fmt, void *options);
+static int write_configuration_file(const char *fname,
+ const or_options_t *options);
+static config_line_t *get_assigned_option(const config_format_t *fmt,
+ const void *options, const char *key,
+ int escape_val);
+static void config_init(const config_format_t *fmt, void *options);
static int or_state_validate(or_state_t *old_options, or_state_t *options,
int from_setconf, char **msg);
static int or_state_load(void);
@@ -574,8 +618,9 @@ static int is_listening_on_low_port(int port_option,
const config_line_t *listen_options);
static uint64_t config_parse_memunit(const char *s, int *ok);
+static int config_parse_msec_interval(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
-static void init_libevent(void);
+static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
/** Magic value for or_options_t. */
@@ -602,7 +647,7 @@ static config_var_t state_extra_var = {
};
/** Configuration format for or_state_t. */
-static config_format_t state_format = {
+static const config_format_t state_format = {
sizeof(or_state_t),
OR_STATE_MAGIC,
STRUCT_OFFSET(or_state_t, _magic),
@@ -618,14 +663,20 @@ static config_format_t state_format = {
/** Command-line and config-file options. */
static or_options_t *global_options = NULL;
+/** DOCDOC */
+static or_options_t *global_default_options = NULL;
/** Name of most recently read torrc file. */
static char *torrc_fname = NULL;
+/** DOCDOC */
+static char *torrc_defaults_fname;
/** Persistent serialized state. */
static or_state_t *global_state = NULL;
/** Configuration Options set by command line. */
static config_line_t *global_cmdline_options = NULL;
/** Contents of most recently read DirPortFrontPage file. */
static char *global_dirfrontpagecontents = NULL;
+/** List of port_cfg_t for client-level (SOCKS, DNS, Trans, NATD) ports. */
+static smartlist_t *configured_client_ports = NULL;
/** Return the contents of our frontpage string, or NULL if not configured. */
const char *
@@ -636,7 +687,7 @@ get_dirportfrontpage(void)
/** Allocate an empty configuration object of a given format type. */
static void *
-config_alloc(config_format_t *fmt)
+config_alloc(const config_format_t *fmt)
{
void *opts = tor_malloc_zero(fmt->size);
*(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
@@ -646,12 +697,19 @@ config_alloc(config_format_t *fmt)
/** Return the currently configured options. */
or_options_t *
-get_options(void)
+get_options_mutable(void)
{
tor_assert(global_options);
return global_options;
}
+/** Returns the currently configured options */
+const or_options_t *
+get_options(void)
+{
+ return get_options_mutable();
+}
+
/** Change the current global options to contain <b>new_val</b> instead of
* their current value; take action based on the new value; free the old value
* as necessary. Returns 0 on success, -1 on failure.
@@ -659,6 +717,9 @@ get_options(void)
int
set_options(or_options_t *new_val, char **msg)
{
+ int i;
+ smartlist_t *elements;
+ config_line_t *line;
or_options_t *old_options = global_options;
global_options = new_val;
/* Note that we pass the *old* options below, for comparison. It
@@ -673,7 +734,34 @@ set_options(or_options_t *new_val, char **msg)
"Acting on config options left us in a broken state. Dying.");
exit(1);
}
-
+ /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
+ * just starting up then the old_options will be undefined. */
+ if (old_options) {
+ elements = smartlist_create();
+ for (i=0; options_format.vars[i].name; ++i) {
+ const config_var_t *var = &options_format.vars[i];
+ const char *var_name = var->name;
+ if (var->type == CONFIG_TYPE_LINELIST_S ||
+ var->type == CONFIG_TYPE_OBSOLETE) {
+ continue;
+ }
+ if (!option_is_same(&options_format, new_val, old_options, var_name)) {
+ line = get_assigned_option(&options_format, new_val, var_name, 1);
+
+ if (line) {
+ for (; line; line = line->next) {
+ smartlist_add(elements, line->key);
+ smartlist_add(elements, line->value);
+ }
+ } else {
+ smartlist_add(elements, (char*)options_format.vars[i].name);
+ smartlist_add(elements, NULL);
+ }
+ }
+ }
+ control_event_conf_changed(elements);
+ smartlist_free(elements);
+ }
config_free(&options_format, old_options);
return 0;
@@ -709,6 +797,11 @@ or_options_free(or_options_t *options)
return;
routerset_free(options->_ExcludeExitNodesUnion);
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
+ rs, routerset_free(rs));
+ smartlist_free(options->NodeFamilySets);
+ }
config_free(&options_format, options);
}
@@ -719,6 +812,8 @@ config_free_all(void)
{
or_options_free(global_options);
global_options = NULL;
+ or_options_free(global_default_options);
+ global_default_options = NULL;
config_free(&state_format, global_state);
global_state = NULL;
@@ -726,7 +821,15 @@ config_free_all(void)
config_free_lines(global_cmdline_options);
global_cmdline_options = NULL;
+ if (configured_client_ports) {
+ SMARTLIST_FOREACH(configured_client_ports,
+ port_cfg_t *, p, tor_free(p));
+ smartlist_free(configured_client_ports);
+ configured_client_ports = NULL;
+ }
+
tor_free(torrc_fname);
+ tor_free(torrc_defaults_fname);
tor_free(_version);
tor_free(global_dirfrontpagecontents);
}
@@ -791,7 +894,7 @@ escaped_safe_str(const char *address)
/** Add the default directory authorities directly into the trusted dir list,
* but only add them insofar as they share bits with <b>type</b>. */
static void
-add_default_trusted_dir_authorities(authority_type_t type)
+add_default_trusted_dir_authorities(dirinfo_type_t type)
{
int i;
const char *dirservers[] = {
@@ -865,16 +968,16 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
/* Now go through the four ways you can configure an alternate
* set of directory authorities, and make sure none are broken. */
for (cl = options->DirServers; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
return 0;
}
@@ -883,8 +986,8 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
* as appropriate.
*/
static int
-consider_adding_dir_authorities(or_options_t *options,
- or_options_t *old_options)
+consider_adding_dir_authorities(const or_options_t *options,
+ const or_options_t *old_options)
{
config_line_t *cl;
int need_to_update =
@@ -905,27 +1008,28 @@ consider_adding_dir_authorities(or_options_t *options,
if (!options->DirServers) {
/* then we may want some of the defaults */
- authority_type_t type = NO_AUTHORITY;
+ dirinfo_type_t type = NO_DIRINFO;
if (!options->AlternateBridgeAuthority)
- type |= BRIDGE_AUTHORITY;
+ type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
- type |= V1_AUTHORITY | V2_AUTHORITY | V3_AUTHORITY;
+ type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
+ MICRODESC_DIRINFO;
if (!options->AlternateHSAuthority)
- type |= HIDSERV_AUTHORITY;
+ type |= HIDSERV_DIRINFO;
add_default_trusted_dir_authorities(type);
}
for (cl = options->DirServers; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
return 0;
}
@@ -937,12 +1041,12 @@ consider_adding_dir_authorities(or_options_t *options,
* Return 0 if all goes well, return -1 if things went badly.
*/
static int
-options_act_reversible(or_options_t *old_options, char **msg)
+options_act_reversible(const or_options_t *old_options, char **msg)
{
smartlist_t *new_listeners = smartlist_create();
smartlist_t *replaced_listeners = smartlist_create();
static int libevent_initialized = 0;
- or_options_t *options = get_options();
+ or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
int set_conn_limit = 0;
int r = -1;
@@ -971,6 +1075,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
#endif
if (running_tor) {
+ int n_client_ports=0;
/* We need to set the connection limit before we can open the listeners. */
if (set_max_file_descriptors((unsigned)options->ConnLimit,
&options->_ConnLimit) < 0) {
@@ -982,18 +1087,37 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Set up libevent. (We need to do this before we can register the
* listeners as listeners.) */
if (running_tor && !libevent_initialized) {
- init_libevent();
+ init_libevent(options);
libevent_initialized = 1;
}
+ /* Adjust the client port configuration so we can launch listeners. */
+ if (parse_client_ports(options, 0, msg, &n_client_ports)) {
+ if (!*msg)
+ *msg = tor_strdup("Unexpected problem parsing client port config");
+ goto rollback;
+ }
+
+ /* Set the hibernation state appropriately.*/
+ consider_hibernation(time(NULL));
+
/* Launch the listeners. (We do this before we setuid, so we can bind to
- * ports under 1024.) We don't want to rebind if we're hibernating. */
+ * ports under 1024.) We don't want to rebind if we're hibernating. If
+ * networking is disabled, this will close all but the control listeners,
+ * but disable those. */
if (!we_are_hibernating()) {
if (retry_all_listeners(replaced_listeners, new_listeners) < 0) {
*msg = tor_strdup("Failed to bind one of the listener ports.");
goto rollback;
}
}
+ if (options->DisableNetwork) {
+ /* Aggressively close non-controller stuff, NOW */
+ log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
+ "non-control network connections. Shutting down all existing "
+ "connections.");
+ connection_mark_all_noncontrol_connections();
+ }
}
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
@@ -1038,7 +1162,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Write control ports to disk as appropriate */
control_ports_write_to_file();
- if (directory_caches_v2_dir_info(options)) {
+ if (directory_caches_v2_dir_info(options)) {
size_t len = strlen(options->DataDirectory)+32;
char *fn = tor_malloc(len);
tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status",
@@ -1114,7 +1238,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/** If we need to have a GEOIP ip-to-country map to run with our configured
* options, return 1 and set *<b>reason_out</b> to a description of why. */
int
-options_need_geoip_info(or_options_t *options, const char **reason_out)
+options_need_geoip_info(const or_options_t *options, const char **reason_out)
{
int bridge_usage =
options->BridgeRelay && options->BridgeRecordUsageByCountry;
@@ -1139,7 +1263,7 @@ options_need_geoip_info(or_options_t *options, const char **reason_out)
/** Return the bandwidthrate that we are going to report to the authorities
* based on the config options. */
uint32_t
-get_effective_bwrate(or_options_t *options)
+get_effective_bwrate(const or_options_t *options)
{
uint64_t bw = options->BandwidthRate;
if (bw > options->MaxAdvertisedBandwidth)
@@ -1153,7 +1277,7 @@ get_effective_bwrate(or_options_t *options)
/** Return the bandwidthburst that we are going to report to the authorities
* based on the config options. */
uint32_t
-get_effective_bwburst(or_options_t *options)
+get_effective_bwburst(const or_options_t *options)
{
uint64_t bw = options->BandwidthBurst;
if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
@@ -1162,6 +1286,24 @@ get_effective_bwburst(or_options_t *options)
return (uint32_t)bw;
}
+/** Return True if any changes from <b>old_options</b> to
+ * <b>new_options</b> needs us to refresh our TLS context. */
+static int
+options_transition_requires_fresh_tls_context(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ tor_assert(new_options);
+
+ if (!old_options)
+ return 0;
+
+ if ((old_options->DynamicDHGroups != new_options->DynamicDHGroups)) {
+ return 1;
+ }
+
+ return 0;
+}
+
/** Fetch the active option list, and take actions based on it. All of the
* things we do should survive being done repeatedly. If present,
* <b>old_options</b> contains the previous value of the options.
@@ -1172,15 +1314,23 @@ get_effective_bwburst(or_options_t *options)
* here yet. Some is still in do_hup() and other places.
*/
static int
-options_act(or_options_t *old_options)
+options_act(const or_options_t *old_options)
{
config_line_t *cl;
- or_options_t *options = get_options();
+ or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
char *msg;
const int transition_affects_workers =
old_options && options_transition_affects_workers(old_options, options);
+ /* disable ptrace and later, other basic debugging techniques */
+ if (options->DisableDebuggerAttachment) {
+ tor_disable_debugger_attach();
+ } else {
+ log_notice(LD_CONFIG,"Debugger attachment enabled "
+ "for unprivileged users.");
+ }
+
if (running_tor && !have_lockfile()) {
if (try_locking(options, 1) < 0)
return -1;
@@ -1220,6 +1370,32 @@ options_act(or_options_t *old_options)
rep_hist_load_mtbf_data(time(NULL));
}
+ mark_transport_list();
+ pt_prepare_proxy_list_for_config_read();
+ if (options->ClientTransportPlugin) {
+ for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+ if (parse_client_transport_line(cl->value, 0)<0) {
+ log_warn(LD_BUG,
+ "Previously validated ClientTransportPlugin line "
+ "could not be added!");
+ return -1;
+ }
+ }
+ }
+
+ if (options->ServerTransportPlugin) {
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (parse_server_transport_line(cl->value, 0)<0) {
+ log_warn(LD_BUG,
+ "Previously validated ServerTransportPlugin line "
+ "could not be added!");
+ return -1;
+ }
+ }
+ }
+ sweep_transport_list();
+ sweep_proxy_list();
+
/* Bail out at this point if we're not going to be a client or server:
* we want to not fork, and to log stuff to stderr. */
if (!running_tor)
@@ -1231,6 +1407,29 @@ options_act(or_options_t *old_options)
finish_daemon(options->DataDirectory);
}
+ /* If needed, generate a new TLS DH prime according to the current torrc. */
+ if (server_mode(options)) {
+ if (!old_options) {
+ if (options->DynamicDHGroups) {
+ char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
+ crypto_set_tls_dh_prime(fname);
+ tor_free(fname);
+ } else {
+ crypto_set_tls_dh_prime(NULL);
+ }
+ } else {
+ if (options->DynamicDHGroups && !old_options->DynamicDHGroups) {
+ char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
+ crypto_set_tls_dh_prime(fname);
+ tor_free(fname);
+ } else if (!options->DynamicDHGroups && old_options->DynamicDHGroups) {
+ crypto_set_tls_dh_prime(NULL);
+ }
+ }
+ } else { /* clients don't need a dynamic DH prime. */
+ crypto_set_tls_dh_prime(NULL);
+ }
+
/* We want to reinit keys as needed before we do much of anything else:
keys are important, and other things can depend on them. */
if (transition_affects_workers ||
@@ -1240,6 +1439,13 @@ options_act(or_options_t *old_options)
log_warn(LD_BUG,"Error initializing keys; exiting");
return -1;
}
+ } else if (old_options &&
+ options_transition_requires_fresh_tls_context(old_options,
+ options)) {
+ if (router_initialize_tls_context() < 0) {
+ log_warn(LD_BUG,"Error initializing TLS context.");
+ return -1;
+ }
}
/* Write our PID to the PID file. If we do not have write permissions we
@@ -1279,17 +1485,16 @@ options_act(or_options_t *old_options)
if (accounting_is_enabled(options))
configure_accounting(time(NULL));
- /* parse RefuseUnknownExits tristate */
- if (!strcmp(options->RefuseUnknownExits, "0"))
- options->RefuseUnknownExits_ = 0;
- else if (!strcmp(options->RefuseUnknownExits, "1"))
- options->RefuseUnknownExits_ = 1;
- else if (!strcmp(options->RefuseUnknownExits, "auto"))
- options->RefuseUnknownExits_ = -1;
- else {
- /* Should have caught this in options_validate */
- return -1;
- }
+#ifdef USE_BUFFEREVENTS
+ /* If we're using the bufferevents implementation and our rate limits
+ * changed, we need to tell the rate-limiting system about it. */
+ if (!old_options ||
+ old_options->BandwidthRate != options->BandwidthRate ||
+ old_options->BandwidthBurst != options->BandwidthBurst ||
+ old_options->RelayBandwidthRate != options->RelayBandwidthRate ||
+ old_options->RelayBandwidthBurst != options->RelayBandwidthBurst)
+ connection_bucket_init();
+#endif
/* Change the cell EWMA settings */
cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
@@ -1408,44 +1613,69 @@ options_act(or_options_t *old_options)
tor_free(actual_fname);
}
- if (options->DirReqStatistics && !geoip_is_loaded()) {
- /* Check if GeoIP database could be loaded. */
- log_warn(LD_CONFIG, "Configured to measure directory request "
- "statistics, but no GeoIP database found!");
- return -1;
- }
-
- if (options->EntryStatistics) {
- if (should_record_bridge_info(options)) {
- /* Don't allow measuring statistics on entry guards when configured
- * as bridge. */
- log_warn(LD_CONFIG, "Bridges cannot be configured to measure "
- "additional GeoIP statistics as entry guards.");
- return -1;
- } else if (!geoip_is_loaded()) {
- /* Check if GeoIP database could be loaded. */
- log_warn(LD_CONFIG, "Configured to measure entry node statistics, "
- "but no GeoIP database found!");
- return -1;
- }
- }
-
if (options->CellStatistics || options->DirReqStatistics ||
- options->EntryStatistics || options->ExitPortStatistics) {
+ options->EntryStatistics || options->ExitPortStatistics ||
+ options->ConnDirectionStatistics ||
+ options->BridgeAuthoritativeDir) {
time_t now = time(NULL);
+ int print_notice = 0;
+
+ /* If we aren't acting as a server, we can't collect stats anyway. */
+ if (!server_mode(options)) {
+ options->CellStatistics = 0;
+ options->DirReqStatistics = 0;
+ options->EntryStatistics = 0;
+ options->ExitPortStatistics = 0;
+ }
+
if ((!old_options || !old_options->CellStatistics) &&
- options->CellStatistics)
+ options->CellStatistics) {
rep_hist_buffer_stats_init(now);
+ print_notice = 1;
+ }
if ((!old_options || !old_options->DirReqStatistics) &&
- options->DirReqStatistics)
- geoip_dirreq_stats_init(now);
+ options->DirReqStatistics) {
+ if (geoip_is_loaded()) {
+ geoip_dirreq_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->DirReqStatistics = 0;
+ /* Don't warn Tor clients, they don't use statistics */
+ if (options->ORPort)
+ log_notice(LD_CONFIG, "Configured to measure directory request "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
if ((!old_options || !old_options->EntryStatistics) &&
- options->EntryStatistics)
- geoip_entry_stats_init(now);
+ options->EntryStatistics && !should_record_bridge_info(options)) {
+ if (geoip_is_loaded()) {
+ geoip_entry_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->EntryStatistics = 0;
+ log_notice(LD_CONFIG, "Configured to measure entry node "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
if ((!old_options || !old_options->ExitPortStatistics) &&
- options->ExitPortStatistics)
+ options->ExitPortStatistics) {
rep_hist_exit_stats_init(now);
- if (!old_options)
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->ConnDirectionStatistics) &&
+ options->ConnDirectionStatistics) {
+ rep_hist_conn_stats_init(now);
+ }
+ if ((!old_options || !old_options->BridgeAuthoritativeDir) &&
+ options->BridgeAuthoritativeDir) {
+ rep_hist_desc_stats_init(now);
+ print_notice = 1;
+ }
+ if (print_notice)
log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
"the *-stats files that will first be written to the "
"data directory in 24 hours from now.");
@@ -1463,6 +1693,12 @@ options_act(or_options_t *old_options)
if (old_options && old_options->ExitPortStatistics &&
!options->ExitPortStatistics)
rep_hist_exit_stats_term();
+ if (old_options && old_options->ConnDirectionStatistics &&
+ !options->ConnDirectionStatistics)
+ rep_hist_conn_stats_term();
+ if (old_options && old_options->BridgeAuthoritativeDir &&
+ !options->BridgeAuthoritativeDir)
+ rep_hist_desc_stats_term();
/* Check if we need to parse and add the EntryNodes config option. */
if (options->EntryNodes &&
@@ -1520,7 +1756,7 @@ options_act(or_options_t *old_options)
* apply abbreviations that work for the config file and the command line.
* If <b>warn_obsolete</b> is set, warn about deprecated names. */
static const char *
-expand_abbrev(config_format_t *fmt, const char *option, int command_line,
+expand_abbrev(const config_format_t *fmt, const char *option, int command_line,
int warn_obsolete)
{
int i;
@@ -1558,7 +1794,11 @@ config_get_commandlines(int argc, char **argv, config_line_t **result)
int i = 1;
while (i < argc) {
+ unsigned command = CONFIG_LINE_NORMAL;
+ int want_arg = 1;
+
if (!strcmp(argv[i],"-f") ||
+ !strcmp(argv[i],"--defaults-torrc") ||
!strcmp(argv[i],"--hash-password")) {
i += 2; /* command-line option with argument. ignore them. */
continue;
@@ -1575,13 +1815,6 @@ config_get_commandlines(int argc, char **argv, config_line_t **result)
continue;
}
- if (i == argc-1) {
- log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
- argv[i]);
- config_free_lines(front);
- return -1;
- }
-
*new = tor_malloc_zero(sizeof(config_line_t));
s = argv[i];
@@ -1590,15 +1823,33 @@ config_get_commandlines(int argc, char **argv, config_line_t **result)
s++;
if (*s == '-')
s++;
+ /* Figure out the command, if any. */
+ if (*s == '+') {
+ s++;
+ command = CONFIG_LINE_APPEND;
+ } else if (*s == '/') {
+ s++;
+ command = CONFIG_LINE_CLEAR;
+ /* A 'clear' command has no argument. */
+ want_arg = 0;
+ }
+
+ if (want_arg && i == argc-1) {
+ log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
+ argv[i]);
+ config_free_lines(front);
+ return -1;
+ }
(*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
- (*new)->value = tor_strdup(argv[i+1]);
+ (*new)->value = want_arg ? tor_strdup(argv[i+1]) : tor_strdup("");
+ (*new)->command = command;
(*new)->next = NULL;
log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
(*new)->key, (*new)->value);
new = &((*new)->next);
- i += 2;
+ i += want_arg ? 2 : 1;
}
*result = front;
return 0;
@@ -1613,7 +1864,7 @@ config_line_append(config_line_t **lst,
{
config_line_t *newline;
- newline = tor_malloc(sizeof(config_line_t));
+ newline = tor_malloc_zero(sizeof(config_line_t));
newline->key = tor_strdup(key);
newline->value = tor_strdup(val);
newline->next = NULL;
@@ -1626,9 +1877,12 @@ config_line_append(config_line_t **lst,
/** Helper: parse the config string and strdup into key/value
* strings. Set *result to the list, or NULL if parsing the string
* failed. Return 0 on success, -1 on failure. Warn and ignore any
- * misformatted lines. */
+ * misformatted lines.
+ *
+ * If <b>extended</b> is set, then treat keys beginning with / and with + as
+ * indicating "clear" and "append" respectively. */
int
-config_get_lines(const char *string, config_line_t **result)
+config_get_lines(const char *string, config_line_t **result, int extended)
{
config_line_t *list = NULL, **next;
char *k, *v;
@@ -1644,13 +1898,30 @@ config_get_lines(const char *string, config_line_t **result)
return -1;
}
if (k && v) {
+ unsigned command = CONFIG_LINE_NORMAL;
+ if (extended) {
+ if (k[0] == '+') {
+ char *k_new = tor_strdup(k+1);
+ tor_free(k);
+ k = k_new;
+ command = CONFIG_LINE_APPEND;
+ } else if (k[0] == '/') {
+ char *k_new = tor_strdup(k+1);
+ tor_free(k);
+ k = k_new;
+ tor_free(v);
+ v = tor_strdup("");
+ command = CONFIG_LINE_CLEAR;
+ }
+ }
/* This list can get long, so we keep a pointer to the end of it
* rather than using config_line_append over and over and getting
* n^2 performance. */
- *next = tor_malloc(sizeof(config_line_t));
+ *next = tor_malloc_zero(sizeof(config_line_t));
(*next)->key = k;
(*next)->value = v;
(*next)->next = NULL;
+ (*next)->command = command;
next = &((*next)->next);
} else {
tor_free(k);
@@ -1680,12 +1951,9 @@ config_free_lines(config_line_t *front)
}
}
-/** If <b>key</b> is a configuration option, return the corresponding
- * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
- * warn, and return the corresponding config_var_t. Otherwise return NULL.
- */
+/** As config_find_option, but return a non-const pointer. */
static config_var_t *
-config_find_option(config_format_t *fmt, const char *key)
+config_find_option_mutable(config_format_t *fmt, const char *key)
{
int i;
size_t keylen = strlen(key);
@@ -1710,9 +1978,20 @@ config_find_option(config_format_t *fmt, const char *key)
return NULL;
}
+/** If <b>key</b> is a configuration option, return the corresponding const
+ * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
+ * warn, and return the corresponding const config_var_t. Otherwise return
+ * NULL.
+ */
+static const config_var_t *
+config_find_option(const config_format_t *fmt, const char *key)
+{
+ return config_find_option_mutable((config_format_t*)fmt, key);
+}
+
/** Return the number of option entries in <b>fmt</b>. */
static int
-config_count_options(config_format_t *fmt)
+config_count_options(const config_format_t *fmt)
{
int i;
for (i=0; fmt->vars[i].name; ++i)
@@ -1730,11 +2009,11 @@ config_count_options(config_format_t *fmt)
* Called from config_assign_line() and option_reset().
*/
static int
-config_assign_value(config_format_t *fmt, or_options_t *options,
+config_assign_value(const config_format_t *fmt, or_options_t *options,
config_line_t *c, char **msg)
{
int i, ok;
- config_var_t *var;
+ const config_var_t *var;
void *lvalue;
CHECK(fmt, options);
@@ -1777,6 +2056,18 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
break;
}
+ case CONFIG_TYPE_MSEC_INTERVAL: {
+ i = config_parse_msec_interval(c->value, &ok);
+ if (!ok) {
+ tor_asprintf(msg,
+ "Msec interval '%s %s' is malformed or out of bounds.",
+ c->key, c->value);
+ return -1;
+ }
+ *(int *)lvalue = i;
+ break;
+ }
+
case CONFIG_TYPE_MEMUNIT: {
uint64_t u64 = config_parse_memunit(c->value, &ok);
if (!ok) {
@@ -1800,6 +2091,20 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
*(int *)lvalue = i;
break;
+ case CONFIG_TYPE_AUTOBOOL:
+ if (!strcmp(c->value, "auto"))
+ *(int *)lvalue = -1;
+ else if (!strcmp(c->value, "0"))
+ *(int *)lvalue = 0;
+ else if (!strcmp(c->value, "1"))
+ *(int *)lvalue = 1;
+ else {
+ tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
+ c->key, c->value);
+ return -1;
+ }
+ break;
+
case CONFIG_TYPE_STRING:
case CONFIG_TYPE_FILENAME:
tor_free(*(char **)lvalue);
@@ -1844,7 +2149,19 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
case CONFIG_TYPE_LINELIST:
case CONFIG_TYPE_LINELIST_S:
- config_line_append((config_line_t**)lvalue, c->key, c->value);
+ {
+ config_line_t *lastval = *(config_line_t**)lvalue;
+ if (lastval && lastval->fragile) {
+ if (c->command != CONFIG_LINE_APPEND) {
+ config_free_lines(lastval);
+ *(config_line_t**)lvalue = NULL;
+ } else {
+ lastval->fragile = 0;
+ }
+ }
+
+ config_line_append((config_line_t**)lvalue, c->key, c->value);
+ }
break;
case CONFIG_TYPE_OBSOLETE:
log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
@@ -1860,6 +2177,28 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
return 0;
}
+/** Mark every linelist in <b>options<b> "fragile", so that fresh assignments
+ * to it will replace old ones. */
+static void
+config_mark_lists_fragile(const config_format_t *fmt, or_options_t *options)
+{
+ int i;
+ tor_assert(fmt);
+ tor_assert(options);
+
+ for (i = 0; fmt->vars[i].name; ++i) {
+ const config_var_t *var = &fmt->vars[i];
+ config_line_t *list;
+ if (var->type != CONFIG_TYPE_LINELIST &&
+ var->type != CONFIG_TYPE_LINELIST_V)
+ continue;
+
+ list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset);
+ if (list)
+ list->fragile = 1;
+ }
+}
+
/** If <b>c</b> is a syntactically valid configuration line, update
* <b>options</b> with its value and return 0. Otherwise return -1 for bad
* key, -2 for bad value.
@@ -1870,11 +2209,11 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
* Called from config_assign().
*/
static int
-config_assign_line(config_format_t *fmt, or_options_t *options,
+config_assign_line(const config_format_t *fmt, or_options_t *options,
config_line_t *c, int use_defaults,
int clear_first, bitarray_t *options_seen, char **msg)
{
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
@@ -1902,8 +2241,9 @@ config_assign_line(config_format_t *fmt, or_options_t *options,
if (!strlen(c->value)) {
/* reset or clear it, then return */
if (!clear_first) {
- if (var->type == CONFIG_TYPE_LINELIST ||
- var->type == CONFIG_TYPE_LINELIST_S) {
+ if ((var->type == CONFIG_TYPE_LINELIST ||
+ var->type == CONFIG_TYPE_LINELIST_S) &&
+ c->command != CONFIG_LINE_CLEAR) {
/* We got an empty linelist from the torrc or command line.
As a special case, call this an error. Warn and ignore. */
log_warn(LD_CONFIG,
@@ -1913,6 +2253,8 @@ config_assign_line(config_format_t *fmt, or_options_t *options,
}
}
return 0;
+ } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
+ option_reset(fmt, options, var, use_defaults);
}
if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
@@ -1935,10 +2277,10 @@ config_assign_line(config_format_t *fmt, or_options_t *options,
/** Restore the option named <b>key</b> in options to its default value.
* Called from config_assign(). */
static void
-config_reset_line(config_format_t *fmt, or_options_t *options,
+config_reset_line(const config_format_t *fmt, or_options_t *options,
const char *key, int use_defaults)
{
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
@@ -1953,7 +2295,7 @@ config_reset_line(config_format_t *fmt, or_options_t *options,
int
option_is_recognized(const char *key)
{
- config_var_t *var = config_find_option(&options_format, key);
+ const config_var_t *var = config_find_option(&options_format, key);
return (var != NULL);
}
@@ -1962,14 +2304,14 @@ option_is_recognized(const char *key)
const char *
option_get_canonical_name(const char *key)
{
- config_var_t *var = config_find_option(&options_format, key);
+ const config_var_t *var = config_find_option(&options_format, key);
return var ? var->name : NULL;
}
/** Return a canonical list of the options assigned for key.
*/
config_line_t *
-option_get_assignment(or_options_t *options, const char *key)
+option_get_assignment(const or_options_t *options, const char *key)
{
return get_assigned_option(&options_format, options, key, 1);
}
@@ -2007,7 +2349,7 @@ config_lines_dup(const config_line_t *inp)
config_line_t *result = NULL;
config_line_t **next_out = &result;
while (inp) {
- *next_out = tor_malloc(sizeof(config_line_t));
+ *next_out = tor_malloc_zero(sizeof(config_line_t));
(*next_out)->key = tor_strdup(inp->key);
(*next_out)->value = tor_strdup(inp->value);
inp = inp->next;
@@ -2022,10 +2364,10 @@ config_lines_dup(const config_line_t *inp)
* value needs to be quoted before it's put in a config file, quote and
* escape that value. Return NULL if no such key exists. */
static config_line_t *
-get_assigned_option(config_format_t *fmt, void *options,
+get_assigned_option(const config_format_t *fmt, const void *options,
const char *key, int escape_val)
{
- config_var_t *var;
+ const config_var_t *var;
const void *value;
config_line_t *result;
tor_assert(options && key);
@@ -2071,6 +2413,7 @@ get_assigned_option(config_format_t *fmt, void *options,
}
/* fall through */
case CONFIG_TYPE_INTERVAL:
+ case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
/* This means every or_options_t uint or bool element
* needs to be an int. Not, say, a uint16_t or char. */
@@ -2086,6 +2429,14 @@ get_assigned_option(config_format_t *fmt, void *options,
tor_asprintf(&result->value, "%f", *(double*)value);
escape_val = 0; /* Can't need escape. */
break;
+
+ case CONFIG_TYPE_AUTOBOOL:
+ if (*(int*)value == -1) {
+ result->value = tor_strdup("auto");
+ escape_val = 0;
+ break;
+ }
+ /* fall through */
case CONFIG_TYPE_BOOL:
result->value = tor_strdup(*(int*)value ? "1" : "0");
escape_val = 0; /* Can't need escape. */
@@ -2198,7 +2549,7 @@ options_trial_assign() calls config_assign(1, 1)
returns.
*/
static int
-config_assign(config_format_t *fmt, void *options, config_line_t *list,
+config_assign(const config_format_t *fmt, void *options, config_line_t *list,
int use_defaults, int clear_first, char **msg)
{
config_line_t *p;
@@ -2235,6 +2586,12 @@ config_assign(config_format_t *fmt, void *options, config_line_t *list,
list = list->next;
}
bitarray_free(options_seen);
+
+ /** Now we're done assigning a group of options to the configuration.
+ * Subsequent group assignments should _replace_ linelists, not extend
+ * them. */
+ config_mark_lists_fragile(fmt, options);
+
return 0;
}
@@ -2260,7 +2617,7 @@ options_trial_assign(config_line_t *list, int use_defaults,
return r;
}
- if (options_validate(get_options(), trial_options, 1, msg) < 0) {
+ if (options_validate(get_options_mutable(), trial_options, 1, msg) < 0) {
config_free(&options_format, trial_options);
return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
}
@@ -2282,7 +2639,8 @@ options_trial_assign(config_line_t *list, int use_defaults,
/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
* Called from option_reset() and config_free(). */
static void
-option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
+option_clear(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var)
{
void *lvalue = STRUCT_VAR_P(options, var->var_offset);
(void)fmt; /* unused */
@@ -2298,11 +2656,15 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
*(time_t*)lvalue = 0;
break;
case CONFIG_TYPE_INTERVAL:
+ case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
case CONFIG_TYPE_PORT:
case CONFIG_TYPE_BOOL:
*(int*)lvalue = 0;
break;
+ case CONFIG_TYPE_AUTOBOOL:
+ *(int*)lvalue = -1;
+ break;
case CONFIG_TYPE_MEMUNIT:
*(uint64_t*)lvalue = 0;
break;
@@ -2336,8 +2698,8 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
* <b>use_defaults</b>, set it to its default value.
* Called by config_init() and option_reset_line() and option_assign_line(). */
static void
-option_reset(config_format_t *fmt, or_options_t *options,
- config_var_t *var, int use_defaults)
+option_reset(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var, int use_defaults)
{
config_line_t *c;
char *msg = NULL;
@@ -2377,7 +2739,7 @@ list_torrc_options(void)
int i;
smartlist_t *lines = smartlist_create();
for (i = 0; _option_vars[i].name; ++i) {
- config_var_t *var = &_option_vars[i];
+ const config_var_t *var = &_option_vars[i];
if (var->type == CONFIG_TYPE_OBSOLETE ||
var->type == CONFIG_TYPE_LINELIST_V)
continue;
@@ -2396,7 +2758,7 @@ static uint32_t last_resolved_addr = 0;
* public IP address.
*/
int
-resolve_my_address(int warn_severity, or_options_t *options,
+resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr_out, char **hostname_out)
{
struct in_addr in;
@@ -2405,7 +2767,7 @@ resolve_my_address(int warn_severity, or_options_t *options,
int explicit_ip=1;
int explicit_hostname=1;
int from_interface=0;
- char tmpbuf[INET_NTOA_BUF_LEN];
+ char *addr_string = NULL;
const char *address = options->Address;
int notice_severity = warn_severity <= LOG_NOTICE ?
LOG_NOTICE : warn_severity;
@@ -2447,48 +2809,43 @@ resolve_my_address(int warn_severity, or_options_t *options,
return -1;
}
from_interface = 1;
- in.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ addr = interface_ip;
log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
- "local interface. Using that.", tmpbuf);
+ "local interface. Using that.", fmt_addr32(addr));
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
} else { /* resolved hostname into addr */
- in.s_addr = htonl(addr);
-
if (!explicit_hostname &&
- is_internal_IP(ntohl(in.s_addr), 0)) {
+ is_internal_IP(addr, 0)) {
uint32_t interface_ip;
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
- "resolves to a private IP address (%s). Trying something "
- "else.", hostname, tmpbuf);
+ "resolves to a private IP address (%s). Trying something "
+ "else.", hostname, fmt_addr32(addr));
if (get_interface_address(warn_severity, &interface_ip)) {
log_fn(warn_severity, LD_CONFIG,
"Could not get local interface IP address. Too bad.");
} else if (is_internal_IP(interface_ip, 0)) {
- struct in_addr in2;
- in2.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
log_fn(notice_severity, LD_CONFIG,
"Interface IP address '%s' is a private address too. "
- "Ignoring.", tmpbuf);
+ "Ignoring.", fmt_addr32(interface_ip));
} else {
from_interface = 1;
- in.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ addr = interface_ip;
log_fn(notice_severity, LD_CONFIG,
"Learned IP address '%s' for local interface."
- " Using that.", tmpbuf);
+ " Using that.", fmt_addr32(addr));
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
}
}
}
+ } else {
+ addr = ntohl(in.s_addr); /* set addr so that addr_string is not
+ * illformed */
}
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- if (is_internal_IP(ntohl(in.s_addr), 0)) {
+ addr_string = tor_dup_ip(addr);
+ if (is_internal_IP(addr, 0)) {
/* make sure we're ok with publishing an internal IP */
if (!options->DirServers && !options->AlternateDirAuthority) {
/* if they are using the default dirservers, disallow internal IPs
@@ -2496,7 +2853,8 @@ resolve_my_address(int warn_severity, or_options_t *options,
log_fn(warn_severity, LD_CONFIG,
"Address '%s' resolves to private IP address '%s'. "
"Tor servers that use the default DirServers must have public "
- "IP addresses.", hostname, tmpbuf);
+ "IP addresses.", hostname, addr_string);
+ tor_free(addr_string);
return -1;
}
if (!explicit_ip) {
@@ -2504,19 +2862,20 @@ resolve_my_address(int warn_severity, or_options_t *options,
* they're using an internal address. */
log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
"IP address '%s'. Please set the Address config option to be "
- "the IP address you want to use.", hostname, tmpbuf);
+ "the IP address you want to use.", hostname, addr_string);
+ tor_free(addr_string);
return -1;
}
}
- log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
- *addr_out = ntohl(in.s_addr);
+ log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr));
+ *addr_out = addr;
if (last_resolved_addr && last_resolved_addr != *addr_out) {
/* Leave this as a notice, regardless of the requested severity,
* at least until dynamic IP address support becomes bulletproof. */
log_notice(LD_NET,
"Your IP address seems to have changed to %s. Updating.",
- tmpbuf);
+ addr_string);
ip_address_changed(0);
}
if (last_resolved_addr != *addr_out) {
@@ -2535,11 +2894,12 @@ resolve_my_address(int warn_severity, or_options_t *options,
}
control_event_server_status(LOG_NOTICE,
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
- tmpbuf, method, h?"HOSTNAME=":"", h);
+ addr_string, method, h?"HOSTNAME=":"", h);
}
last_resolved_addr = *addr_out;
if (hostname_out)
*hostname_out = tor_strdup(hostname);
+ tor_free(addr_string);
return 0;
}
@@ -2574,7 +2934,7 @@ is_local_addr(const tor_addr_t *addr)
/** Release storage held by <b>options</b>. */
static void
-config_free(config_format_t *fmt, void *options)
+config_free(const config_format_t *fmt, void *options)
{
int i;
@@ -2613,8 +2973,9 @@ config_lines_eq(config_line_t *a, config_line_t *b)
* and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
*/
static int
-option_is_same(config_format_t *fmt,
- or_options_t *o1, or_options_t *o2, const char *name)
+option_is_same(const config_format_t *fmt,
+ const or_options_t *o1, const or_options_t *o2,
+ const char *name)
{
config_line_t *c1, *c2;
int r = 1;
@@ -2631,7 +2992,7 @@ option_is_same(config_format_t *fmt,
/** Copy storage held by <b>old</b> into a new or_options_t and return it. */
static or_options_t *
-options_dup(config_format_t *fmt, or_options_t *old)
+options_dup(const config_format_t *fmt, const or_options_t *old)
{
or_options_t *newopts;
int i;
@@ -2695,7 +3056,7 @@ is_listening_on_low_port(int port_option,
return (port_option < 1024);
for (l = listen_options; l; l = l->next) {
- parse_addr_port(LOG_WARN, l->value, NULL, NULL, &p);
+ addr_port_lookup(LOG_WARN, l->value, NULL, NULL, &p);
if (p<1024) {
return 1;
}
@@ -2707,10 +3068,10 @@ is_listening_on_low_port(int port_option,
/** Set all vars in the configuration object <b>options</b> to their default
* values. */
static void
-config_init(config_format_t *fmt, void *options)
+config_init(const config_format_t *fmt, void *options)
{
int i;
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
for (i=0; fmt->vars[i].name; ++i) {
@@ -2726,24 +3087,30 @@ config_init(config_format_t *fmt, void *options)
* Else, if comment_defaults, write default values as comments.
*/
static char *
-config_dump(config_format_t *fmt, void *options, int minimal,
+config_dump(const config_format_t *fmt, const void *default_options,
+ const void *options, int minimal,
int comment_defaults)
{
smartlist_t *elements;
- or_options_t *defaults;
+ const or_options_t *defaults = default_options;
+ void *defaults_tmp = NULL;
config_line_t *line, *assigned;
char *result;
int i;
char *msg = NULL;
- defaults = config_alloc(fmt);
- config_init(fmt, defaults);
+ if (defaults == NULL) {
+ defaults = defaults_tmp = config_alloc(fmt);
+ config_init(fmt, defaults_tmp);
+ }
/* XXX use a 1 here so we don't add a new log line while dumping */
- if (fmt->validate_fn(NULL,defaults, 1, &msg) < 0) {
- log_err(LD_BUG, "Failed to validate default config.");
- tor_free(msg);
- tor_assert(0);
+ if (default_options == NULL) {
+ if (fmt->validate_fn(NULL, defaults_tmp, 1, &msg) < 0) {
+ log_err(LD_BUG, "Failed to validate default config.");
+ tor_free(msg);
+ tor_assert(0);
+ }
}
elements = smartlist_create();
@@ -2785,7 +3152,8 @@ config_dump(config_format_t *fmt, void *options, int minimal,
result = smartlist_join_strings(elements, "", 0, NULL);
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements);
- config_free(fmt, defaults);
+ if (defaults_tmp)
+ config_free(fmt, defaults_tmp);
return result;
}
@@ -2794,9 +3162,10 @@ config_dump(config_format_t *fmt, void *options, int minimal,
* include options that are the same as Tor's defaults.
*/
char *
-options_dump(or_options_t *options, int minimal)
+options_dump(const or_options_t *options, int minimal)
{
- return config_dump(&options_format, options, minimal, 0);
+ return config_dump(&options_format, global_default_options,
+ options, minimal, 0);
}
/** Return 0 if every element of sl is a string holding a decimal
@@ -2853,24 +3222,24 @@ static int
compute_publishserverdescriptor(or_options_t *options)
{
smartlist_t *list = options->PublishServerDescriptor;
- authority_type_t *auth = &options->_PublishServerDescriptor;
- *auth = NO_AUTHORITY;
+ dirinfo_type_t *auth = &options->_PublishServerDescriptor;
+ *auth = NO_DIRINFO;
if (!list) /* empty list, answer is none */
return 0;
SMARTLIST_FOREACH(list, const char *, string, {
if (!strcasecmp(string, "v1"))
- *auth |= V1_AUTHORITY;
+ *auth |= V1_DIRINFO;
else if (!strcmp(string, "1"))
if (options->BridgeRelay)
- *auth |= BRIDGE_AUTHORITY;
+ *auth |= BRIDGE_DIRINFO;
else
- *auth |= V2_AUTHORITY | V3_AUTHORITY;
+ *auth |= V2_DIRINFO | V3_DIRINFO;
else if (!strcasecmp(string, "v2"))
- *auth |= V2_AUTHORITY;
+ *auth |= V2_DIRINFO;
else if (!strcasecmp(string, "v3"))
- *auth |= V3_AUTHORITY;
+ *auth |= V3_DIRINFO;
else if (!strcasecmp(string, "bridge"))
- *auth |= BRIDGE_AUTHORITY;
+ *auth |= BRIDGE_DIRINFO;
else if (!strcasecmp(string, "hidserv"))
log_warn(LD_CONFIG,
"PublishServerDescriptor hidserv is invalid. See "
@@ -2898,6 +3267,10 @@ compute_publishserverdescriptor(or_options_t *options)
* will generate too many circuits and potentially overload the network. */
#define MIN_CIRCUIT_STREAM_TIMEOUT 10
+/** Lowest allowable value for HeartbeatPeriod; if this is too low, we might
+ * expose more information than we're comfortable with. */
+#define MIN_HEARTBEAT_PERIOD (30*60)
+
/** Return 0 if every setting in <b>options</b> is reasonable, and a
* permissible transition from <b>old_options</b>. Else return -1.
* Should have no side effects, except for normalizing the contents of
@@ -2917,6 +3290,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
int i;
config_line_t *cl;
const char *uname = get_uname();
+ int n_client_ports=0;
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
@@ -2940,57 +3314,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->DirPort == 0 && options->DirListenAddress != NULL)
REJECT("DirPort must be defined if DirListenAddress is defined.");
- if (options->DNSPort == 0 && options->DNSListenAddress != NULL)
- REJECT("DNSPort must be defined if DNSListenAddress is defined.");
-
- if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
- REJECT("ControlPort must be defined if ControlListenAddress is defined.");
-
- if (options->TransPort == 0 && options->TransListenAddress != NULL)
- REJECT("TransPort must be defined if TransListenAddress is defined.");
-
- if (options->NATDPort == 0 && options->NATDListenAddress != NULL)
- REJECT("NATDPort must be defined if NATDListenAddress is defined.");
-
- /* Don't gripe about SocksPort 0 with SocksListenAddress set; a standard
- * configuration does this. */
-
- for (i = 0; i < 3; ++i) {
- int is_socks = i==0;
- int is_trans = i==1;
- config_line_t *line, *opt, *old;
- const char *tp;
- if (is_socks) {
- opt = options->SocksListenAddress;
- old = old_options ? old_options->SocksListenAddress : NULL;
- tp = "SOCKS proxy";
- } else if (is_trans) {
- opt = options->TransListenAddress;
- old = old_options ? old_options->TransListenAddress : NULL;
- tp = "transparent proxy";
- } else {
- opt = options->NATDListenAddress;
- old = old_options ? old_options->NATDListenAddress : NULL;
- tp = "natd proxy";
- }
-
- for (line = opt; line; line = line->next) {
- char *address = NULL;
- uint16_t port;
- uint32_t addr;
- if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0)
- continue; /* We'll warn about this later. */
- if (!is_internal_IP(addr, 1) &&
- (!old_options || !config_lines_eq(old, opt))) {
- log_warn(LD_CONFIG,
- "You specified a public address '%s' for a %s. Other "
- "people on the Internet might find your computer and use it as "
- "an open %s. Please don't allow this unless you have "
- "a good reason.", address, tp, tp);
- }
- tor_free(address);
- }
- }
+ if (parse_client_ports(options, 1, msg, &n_client_ports) < 0)
+ return -1;
if (validate_data_directory(options)<0)
REJECT("Invalid DataDirectory");
@@ -3014,8 +3339,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
"misconfigured or something else goes wrong.");
/* Special case on first boot if no Log options are given. */
- if (!options->Logs && !options->RunAsDaemon && !from_setconf)
- config_line_append(&options->Logs, "Log", "notice stdout");
+ if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
+ if (quiet_level == 0)
+ config_line_append(&options->Logs, "Log", "notice stdout");
+ else if (quiet_level == 1)
+ config_line_append(&options->Logs, "Log", "warn stdout");
+ }
if (options_init_logs(options, 1)<0) /* Validate the log(s) */
REJECT("Failed to validate Log options. See logs for details.");
@@ -3027,20 +3356,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Failed to resolve/guess local address. See logs for details.");
}
- if (strcmp(options->RefuseUnknownExits, "0") &&
- strcmp(options->RefuseUnknownExits, "1") &&
- strcmp(options->RefuseUnknownExits, "auto")) {
- REJECT("RefuseUnknownExits must be 0, 1, or auto");
- }
-
#ifndef MS_WINDOWS
if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
#endif
- if (options->SocksPort == 0 && options->TransPort == 0 &&
- options->NATDPort == 0 && options->ORPort == 0 &&
- options->DNSPort == 0 && !options->RendConfigLines)
+ if (n_client_ports == 0 && options->ORPort == 0 && !options->RendConfigLines)
log(LOG_WARN, LD_CONFIG,
"SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all "
"undefined, and there aren't any hidden services configured. "
@@ -3051,6 +3372,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("TransPort and TransListenAddress are disabled in this build.");
#endif
+ if (options->TokenBucketRefillInterval <= 0
+ || options->TokenBucketRefillInterval > 1000) {
+ REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
+ }
+
if (options->AccountingMax &&
(is_listening_on_low_port(options->ORPort, options->ORListenAddress) ||
is_listening_on_low_port(options->DirPort, options->DirListenAddress)))
@@ -3070,17 +3396,24 @@ options_validate(or_options_t *old_options, or_options_t *options,
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
}
+ if (options->NodeFamilies) {
+ options->NodeFamilySets = smartlist_create();
+ for (cl = options->NodeFamilies; cl; cl = cl->next) {
+ routerset_t *rs = routerset_new();
+ if (routerset_parse(rs, cl->value, cl->key) == 0) {
+ smartlist_add(options->NodeFamilySets, rs);
+ } else {
+ routerset_free(rs);
+ }
+ }
+ }
+
if (options->ExcludeNodes && options->StrictNodes) {
COMPLAIN("You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
"features to be broken in unpredictable ways.");
}
- if (options->EntryNodes && !routerset_is_list(options->EntryNodes)) {
- /* XXXX fix this; see entry_guards_prepend_from_config(). */
- REJECT("IPs or countries are not yet supported in EntryNodes.");
- }
-
if (options->AuthoritativeDir) {
if (!options->ContactInfo && !options->TestingTorNetwork)
REJECT("Authoritative directory servers must set ContactInfo");
@@ -3142,6 +3475,15 @@ options_validate(or_options_t *old_options, or_options_t *options,
return -1;
}
+ if (options->MaxClientCircuitsPending <= 0 ||
+ options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) {
+ tor_asprintf(msg,
+ "MaxClientCircuitsPending must be between 1 and %d, but "
+ "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING,
+ options->MaxClientCircuitsPending);
+ return -1;
+ }
+
if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
return -1;
@@ -3290,9 +3632,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if ((options->BridgeRelay
- || options->_PublishServerDescriptor & BRIDGE_AUTHORITY)
+ || options->_PublishServerDescriptor & BRIDGE_DIRINFO)
&& (options->_PublishServerDescriptor
- & (V1_AUTHORITY|V2_AUTHORITY|V3_AUTHORITY))) {
+ & (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
REJECT("Bridges are not supposed to publish router descriptors to the "
"directory authorities. Please correct your "
"PublishServerDescriptor line.");
@@ -3335,6 +3677,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT;
}
+ if (options->HeartbeatPeriod &&
+ options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD) {
+ log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; "
+ "raising to %d seconds.", MIN_HEARTBEAT_PERIOD);
+ options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD;
+ }
+
if (options->KeepalivePeriod < 1)
REJECT("KeepalivePeriod option must be positive.");
@@ -3359,6 +3708,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (ensure_bandwidth_cap(&options->PerConnBWBurst,
"PerConnBWBurst", msg) < 0)
return -1;
+ if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
+ "AuthDirFastGuarantee", msg) < 0)
+ return -1;
+ if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
+ "AuthDirGuardBWGuarantee", msg) < 0)
+ return -1;
if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
options->RelayBandwidthBurst = options->RelayBandwidthRate;
@@ -3411,7 +3766,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Failed to parse accounting options. See logs for details.");
if (options->HTTPProxy) { /* parse it now */
- if (tor_addr_port_parse(options->HTTPProxy,
+ if (tor_addr_port_lookup(options->HTTPProxy,
&options->HTTPProxyAddr, &options->HTTPProxyPort) < 0)
REJECT("HTTPProxy failed to parse or resolve. Please fix.");
if (options->HTTPProxyPort == 0) { /* give it a default */
@@ -3425,7 +3780,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->HTTPSProxy) { /* parse it now */
- if (tor_addr_port_parse(options->HTTPSProxy,
+ if (tor_addr_port_lookup(options->HTTPSProxy,
&options->HTTPSProxyAddr, &options->HTTPSProxyPort) <0)
REJECT("HTTPSProxy failed to parse or resolve. Please fix.");
if (options->HTTPSProxyPort == 0) { /* give it a default */
@@ -3439,7 +3794,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->Socks4Proxy) { /* parse it now */
- if (tor_addr_port_parse(options->Socks4Proxy,
+ if (tor_addr_port_lookup(options->Socks4Proxy,
&options->Socks4ProxyAddr,
&options->Socks4ProxyPort) <0)
REJECT("Socks4Proxy failed to parse or resolve. Please fix.");
@@ -3449,7 +3804,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->Socks5Proxy) { /* parse it now */
- if (tor_addr_port_parse(options->Socks5Proxy,
+ if (tor_addr_port_lookup(options->Socks5Proxy,
&options->Socks5ProxyAddr,
&options->Socks5ProxyPort) <0)
REJECT("Socks5Proxy failed to parse or resolve. Please fix.");
@@ -3458,8 +3813,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- if (options->Socks4Proxy && options->Socks5Proxy)
- REJECT("You cannot specify both Socks4Proxy and SOCKS5Proxy");
+ /* Check if more than one proxy type has been enabled. */
+ if (!!options->Socks4Proxy + !!options->Socks5Proxy +
+ !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
+ REJECT("You have configured more than one proxy type. "
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
if (options->Socks5ProxyUsername) {
size_t len;
@@ -3562,8 +3920,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (check_nickname_list(options->MyFamily, "MyFamily", msg))
return -1;
for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (check_nickname_list(cl->value, "NodeFamily", msg))
+ routerset_t *rs = routerset_new();
+ if (routerset_parse(rs, cl->value, cl->key)) {
+ routerset_free(rs);
return -1;
+ }
+ routerset_free(rs);
}
if (validate_addr_policies(options, msg) < 0)
@@ -3576,11 +3938,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("If you set UseBridges, you must specify at least one bridge.");
if (options->UseBridges && !options->TunnelDirConns)
REJECT("If you set UseBridges, you must set TunnelDirConns.");
- if (options->Bridges) {
- for (cl = options->Bridges; cl; cl = cl->next) {
- if (parse_bridge_line(cl->value, 1)<0)
- REJECT("Bridge line did not parse. See logs for details.");
- }
+
+ for (cl = options->Bridges; cl; cl = cl->next) {
+ if (parse_bridge_line(cl->value, 1)<0)
+ REJECT("Bridge line did not parse. See logs for details.");
+ }
+
+ for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+ if (parse_client_transport_line(cl->value, 1)<0)
+ REJECT("Transport line did not parse. See logs for details.");
+ }
+
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (parse_server_transport_line(cl->value, 1)<0)
+ REJECT("Server transport line did not parse. See logs for details.");
}
if (options->ConstrainedSockets) {
@@ -3763,17 +4134,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
static int
opt_streq(const char *s1, const char *s2)
{
- if (!s1 && !s2)
- return 1;
- else if (s1 && s2 && !strcmp(s1,s2))
- return 1;
- else
- return 0;
+ return 0 == strcmp_opt(s1, s2);
}
/** Check if any of the previous options have changed but aren't allowed to. */
static int
-options_transition_allowed(or_options_t *old, or_options_t *new_val,
+options_transition_allowed(const or_options_t *old,
+ const or_options_t *new_val,
char **msg)
{
if (!old)
@@ -3823,14 +4190,26 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val,
return -1;
}
+ if (old->TokenBucketRefillInterval != new_val->TokenBucketRefillInterval) {
+ *msg = tor_strdup("While Tor is running, changing TokenBucketRefill"
+ "Interval is not allowed");
+ return -1;
+ }
+
+ if (old->DisableIOCP != new_val->DisableIOCP) {
+ *msg = tor_strdup("While Tor is running, changing DisableIOCP "
+ "is not allowed.");
+ return -1;
+ }
+
return 0;
}
/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
* will require us to rotate the CPU and DNS workers; else return 0. */
static int
-options_transition_affects_workers(or_options_t *old_options,
- or_options_t *new_options)
+options_transition_affects_workers(const or_options_t *old_options,
+ const or_options_t *new_options)
{
if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
old_options->NumCPUs != new_options->NumCPUs ||
@@ -3853,8 +4232,8 @@ options_transition_affects_workers(or_options_t *old_options,
/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
* will require us to generate a new descriptor; else return 0. */
static int
-options_transition_affects_descriptor(or_options_t *old_options,
- or_options_t *new_options)
+options_transition_affects_descriptor(const or_options_t *old_options,
+ const or_options_t *new_options)
{
/* XXX We can be smarter here. If your DirPort isn't being
* published and you just turned it off, no need to republish. Etc. */
@@ -3867,6 +4246,7 @@ options_transition_affects_descriptor(or_options_t *old_options,
old_options->ORPort != new_options->ORPort ||
old_options->DirPort != new_options->DirPort ||
old_options->ClientOnly != new_options->ClientOnly ||
+ old_options->DisableNetwork != new_options->DisableNetwork ||
old_options->_PublishServerDescriptor !=
new_options->_PublishServerDescriptor ||
get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
@@ -3875,7 +4255,8 @@ options_transition_affects_descriptor(or_options_t *old_options,
!opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
!opt_streq(old_options->MyFamily, new_options->MyFamily) ||
!opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
- old_options->AccountingMax != new_options->AccountingMax)
+ old_options->AccountingMax != new_options->AccountingMax ||
+ public_server_mode(old_options) != public_server_mode(new_options))
return 1;
return 0;
@@ -3939,17 +4320,25 @@ get_windows_conf_root(void)
}
#endif
-/** Return the default location for our torrc file. */
+/** Return the default location for our torrc file.
+ * DOCDOC defaults_file */
static const char *
-get_default_conf_file(void)
+get_default_conf_file(int defaults_file)
{
#ifdef MS_WINDOWS
- static char path[MAX_PATH+1];
- strlcpy(path, get_windows_conf_root(), MAX_PATH);
- strlcat(path,"\\torrc",MAX_PATH);
- return path;
+ if (defaults_file) {
+ static char defaults_path[MAX_PATH+1];
+ tor_snprintf(defaults_path, MAX_PATH, "%s\\torrc-defaults",
+ get_windows_conf_root());
+ return defaults_path;
+ } else {
+ static char path[MAX_PATH+1];
+ tor_snprintf(path, MAX_PATH, "%s\\torrc",
+ get_windows_conf_root());
+ return path;
+ }
#else
- return (CONFDIR "/torrc");
+ return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc";
#endif
}
@@ -3982,37 +4371,46 @@ check_nickname_list(const char *lst, const char *name, char **msg)
return r;
}
-/** Learn config file name from command line arguments, or use the default */
+/** Learn config file name from command line arguments, or use the default,
+ * DOCDOC defaults_file */
static char *
find_torrc_filename(int argc, char **argv,
+ int defaults_file,
int *using_default_torrc, int *ignore_missing_torrc)
{
char *fname=NULL;
int i;
+ const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f";
+ const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc";
+
+ if (defaults_file)
+ *ignore_missing_torrc = 1;
for (i = 1; i < argc; ++i) {
- if (i < argc-1 && !strcmp(argv[i],"-f")) {
+ if (i < argc-1 && !strcmp(argv[i],fname_opt)) {
if (fname) {
- log(LOG_WARN, LD_CONFIG, "Duplicate -f options on command line.");
+ log(LOG_WARN, LD_CONFIG, "Duplicate %s options on command line.",
+ fname_opt);
tor_free(fname);
}
fname = expand_filename(argv[i+1]);
*using_default_torrc = 0;
++i;
- } else if (!strcmp(argv[i],"--ignore-missing-torrc")) {
+ } else if (ignore_opt && !strcmp(argv[i],ignore_opt)) {
*ignore_missing_torrc = 1;
}
}
if (*using_default_torrc) {
/* didn't find one, try CONFDIR */
- const char *dflt = get_default_conf_file();
+ const char *dflt = get_default_conf_file(defaults_file);
if (dflt && file_status(dflt) == FN_FILE) {
fname = tor_strdup(dflt);
} else {
#ifndef MS_WINDOWS
- char *fn;
- fn = expand_filename("~/.torrc");
+ char *fn = NULL;
+ if (!defaults_file)
+ fn = expand_filename("~/.torrc");
if (fn && file_status(fn) == FN_FILE) {
fname = fn;
} else {
@@ -4027,43 +4425,48 @@ find_torrc_filename(int argc, char **argv,
return fname;
}
-/** Load torrc from disk, setting torrc_fname if successful */
+/** Load torrc from disk, setting torrc_fname if successful.
+ * DOCDOC defaults_file */
static char *
-load_torrc_from_disk(int argc, char **argv)
+load_torrc_from_disk(int argc, char **argv, int defaults_file)
{
char *fname=NULL;
char *cf = NULL;
int using_default_torrc = 1;
int ignore_missing_torrc = 0;
+ char **fname_var = defaults_file ? &torrc_defaults_fname : &torrc_fname;
- fname = find_torrc_filename(argc, argv,
+ fname = find_torrc_filename(argc, argv, defaults_file,
&using_default_torrc, &ignore_missing_torrc);
tor_assert(fname);
log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname);
- tor_free(torrc_fname);
- torrc_fname = fname;
+ tor_free(*fname_var);
+ *fname_var = fname;
/* Open config file */
if (file_status(fname) != FN_FILE ||
!(cf = read_file_to_str(fname,0,NULL))) {
- if (using_default_torrc == 1 || ignore_missing_torrc ) {
- log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
- "using reasonable defaults.", fname);
+ if (using_default_torrc == 1 || ignore_missing_torrc) {
+ if (!defaults_file)
+ log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
+ "using reasonable defaults.", fname);
tor_free(fname); /* sets fname to NULL */
- torrc_fname = NULL;
+ *fname_var = NULL;
cf = tor_strdup("");
} else {
log(LOG_WARN, LD_CONFIG,
"Unable to open configuration file \"%s\".", fname);
goto err;
}
+ } else {
+ log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname);
}
return cf;
err:
tor_free(fname);
- torrc_fname = NULL;
+ *fname_var = NULL;
return NULL;
}
@@ -4074,7 +4477,7 @@ load_torrc_from_disk(int argc, char **argv)
int
options_init_from_torrc(int argc, char **argv)
{
- char *cf=NULL;
+ char *cf=NULL, *cf_defaults=NULL;
int i, retval, command;
static char **backup_argv;
static int backup_argc;
@@ -4134,13 +4537,15 @@ options_init_from_torrc(int argc, char **argv)
if (command == CMD_HASH_PASSWORD) {
cf = tor_strdup("");
} else {
- cf = load_torrc_from_disk(argc, argv);
+ cf_defaults = load_torrc_from_disk(argc, argv, 1);
+ cf = load_torrc_from_disk(argc, argv, 0);
if (!cf)
goto err;
}
- retval = options_init_from_string(cf, command, command_arg, &errmsg);
+ retval = options_init_from_string(cf_defaults, cf, command, command_arg, &errmsg);
tor_free(cf);
+ tor_free(cf_defaults);
if (retval < 0)
goto err;
@@ -4164,13 +4569,13 @@ options_init_from_torrc(int argc, char **argv)
* * -4 for error while setting the new options
*/
setopt_err_t
-options_init_from_string(const char *cf,
+options_init_from_string(const char *cf_defaults, const char *cf,
int command, const char *command_arg,
char **msg)
{
- or_options_t *oldoptions, *newoptions;
+ or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL;
config_line_t *cl;
- int retval;
+ int retval, i;
setopt_err_t err = SETOPT_ERR_MISC;
tor_assert(msg);
@@ -4183,17 +4588,24 @@ options_init_from_string(const char *cf,
newoptions->command = command;
newoptions->command_arg = command_arg;
- /* get config lines, assign them */
- retval = config_get_lines(cf, &cl);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
- }
- retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
- config_free_lines(cl);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
+ for (i = 0; i < 2; ++i) {
+ const char *body = i==0 ? cf_defaults : cf;
+ if (!body)
+ continue;
+ /* get config lines, assign them */
+ retval = config_get_lines(body, &cl, 1);
+ if (retval < 0) {
+ err = SETOPT_ERR_PARSE;
+ goto err;
+ }
+ retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
+ config_free_lines(cl);
+ if (retval < 0) {
+ err = SETOPT_ERR_PARSE;
+ goto err;
+ }
+ if (i==0)
+ newdefaultoptions = options_dup(&options_format, newoptions);
}
/* Go through command-line variables too */
@@ -4218,9 +4630,9 @@ options_init_from_string(const char *cf,
/* Change defaults. */
int i;
for (i = 0; testing_tor_network_defaults[i].name; ++i) {
- config_var_t *new_var = &testing_tor_network_defaults[i];
+ const config_var_t *new_var = &testing_tor_network_defaults[i];
config_var_t *old_var =
- config_find_option(&options_format, new_var->name);
+ config_find_option_mutable(&options_format, new_var->name);
tor_assert(new_var);
tor_assert(old_var);
old_var->initvalue = new_var->initvalue;
@@ -4228,6 +4640,8 @@ options_init_from_string(const char *cf,
/* Clear newoptions and re-initialize them with new defaults. */
config_free(&options_format, newoptions);
+ config_free(&options_format, newdefaultoptions);
+ newdefaultoptions = NULL;
newoptions = tor_malloc_zero(sizeof(or_options_t));
newoptions->_magic = OR_OPTIONS_MAGIC;
options_init(newoptions);
@@ -4235,22 +4649,24 @@ options_init_from_string(const char *cf,
newoptions->command_arg = command_arg;
/* Assign all options a second time. */
- retval = config_get_lines(cf, &cl);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
- }
- retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
- config_free_lines(cl);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
- }
- retval = config_assign(&options_format, newoptions,
- global_cmdline_options, 0, 0, msg);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
+ for (i = 0; i < 2; ++i) {
+ const char *body = i==0 ? cf_defaults : cf;
+ if (!body)
+ continue;
+ /* get config lines, assign them */
+ retval = config_get_lines(body, &cl, 1);
+ if (retval < 0) {
+ err = SETOPT_ERR_PARSE;
+ goto err;
+ }
+ retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
+ config_free_lines(cl);
+ if (retval < 0) {
+ err = SETOPT_ERR_PARSE;
+ goto err;
+ }
+ if (i==0)
+ newdefaultoptions = options_dup(&options_format, newoptions);
}
}
@@ -4269,11 +4685,14 @@ options_init_from_string(const char *cf,
err = SETOPT_ERR_SETTING;
goto err; /* frees and replaces old options */
}
+ config_free(&options_format, global_default_options);
+ global_default_options = newdefaultoptions;
return SETOPT_OK;
err:
config_free(&options_format, newoptions);
+ config_free(&options_format, newdefaultoptions);
if (*msg) {
char *old_msg = *msg;
tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
@@ -4285,19 +4704,21 @@ options_init_from_string(const char *cf,
/** Return the location for our configuration file.
*/
const char *
-get_torrc_fname(void)
+get_torrc_fname(int defaults_fname)
{
- if (torrc_fname)
- return torrc_fname;
+ const char *fname = defaults_fname ? torrc_defaults_fname : torrc_fname;
+
+ if (fname)
+ return fname;
else
- return get_default_conf_file();
+ return get_default_conf_file(defaults_fname);
}
/** Adjust the address map based on the MapAddress elements in the
* configuration <b>options</b>
*/
-static void
-config_register_addressmaps(or_options_t *options)
+void
+config_register_addressmaps(const or_options_t *options)
{
smartlist_t *elts;
config_line_t *opt;
@@ -4346,6 +4767,35 @@ options_init_logs(or_options_t *options, int validate_only)
options->RunAsDaemon;
#endif
+ if (options->LogTimeGranularity <= 0) {
+ log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
+ options->LogTimeGranularity);
+ return -1;
+ } else if (1000 % options->LogTimeGranularity != 0 &&
+ options->LogTimeGranularity % 1000 != 0) {
+ int granularity = options->LogTimeGranularity;
+ if (granularity < 40) {
+ do granularity++;
+ while (1000 % granularity != 0);
+ } else if (granularity < 1000) {
+ granularity = 1000 / granularity;
+ while (1000 % granularity != 0)
+ granularity--;
+ granularity = 1000 / granularity;
+ } else {
+ granularity = 1000 * ((granularity / 1000) + 1);
+ }
+ log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a "
+ "divisor or a multiple of 1 second. Changing to "
+ "'%d'.",
+ options->LogTimeGranularity, granularity);
+ if (!validate_only)
+ set_log_time_granularity(granularity);
+ } else {
+ if (!validate_only)
+ set_log_time_granularity(options->LogTimeGranularity);
+ }
+
ok = 1;
elts = smartlist_create();
@@ -4435,6 +4885,8 @@ parse_bridge_line(const char *line, int validate_only)
smartlist_t *items = NULL;
int r;
char *addrport=NULL, *fingerprint=NULL;
+ char *transport_name=NULL;
+ char *field1=NULL;
tor_addr_t addr;
uint16_t port = 0;
char digest[DIGEST_LEN];
@@ -4446,9 +4898,25 @@ parse_bridge_line(const char *line, int validate_only)
log_warn(LD_CONFIG, "Too few arguments to Bridge line.");
goto err;
}
- addrport = smartlist_get(items, 0);
+
+ /* field1 is either a transport name or addrport */
+ field1 = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
- if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+
+ if (!(strstr(field1, ".") || strstr(field1, ":"))) {
+ /* new-style bridge line */
+ transport_name = field1;
+ if (smartlist_len(items) < 1) {
+ log_warn(LD_CONFIG, "Too few items to Bridge line.");
+ goto err;
+ }
+ addrport = smartlist_get(items, 0);
+ smartlist_del_keeporder(items, 0);
+ } else {
+ addrport = field1;
+ }
+
+ if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport);
goto err;
}
@@ -4472,26 +4940,282 @@ parse_bridge_line(const char *line, int validate_only)
}
if (!validate_only) {
- log_debug(LD_DIR, "Bridge at %s:%d (%s)", fmt_addr(&addr),
- (int)port,
+ log_debug(LD_DIR, "Bridge at %s:%d (transport: %s) (%s)",
+ fmt_addr(&addr), (int)port,
+ transport_name ? transport_name : "no transport",
fingerprint ? fingerprint : "no key listed");
- bridge_add_from_config(&addr, port, fingerprint ? digest : NULL);
+ bridge_add_from_config(&addr, port,
+ fingerprint ? digest : NULL, transport_name);
}
r = 0;
goto done;
- err:
+ err:
r = -1;
- done:
+ done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
tor_free(addrport);
+ tor_free(transport_name);
tor_free(fingerprint);
return r;
}
+/** Read the contents of a ClientTransportPlugin line from
+ * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ *
+ * If <b>validate_only</b> is 0, and the line is well-formed:
+ * - If it's an external proxy line, add the transport described in the line to
+ * our internal transport list.
+ * - If it's a managed proxy line, launch the managed proxy. */
+static int
+parse_client_transport_line(const char *line, int validate_only)
+{
+ smartlist_t *items = NULL;
+ int r;
+ char *field2=NULL;
+
+ const char *transports=NULL;
+ smartlist_t *transport_list=NULL;
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+ int socks_ver=PROXY_NONE;
+
+ /* managed proxy options */
+ int is_managed=0;
+ char **proxy_argv=NULL;
+ char **tmp=NULL;
+ int proxy_argc,i;
+
+ int line_length;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ line_length = smartlist_len(items);
+ if (line_length < 3) {
+ log_warn(LD_CONFIG, "Too few arguments on ClientTransportPlugin line.");
+ goto err;
+ }
+
+ /* Get the first line element, split it to commas into
+ transport_list (in case it's multiple transports) and validate
+ the transport names. */
+ transports = smartlist_get(items, 0);
+ transport_list = smartlist_create();
+ smartlist_split_string(transport_list, transports, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
+ if (!string_is_C_identifier(transport_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ transport_name);
+ goto err;
+ }
+ } SMARTLIST_FOREACH_END(transport_name);
+
+ /* field2 is either a SOCKS version or "exec" */
+ field2 = smartlist_get(items, 1);
+
+ if (!strcmp(field2,"socks4")) {
+ socks_ver = PROXY_SOCKS4;
+ } else if (!strcmp(field2,"socks5")) {
+ socks_ver = PROXY_SOCKS5;
+ } else if (!strcmp(field2,"exec")) {
+ is_managed=1;
+ } else {
+ log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.",
+ field2);
+ goto err;
+ }
+
+ if (is_managed) { /* managed */
+ if (!validate_only) { /* if we are not just validating, use the
+ rest of the line as the argv of the proxy
+ to be launched */
+ proxy_argc = line_length-2;
+ tor_assert(proxy_argc > 0);
+ proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
+ tmp = proxy_argv;
+ for (i=0;i<proxy_argc;i++) { /* store arguments */
+ *tmp++ = smartlist_get(items, 2);
+ smartlist_del_keeporder(items, 2);
+ }
+ *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+
+ /* kickstart the thing */
+ pt_kickstart_client_proxy(transport_list, proxy_argv);
+ }
+ } else { /* external */
+ if (smartlist_len(transport_list) != 1) {
+ log_warn(LD_CONFIG, "You can't have an external proxy with "
+ "more than one transports.");
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 2);
+
+ if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ if (!validate_only) {
+ transport_add_from_config(&addr, port, smartlist_get(transport_list, 0),
+ socks_ver);
+
+ log_info(LD_DIR, "Transport '%s' found at %s:%d",
+ transports, fmt_addr(&addr), (int)port);
+ }
+ }
+
+ r = 0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ if (transport_list) {
+ SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
+ smartlist_free(transport_list);
+ }
+
+ return r;
+}
+
+/** Read the contents of a ServerTransportPlugin line from
+ * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ * If <b>validate_only</b> is 0, the line is well-formed, and it's a
+ * managed proxy line, launch the managed proxy. */
+static int
+parse_server_transport_line(const char *line, int validate_only)
+{
+ smartlist_t *items = NULL;
+ int r;
+ const char *transports=NULL;
+ smartlist_t *transport_list=NULL;
+ char *type=NULL;
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ /* managed proxy options */
+ int is_managed=0;
+ char **proxy_argv=NULL;
+ char **tmp=NULL;
+ int proxy_argc,i;
+
+ int line_length;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ line_length = smartlist_len(items);
+ if (line_length < 3) {
+ log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line.");
+ goto err;
+ }
+
+ /* Get the first line element, split it to commas into
+ transport_list (in case it's multiple transports) and validate
+ the transport names. */
+ transports = smartlist_get(items, 0);
+ transport_list = smartlist_create();
+ smartlist_split_string(transport_list, transports, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
+ if (!string_is_C_identifier(transport_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ transport_name);
+ goto err;
+ }
+ } SMARTLIST_FOREACH_END(transport_name);
+
+ type = smartlist_get(items, 1);
+
+ if (!strcmp(type, "exec")) {
+ is_managed=1;
+ } else if (!strcmp(type, "proxy")) {
+ is_managed=0;
+ } else {
+ log_warn(LD_CONFIG, "Strange ServerTransportPlugin type '%s'", type);
+ goto err;
+ }
+
+ if (is_managed) { /* managed */
+ if (!validate_only) {
+ proxy_argc = line_length-2;
+ tor_assert(proxy_argc > 0);
+ proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
+ tmp = proxy_argv;
+
+ for (i=0;i<proxy_argc;i++) { /* store arguments */
+ *tmp++ = smartlist_get(items, 2);
+ smartlist_del_keeporder(items, 2);
+ }
+ *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+
+ /* kickstart the thing */
+ pt_kickstart_server_proxy(transport_list, proxy_argv);
+ }
+ } else { /* external */
+ if (smartlist_len(transport_list) != 1) {
+ log_warn(LD_CONFIG, "You can't have an external proxy with "
+ "more than one transports.");
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 2);
+
+ if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ if (!validate_only) {
+ log_info(LD_DIR, "Server transport '%s' at %s:%d.",
+ transports, fmt_addr(&addr), (int)port);
+ }
+ }
+
+ r = 0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ if (transport_list) {
+ SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
+ smartlist_free(transport_list);
+ }
+
+ return r;
+}
+
/** Read the contents of a DirServer line from <b>line</b>. If
* <b>validate_only</b> is 0, and the line is well-formed, and it
* shares any bits with <b>required_type</b> or <b>required_type</b>
@@ -4499,7 +5223,7 @@ parse_bridge_line(const char *line, int validate_only)
* bits it's missing) as a valid authority. Return 0 on success,
* or -1 if the line isn't well-formed or if we can't add it. */
static int
-parse_dir_server_line(const char *line, authority_type_t required_type,
+parse_dir_server_line(const char *line, dirinfo_type_t required_type,
int validate_only)
{
smartlist_t *items = NULL;
@@ -4508,7 +5232,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
uint16_t dir_port = 0, or_port = 0;
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
- authority_type_t type = V2_AUTHORITY;
+ dirinfo_type_t type = V2_DIRINFO;
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
items = smartlist_create();
@@ -4529,13 +5253,13 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
if (TOR_ISDIGIT(flag[0]))
break;
if (!strcasecmp(flag, "v1")) {
- type |= (V1_AUTHORITY | HIDSERV_AUTHORITY);
+ type |= (V1_DIRINFO | HIDSERV_DIRINFO);
} else if (!strcasecmp(flag, "hs")) {
- type |= HIDSERV_AUTHORITY;
+ type |= HIDSERV_DIRINFO;
} else if (!strcasecmp(flag, "no-hs")) {
is_not_hidserv_authority = 1;
} else if (!strcasecmp(flag, "bridge")) {
- type |= BRIDGE_AUTHORITY;
+ type |= BRIDGE_DIRINFO;
} else if (!strcasecmp(flag, "no-v2")) {
is_not_v2_authority = 1;
} else if (!strcasecmpstart(flag, "orport=")) {
@@ -4552,7 +5276,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
flag);
} else {
- type |= V3_AUTHORITY;
+ type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
}
} else {
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
@@ -4562,9 +5286,9 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
smartlist_del_keeporder(items, 0);
}
if (is_not_hidserv_authority)
- type &= ~HIDSERV_AUTHORITY;
+ type &= ~HIDSERV_DIRINFO;
if (is_not_v2_authority)
- type &= ~V2_AUTHORITY;
+ type &= ~V2_DIRINFO;
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
@@ -4572,7 +5296,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
}
addrport = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
- if (parse_addr_port(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
+ if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport);
goto err;
}
@@ -4592,7 +5316,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
* clause once Tor 0.1.2.17 is obsolete. */
log_warn(LD_CONFIG, "Dangerous dirserver line. To correct, erase your "
"torrc file (%s), or reinstall Tor and use the default torrc.",
- get_torrc_fname());
+ get_torrc_fname(0));
goto err;
}
if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
@@ -4627,6 +5351,374 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
return r;
}
+/** Free all storage held in <b>port</b> */
+static void
+port_cfg_free(port_cfg_t *port)
+{
+ tor_free(port);
+}
+
+/** Warn for every port in <b>ports</b> that is on a publicly routable
+ * address. */
+static void
+warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
+{
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (port->is_unix_addr) {
+ /* Unix sockets aren't accessible over a network. */
+ } else if (!tor_addr_is_internal(&port->addr, 1)) {
+ log_warn(LD_CONFIG, "You specified a public address for %sPort. "
+ "Other people on the Internet might find your computer and "
+ "use it as an open proxy. Please don't allow this unless you "
+ "have a good reason.", portname);
+ } else if (!tor_addr_is_loopback(&port->addr)) {
+ log_notice(LD_CONFIG, "You configured a non-loopback address for "
+ "%sPort. This allows everybody on your local network to use "
+ "your machine as a proxy. Make sure this is what you wanted.",
+ portname);
+ }
+ } SMARTLIST_FOREACH_END(port);
+}
+
+#define CL_PORT_NO_OPTIONS (1u<<0)
+#define CL_PORT_WARN_NONLOCAL (1u<<1)
+#define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2)
+
+/**
+ * Parse port configuration for a single client port type.
+ *
+ * Read entries of the "FooPort" type from the list <b>ports</b>, and
+ * entries of the "FooListenAddress" type from the list
+ * <b>listenaddrs</b>. Two syntaxes are supported: a legacy syntax
+ * where FooPort is at most a single entry containing a port number and
+ * where FooListenAddress has any number of address:port combinations;
+ * and a new syntax where there are no FooListenAddress entries and
+ * where FooPort can have any number of entries of the format
+ * "[Address:][Port] IsolationOptions".
+ *
+ * In log messages, describe the port type as <b>portname</b>.
+ *
+ * If no address is specified, default to <b>defaultaddr</b>. If no
+ * FooPort is given, default to defaultport (if 0, there is no default).
+ *
+ * If CL_PORT_NO_OPTIONS is set in <b>flags</b>, do not allow stream
+ * isolation options in the FooPort entries.
+ *
+ * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
+ * ports are not on a local address.
+ *
+ * Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
+ * if FooListenAddress is set but FooPort is 0.
+ *
+ * On success, if <b>out</b> is given, add a new port_cfg_t entry to
+ * <b>out</b> for every port that the client should listen on. Return 0
+ * on success, -1 on failure.
+ */
+static int
+parse_client_port_config(smartlist_t *out,
+ const config_line_t *ports,
+ const config_line_t *listenaddrs,
+ const char *portname,
+ int listener_type,
+ const char *defaultaddr,
+ int defaultport,
+ unsigned flags)
+{
+ smartlist_t *elts;
+ int retval = -1;
+ const unsigned allow_client_options = !(flags & CL_PORT_NO_OPTIONS);
+ const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
+ const unsigned allow_spurious_listenaddr =
+ flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
+
+ /* FooListenAddress is deprecated; let's make it work like it used to work,
+ * though. */
+ if (listenaddrs) {
+ int mainport = defaultport;
+
+ if (ports && ports->next) {
+ log_warn(LD_CONFIG, "%sListenAddress can't be used when there are "
+ "multiple %sPort lines", portname, portname);
+ return -1;
+ } else if (ports) {
+ if (!strcmp(ports->value, "auto")) {
+ mainport = CFG_AUTO_PORT;
+ } else {
+ int ok;
+ mainport = (int)tor_parse_long(ports->value, 10, 0, 65535, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_CONFIG, "%sListenAddress can only be used with a single "
+ "%sPort with value \"auto\" or 1-65535.",
+ portname, portname);
+ return -1;
+ }
+ }
+ }
+
+ if (mainport == 0) {
+ if (allow_spurious_listenaddr)
+ return 1;
+ log_warn(LD_CONFIG, "%sPort must be defined if %sListenAddress is used",
+ portname, portname);
+ return -1;
+ }
+
+ for (; listenaddrs; listenaddrs = listenaddrs->next) {
+ tor_addr_t addr;
+ uint16_t port = 0;
+ if (tor_addr_port_lookup(listenaddrs->value, &addr, &port) < 0) {
+ log_warn(LD_CONFIG, "Unable to parse %sListenAddress '%s'",
+ portname, listenaddrs->value);
+ return -1;
+ }
+ if (out) {
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = port ? port : mainport;
+ tor_addr_copy(&cfg->addr, &addr);
+ cfg->session_group = SESSION_GROUP_UNSET;
+ cfg->isolation_flags = ISO_DEFAULT;
+ smartlist_add(out, cfg);
+ }
+ }
+
+ if (warn_nonlocal && out)
+ warn_nonlocal_client_ports(out, portname);
+ return 0;
+ } /* end if (listenaddrs) */
+
+ /* No ListenAddress lines. If there's no FooPort, then maybe make a default
+ * one. */
+ if (! ports) {
+ if (defaultport && out) {
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = defaultport;
+ tor_addr_parse(&cfg->addr, defaultaddr);
+ cfg->session_group = SESSION_GROUP_UNSET;
+ cfg->isolation_flags = ISO_DEFAULT;
+ smartlist_add(out, cfg);
+ }
+ return 0;
+ }
+
+ /* At last we can actually parse the FooPort lines. The syntax is:
+ * [Addr:](Port|auto) [Options].*/
+ elts = smartlist_create();
+
+ for (; ports; ports = ports->next) {
+ tor_addr_t addr;
+ int port;
+ int sessiongroup = SESSION_GROUP_UNSET;
+ unsigned isolation = ISO_DEFAULT;
+
+ char *addrport;
+ uint16_t ptmp=0;
+ int ok;
+
+ smartlist_split_string(elts, ports->value, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(elts) == 0) {
+ log_warn(LD_CONFIG, "Invalid %sPort line with no value", portname);
+ goto err;
+ }
+
+ if (!allow_client_options && smartlist_len(elts) > 1) {
+ log_warn(LD_CONFIG, "Too many options on %sPort line", portname);
+ goto err;
+ }
+
+ /* Now parse the addr/port value */
+ addrport = smartlist_get(elts, 0);
+ if (!strcmp(addrport, "auto")) {
+ port = CFG_AUTO_PORT;
+ tor_addr_parse(&addr, defaultaddr);
+ } else if (!strcasecmpend(addrport, ":auto")) {
+ char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
+ port = CFG_AUTO_PORT;
+ if (tor_addr_port_lookup(addrtmp, &addr, &ptmp)<0 || ptmp) {
+ log_warn(LD_CONFIG, "Invalid address '%s' for %sPort",
+ escaped(addrport), portname);
+ tor_free(addrtmp);
+ goto err;
+ }
+ } else {
+ /* Try parsing integer port before address, because, who knows?
+ "9050" might be a valid address. */
+ port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
+ if (ok) {
+ tor_addr_parse(&addr, defaultaddr);
+ } else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) {
+ if (ptmp == 0) {
+ log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
+ goto err;
+ }
+ port = ptmp;
+ } else {
+ log_warn(LD_CONFIG, "Couldn't parse address '%s' for %sPort",
+ escaped(addrport), portname);
+ goto err;
+ }
+ }
+
+ /* Now parse the rest of the options, if any. */
+ SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
+ int no = 0, isoflag = 0;
+ const char *elt_orig = elt;
+ if (elt_sl_idx == 0)
+ continue; /* Skip addr:port */
+ if (!strcasecmpstart(elt, "SessionGroup=")) {
+ int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
+ 10, 0, INT_MAX, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
+ portname, escaped(elt));
+ goto err;
+ }
+ if (sessiongroup >= 0) {
+ log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
+ portname);
+ goto err;
+ }
+ sessiongroup = group;
+ continue;
+ }
+
+ if (!strcasecmpstart(elt, "No")) {
+ no = 1;
+ elt += 2;
+ }
+ if (!strcasecmpend(elt, "s"))
+ elt[strlen(elt)-1] = '\0'; /* kill plurals. */
+
+ if (!strcasecmp(elt, "IsolateDestPort")) {
+ isoflag = ISO_DESTPORT;
+ } else if (!strcasecmp(elt, "IsolateDestAddr")) {
+ isoflag = ISO_DESTADDR;
+ } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
+ isoflag = ISO_SOCKSAUTH;
+ } else if (!strcasecmp(elt, "IsolateClientProtocol")) {
+ isoflag = ISO_CLIENTPROTO;
+ } else if (!strcasecmp(elt, "IsolateClientAddr")) {
+ isoflag = ISO_CLIENTADDR;
+ } else {
+ log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
+ portname, escaped(elt_orig));
+ }
+
+ if (no) {
+ isolation &= ~isoflag;
+ } else {
+ isolation |= isoflag;
+ }
+ } SMARTLIST_FOREACH_END(elt);
+
+ if (out && port) {
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = port;
+ tor_addr_copy(&cfg->addr, &addr);
+ cfg->session_group = sessiongroup;
+ cfg->isolation_flags = isolation;
+ smartlist_add(out, cfg);
+ }
+ SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+ smartlist_clear(elts);
+ }
+
+ if (warn_nonlocal && out)
+ warn_nonlocal_client_ports(out, portname);
+
+ retval = 0;
+ err:
+ SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+ smartlist_free(elts);
+ return retval;
+}
+
+/** Parse all client port types (Socks, DNS, Trans, NATD) from
+ * <b>options</b>. On success, set *<b>n_ports_out</b> to the number of
+ * ports that are listed and return 0. On failure, set *<b>msg</b> to a
+ * description of the problem and return -1.
+ *
+ * If <b>validate_only</b> is false, set configured_client_ports to the
+ * new list of ports parsed from <b>options</b>.
+ **/
+static int
+parse_client_ports(const or_options_t *options, int validate_only,
+ char **msg, int *n_ports_out)
+{
+ smartlist_t *ports;
+ int retval = -1;
+
+ ports = smartlist_create();
+
+ *n_ports_out = 0;
+
+ if (parse_client_port_config(ports,
+ options->SocksPort, options->SocksListenAddress,
+ "Socks", CONN_TYPE_AP_LISTENER,
+ "127.0.0.1", 9050,
+ CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR) < 0) {
+ *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
+ goto err;
+ }
+ if (parse_client_port_config(ports,
+ options->DNSPort, options->DNSListenAddress,
+ "DNS", CONN_TYPE_AP_DNS_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration");
+ goto err;
+ }
+ if (parse_client_port_config(ports,
+ options->TransPort, options->TransListenAddress,
+ "Trans", CONN_TYPE_AP_TRANS_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid TransPort/TransListenAddress configuration");
+ goto err;
+ }
+ if (parse_client_port_config(ports,
+ options->NATDPort, options->NATDListenAddress,
+ "NATD", CONN_TYPE_AP_NATD_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration");
+ goto err;
+ }
+
+ *n_ports_out = smartlist_len(ports);
+
+ if (!validate_only) {
+ if (configured_client_ports) {
+ SMARTLIST_FOREACH(configured_client_ports,
+ port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(configured_client_ports);
+ }
+ configured_client_ports = ports;
+ ports = NULL; /* prevent free below. */
+ }
+
+ retval = 0;
+ err:
+ if (ports) {
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(ports);
+ }
+ return retval;
+}
+
+/** Return a list of port_cfg_t for client ports parsed from the
+ * options. */
+const smartlist_t *
+get_configured_client_ports(void)
+{
+ if (!configured_client_ports)
+ configured_client_ports = smartlist_create();
+ return configured_client_ports;
+}
+
/** Adjust the value of options->DataDirectory, or fill it in if it's
* absent. Return 0 on success, -1 on failure. */
static int
@@ -4698,7 +5790,7 @@ validate_data_directory(or_options_t *options)
* doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
* replace it. Return 0 on success, -1 on failure. */
static int
-write_configuration_file(const char *fname, or_options_t *options)
+write_configuration_file(const char *fname, const or_options_t *options)
{
char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
int rename_old = 0, r;
@@ -4783,7 +5875,7 @@ options_save_current(void)
* If we try falling back to datadirectory or something, we have a better
* chance of saving the configuration, but a better chance of doing
* something the user never expected. */
- return write_configuration_file(get_torrc_fname(), get_options());
+ return write_configuration_file(get_torrc_fname(0), get_options());
}
/** Mapping from a unit name to a multiplier for converting that unit into a
@@ -4839,6 +5931,26 @@ static struct unit_table_t time_units[] = {
{ NULL, 0 },
};
+/** Table to map the names of time units to the number of milliseconds
+ * they contain. */
+static struct unit_table_t time_msec_units[] = {
+ { "", 1 },
+ { "msec", 1 },
+ { "millisecond", 1 },
+ { "milliseconds", 1 },
+ { "second", 1000 },
+ { "seconds", 1000 },
+ { "minute", 60*1000 },
+ { "minutes", 60*1000 },
+ { "hour", 60*60*1000 },
+ { "hours", 60*60*1000 },
+ { "day", 24*60*60*1000 },
+ { "days", 24*60*60*1000 },
+ { "week", 7*24*60*60*1000 },
+ { "weeks", 7*24*60*60*1000 },
+ { NULL, 0 },
+};
+
/** Parse a string <b>val</b> containing a number, zero or more
* spaces, and an optional unit string. If the unit appears in the
* table <b>u</b>, then multiply the number by the unit multiplier.
@@ -4902,6 +6014,25 @@ config_parse_memunit(const char *s, int *ok)
return u;
}
+/** Parse a string in the format "number unit", where unit is a unit of
+ * time in milliseconds. On success, set *<b>ok</b> to true and return
+ * the number of milliseconds in the provided interval. Otherwise, set
+ * *<b>ok</b> to 0 and return -1. */
+static int
+config_parse_msec_interval(const char *s, int *ok)
+{
+ uint64_t r;
+ r = config_parse_units(s, time_msec_units, ok);
+ if (!ok)
+ return -1;
+ if (r > INT_MAX) {
+ log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
+ *ok = 0;
+ return -1;
+ }
+ return (int)r;
+}
+
/** Parse a string in the format "number unit", where unit is a unit of time.
* On success, set *<b>ok</b> to true and return the number of seconds in
* the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
@@ -4921,13 +6052,29 @@ config_parse_interval(const char *s, int *ok)
return (int)r;
}
+/** Return the number of cpus configured in <b>options</b>. If we are
+ * told to auto-detect the number of cpus, return the auto-detected number. */
+int
+get_num_cpus(const or_options_t *options)
+{
+ if (options->NumCPUs == 0) {
+ int n = compute_num_cpus();
+ return (n >= 1) ? n : 1;
+ } else {
+ return options->NumCPUs;
+ }
+}
+
/**
* Initialize the libevent library.
*/
static void
-init_libevent(void)
+init_libevent(const or_options_t *options)
{
const char *badness=NULL;
+ tor_libevent_cfg cfg;
+
+ tor_assert(options);
configure_libevent_logging();
/* If the kernel complains that some method (say, epoll) doesn't
@@ -4937,7 +6084,12 @@ init_libevent(void)
tor_check_libevent_header_compatibility();
- tor_libevent_initialize();
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.disable_iocp = options->DisableIOCP;
+ cfg.num_cpus = get_num_cpus(options);
+ cfg.msec_per_tick = options->TokenBucketRefillInterval;
+
+ tor_libevent_initialize(&cfg);
suppress_libevent_log_msg(NULL);
@@ -4976,7 +6128,7 @@ get_or_state(void)
* Note: Consider using the get_datadir_fname* macros in or.h.
*/
char *
-options_get_datadir_fname2_suffix(or_options_t *options,
+options_get_datadir_fname2_suffix(const or_options_t *options,
const char *sub1, const char *sub2,
const char *suffix)
{
@@ -5011,6 +6163,69 @@ options_get_datadir_fname2_suffix(or_options_t *options,
return fname;
}
+/** Return true if <b>line</b> is a valid state TransportProxy line.
+ * Return false otherwise. */
+static int
+state_transport_line_is_valid(const char *line)
+{
+ smartlist_t *items = NULL;
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+ int r;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) != 2) {
+ log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line.");
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 1);
+ if (tor_addr_port_lookup(addrport, &addr, &port) < 0) {
+ log_warn(LD_CONFIG, "state: Could not parse addrport.");
+ goto err;
+ }
+
+ if (!port) {
+ log_warn(LD_CONFIG, "state: Transport line did not contain port.");
+ goto err;
+ }
+
+ r = 1;
+ goto done;
+
+ err:
+ r = 0;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ return r;
+}
+
+/** Return 0 if all TransportProxy lines in <b>state</b> are well
+ * formed. Otherwise, return -1. */
+static int
+validate_transports_in_state(or_state_t *state)
+{
+ int broken = 0;
+ config_line_t *line;
+
+ for (line = state->TransportProxies ; line ; line = line->next) {
+ tor_assert(!strcmp(line->key, "TransportProxy"));
+ if (!state_transport_line_is_valid(line->value))
+ broken = 1;
+ }
+
+ if (broken)
+ log_warn(LD_CONFIG, "state: State file seems to be broken.");
+
+ return 0;
+}
+
/** Return 0 if every setting in <b>state</b> is reasonable, and a
* permissible transition from <b>old_state</b>. Else warn and return -1.
* Should have no side effects, except for normalizing the contents of
@@ -5029,6 +6244,9 @@ or_state_validate(or_state_t *old_state, or_state_t *state,
if (entry_guards_parse_state(state, 0, msg)<0)
return -1;
+ if (validate_transports_in_state(state)<0)
+ return -1;
+
return 0;
}
@@ -5123,7 +6341,7 @@ or_state_load(void)
if (contents) {
config_line_t *lines=NULL;
int assign_retval;
- if (config_get_lines(contents, &lines)<0)
+ if (config_get_lines(contents, &lines, 0)<0)
goto done;
assign_retval = config_assign(&state_format, new_state,
lines, 0, 0, &errmsg);
@@ -5227,7 +6445,7 @@ or_state_save(time_t now)
tor_free(global_state->TorVersion);
tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
- state = config_dump(&state_format, global_state, 1, 0);
+ state = config_dump(&state_format, NULL, global_state, 1, 0);
format_local_iso_time(tbuf, now);
tor_asprintf(&contents,
"# Tor state file last generated on %s local time\n"
@@ -5261,6 +6479,150 @@ or_state_save(time_t now)
return 0;
}
+/** Return the config line for transport <b>transport</b> in the current state.
+ * Return NULL if there is no config line for <b>transport</b>. */
+static config_line_t *
+get_transport_in_state_by_name(const char *transport)
+{
+ or_state_t *or_state = get_or_state();
+ config_line_t *line;
+ config_line_t *ret = NULL;
+ smartlist_t *items = NULL;
+
+ for (line = or_state->TransportProxies ; line ; line = line->next) {
+ tor_assert(!strcmp(line->key, "TransportProxy"));
+
+ items = smartlist_create();
+ smartlist_split_string(items, line->value, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+ if (smartlist_len(items) != 2) /* broken state */
+ goto done;
+
+ if (!strcmp(smartlist_get(items, 0), transport)) {
+ ret = line;
+ goto done;
+ }
+
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ items = NULL;
+ }
+
+ done:
+ if (items) {
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ }
+ return ret;
+}
+
+/** Return string containing the address:port part of the
+ * TransportProxy <b>line</b> for transport <b>transport</b>.
+ * If the line is corrupted, return NULL. */
+static const char *
+get_transport_bindaddr(const char *line, const char *transport)
+{
+ char *line_tmp = NULL;
+
+ if (strlen(line) < strlen(transport) + 2) {
+ goto broken_state;
+ } else {
+ /* line should start with the name of the transport and a space.
+ (for example, "obfs2 127.0.0.1:47245") */
+ tor_asprintf(&line_tmp, "%s ", transport);
+ if (strcmpstart(line, line_tmp))
+ goto broken_state;
+
+ tor_free(line_tmp);
+ return (line+strlen(transport)+1);
+ }
+
+ broken_state:
+ tor_free(line_tmp);
+ return NULL;
+}
+
+/** Return a static string containing the address:port a proxy
+ * transport should bind on. */
+const char *
+get_bindaddr_for_transport(const char *transport)
+{
+ static const char default_addrport[] = "127.0.0.1:0";
+ const char *bindaddr = NULL;
+
+ config_line_t *line = get_transport_in_state_by_name(transport);
+ if (!line)
+ return default_addrport;
+
+ bindaddr = get_transport_bindaddr(line->value, transport);
+
+ return bindaddr ? bindaddr : default_addrport;
+}
+
+/** Save <b>transport</b> listening on <b>addr</b>:<b>port</b> to
+ state */
+void
+save_transport_to_state(const char *transport,
+ const tor_addr_t *addr, uint16_t port)
+{
+ or_state_t *state = get_or_state();
+
+ char *transport_addrport=NULL;
+
+ /** find where to write on the state */
+ config_line_t **next, *line;
+
+ /* see if this transport is already stored in state */
+ config_line_t *transport_line =
+ get_transport_in_state_by_name(transport);
+
+ if (transport_line) { /* if transport already exists in state... */
+ const char *prev_bindaddr = /* get its addrport... */
+ get_transport_bindaddr(transport_line->value, transport);
+ tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port);
+
+ /* if transport in state has the same address as this one, life is good */
+ if (!strcmp(prev_bindaddr, transport_addrport)) {
+ log_info(LD_CONFIG, "Transport seems to have spawned on its usual "
+ "address:port.");
+ goto done;
+ } else { /* if addrport in state is different than the one we got */
+ log_info(LD_CONFIG, "Transport seems to have spawned on different "
+ "address:port. Let's update the state file with the new "
+ "address:port");
+ tor_free(transport_line->value); /* free the old line */
+ tor_asprintf(&transport_line->value, "%s %s:%d", transport,
+ fmt_addr(addr),
+ (int) port); /* replace old addrport line with new line */
+ }
+ } else { /* never seen this one before; save it in state for next time */
+ log_info(LD_CONFIG, "It's the first time we see this transport. "
+ "Let's save its address:port");
+ next = &state->TransportProxies;
+ /* find the last TransportProxy line in the state and point 'next'
+ right after it */
+ line = state->TransportProxies;
+ while (line) {
+ next = &(line->next);
+ line = line->next;
+ }
+
+ /* allocate space for the new line and fill it in */
+ *next = line = tor_malloc_zero(sizeof(config_line_t));
+ line->key = tor_strdup("TransportProxy");
+ tor_asprintf(&line->value, "%s %s:%d", transport,
+ fmt_addr(addr), (int) port);
+
+ next = &(line->next);
+ }
+
+ if (!get_options()->AvoidDiskWrites)
+ or_state_mark_dirty(state, 0);
+
+ done:
+ tor_free(transport_addrport);
+}
+
/** Given a file name check to see whether the file exists but has not been
* modified for a very long time. If so, remove it. */
void
@@ -5293,7 +6655,7 @@ getinfo_helper_config(control_connection_t *conn,
smartlist_t *sl = smartlist_create();
int i;
for (i = 0; _option_vars[i].name; ++i) {
- config_var_t *var = &_option_vars[i];
+ const config_var_t *var = &_option_vars[i];
const char *type;
char *line;
switch (var->type) {
@@ -5302,9 +6664,11 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_UINT: type = "Integer"; break;
case CONFIG_TYPE_PORT: type = "Port"; break;
case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
+ case CONFIG_TYPE_MSEC_INTERVAL: type = "TimeMsecInterval"; break;
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
+ case CONFIG_TYPE_AUTOBOOL: type = "Boolean+Auto"; break;
case CONFIG_TYPE_ISOTIME: type = "Time"; break;
case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
case CONFIG_TYPE_CSV: type = "CommaList"; break;
diff --git a/src/or/config.h b/src/or/config.h
index 78a67dddf5..e1fc5cfe9a 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -13,7 +13,8 @@
#define _TOR_CONFIG_H
const char *get_dirportfrontpage(void);
-or_options_t *get_options(void);
+const or_options_t *get_options(void);
+or_options_t *get_options_mutable(void);
int set_options(or_options_t *new_val, char **msg);
void config_free_all(void);
const char *safe_str_client(const char *address);
@@ -22,25 +23,25 @@ const char *escaped_safe_str_client(const char *address);
const char *escaped_safe_str(const char *address);
const char *get_version(void);
-int config_get_lines(const char *string, config_line_t **result);
+int config_get_lines(const char *string, config_line_t **result, int extended);
void config_free_lines(config_line_t *front);
setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
-int resolve_my_address(int warn_severity, or_options_t *options,
+int resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr, char **hostname_out);
-int is_local_addr(const tor_addr_t *addr) ATTR_PURE;
+int is_local_addr(const tor_addr_t *addr);
void options_init(or_options_t *options);
-char *options_dump(or_options_t *options, int minimal);
+char *options_dump(const or_options_t *options, int minimal);
int options_init_from_torrc(int argc, char **argv);
-setopt_err_t options_init_from_string(const char *cf,
+setopt_err_t options_init_from_string(const char *cf_defaults, const char *cf,
int command, const char *command_arg, char **msg);
int option_is_recognized(const char *key);
const char *option_get_canonical_name(const char *key);
-config_line_t *option_get_assignment(or_options_t *options,
+config_line_t *option_get_assignment(const or_options_t *options,
const char *key);
int options_save_current(void);
-const char *get_torrc_fname(void);
-char *options_get_datadir_fname2_suffix(or_options_t *options,
+const char *get_torrc_fname(int defaults_fname);
+char *options_get_datadir_fname2_suffix(const or_options_t *options,
const char *sub1, const char *sub2,
const char *suffix);
#define get_datadir_fname2_suffix(sub1, sub2, suffix) \
@@ -57,23 +58,35 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
#define get_datadir_fname_suffix(sub1, suffix) \
get_datadir_fname2_suffix((sub1), NULL, (suffix))
+int get_num_cpus(const or_options_t *options);
+
or_state_t *get_or_state(void);
int did_last_state_file_write_fail(void);
int or_state_save(time_t now);
-int options_need_geoip_info(or_options_t *options, const char **reason_out);
+const smartlist_t *get_configured_client_ports(void);
+
+int options_need_geoip_info(const or_options_t *options,
+ const char **reason_out);
+
+void save_transport_to_state(const char *transport_name,
+ const tor_addr_t *addr, uint16_t port);
+const char *get_bindaddr_for_transport(const char *transport);
+
int getinfo_helper_config(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
const char *tor_get_digests(void);
-uint32_t get_effective_bwrate(or_options_t *options);
-uint32_t get_effective_bwburst(or_options_t *options);
+uint32_t get_effective_bwrate(const or_options_t *options);
+uint32_t get_effective_bwburst(const or_options_t *options);
#ifdef CONFIG_PRIVATE
/* Used only by config.c and test.c */
or_options_t *options_new(void);
#endif
+void config_register_addressmaps(const or_options_t *options);
+
#endif
diff --git a/src/or/connection.c b/src/or/connection.c
index 2049f4240c..b87f922175 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -36,17 +36,28 @@
#include "router.h"
#include "routerparse.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/event.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
static connection_t *connection_create_listener(
const struct sockaddr *listensockaddr,
socklen_t listensocklen, int type,
- char* address);
+ const char *address,
+ const port_cfg_t *portcfg);
static void connection_init(time_t now, connection_t *conn, int type,
int socket_family);
static int connection_init_accepted_conn(connection_t *conn,
- uint8_t listener_type);
+ const listener_connection_t *listener);
static int connection_handle_listener_read(connection_t *conn, int new_type);
+#ifndef USE_BUFFEREVENTS
static int connection_bucket_should_increase(int bucket,
or_connection_t *conn);
+#endif
static int connection_finished_flushing(connection_t *conn);
static int connection_flushed_some(connection_t *conn);
static int connection_finished_connecting(connection_t *conn);
@@ -60,6 +71,8 @@ static void set_constrained_socket_buffers(tor_socket_t sock, int size);
static const char *connection_proxy_state_to_string(int state);
static int connection_read_https_proxy_response(connection_t *conn);
static void connection_send_socks5_connect(connection_t *conn);
+static const char *proxy_type_to_string(int proxy_type);
+static int get_proxy_type(void);
/** The last IPv4 address that our network interface seemed to have been
* binding to, in host order. We use this to detect when our IP changes. */
@@ -68,6 +81,15 @@ static uint32_t last_interface_ip = 0;
* Used to detect IP address changes. */
static smartlist_t *outgoing_addrs = NULL;
+#define CASE_ANY_LISTENER_TYPE \
+ case CONN_TYPE_OR_LISTENER: \
+ case CONN_TYPE_AP_LISTENER: \
+ case CONN_TYPE_DIR_LISTENER: \
+ case CONN_TYPE_CONTROL_LISTENER: \
+ case CONN_TYPE_AP_TRANS_LISTENER: \
+ case CONN_TYPE_AP_NATD_LISTENER: \
+ case CONN_TYPE_AP_DNS_LISTENER
+
/**************************************************************/
/**
@@ -108,13 +130,7 @@ conn_state_to_string(int type, int state)
{
static char buf[96];
switch (type) {
- case CONN_TYPE_OR_LISTENER:
- case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
- case CONN_TYPE_AP_NATD_LISTENER:
- case CONN_TYPE_AP_DNS_LISTENER:
- case CONN_TYPE_DIR_LISTENER:
- case CONN_TYPE_CONTROL_LISTENER:
+ CASE_ANY_LISTENER_TYPE:
if (state == LISTENER_STATE_READY)
return "ready";
break;
@@ -124,10 +140,13 @@ conn_state_to_string(int type, int state)
case OR_CONN_STATE_PROXY_HANDSHAKING: return "handshaking (proxy)";
case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)";
case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING:
- return "renegotiating (TLS)";
+ return "renegotiating (TLS, v2 handshake)";
case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
- return "waiting for renegotiation (TLS)";
- case OR_CONN_STATE_OR_HANDSHAKING: return "handshaking (Tor)";
+ return "waiting for renegotiation or V3 handshake";
+ case OR_CONN_STATE_OR_HANDSHAKING_V2:
+ return "handshaking (Tor, v2 handshake)";
+ case OR_CONN_STATE_OR_HANDSHAKING_V3:
+ return "handshaking (Tor, v3 handshake)";
case OR_CONN_STATE_OPEN: return "open";
}
break;
@@ -183,6 +202,26 @@ conn_state_to_string(int type, int state)
return buf;
}
+#ifdef USE_BUFFEREVENTS
+/** Return true iff the connection's type is one that can use a
+ bufferevent-based implementation. */
+int
+connection_type_uses_bufferevent(connection_t *conn)
+{
+ switch (conn->type) {
+ case CONN_TYPE_AP:
+ case CONN_TYPE_EXIT:
+ case CONN_TYPE_DIR:
+ case CONN_TYPE_CONTROL:
+ case CONN_TYPE_OR:
+ case CONN_TYPE_CPUWORKER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+#endif
+
/** Allocate and return a new dir_connection_t, initialized as by
* connection_init(). */
dir_connection_t *
@@ -211,16 +250,26 @@ or_connection_new(int socket_family)
return or_conn;
}
+/** Allocate and return a new entry_connection_t, initialized as by
+ * connection_init(). */
+entry_connection_t *
+entry_connection_new(int type, int socket_family)
+{
+ entry_connection_t *entry_conn = tor_malloc_zero(sizeof(entry_connection_t));
+ tor_assert(type == CONN_TYPE_AP);
+ connection_init(time(NULL), ENTRY_TO_CONN(entry_conn), type, socket_family);
+ entry_conn->socks_request = socks_request_new();
+ return entry_conn;
+}
+
/** Allocate and return a new edge_connection_t, initialized as by
* connection_init(). */
edge_connection_t *
edge_connection_new(int type, int socket_family)
{
edge_connection_t *edge_conn = tor_malloc_zero(sizeof(edge_connection_t));
- tor_assert(type == CONN_TYPE_EXIT || type == CONN_TYPE_AP);
+ tor_assert(type == CONN_TYPE_EXIT);
connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family);
- if (type == CONN_TYPE_AP)
- edge_conn->socks_request = tor_malloc_zero(sizeof(socks_request_t));
return edge_conn;
}
@@ -237,6 +286,17 @@ control_connection_new(int socket_family)
return control_conn;
}
+/** Allocate and return a new listener_connection_t, initialized as by
+ * connection_init(). */
+listener_connection_t *
+listener_connection_new(int type, int socket_family)
+{
+ listener_connection_t *listener_conn =
+ tor_malloc_zero(sizeof(listener_connection_t));
+ connection_init(time(NULL), TO_CONN(listener_conn), type, socket_family);
+ return listener_conn;
+}
+
/** Allocate, initialize, and return a new connection_t subtype of <b>type</b>
* to make or receive connections of address family <b>socket_family</b>. The
* type should be one of the CONN_TYPE_* constants. */
@@ -248,15 +308,20 @@ connection_new(int type, int socket_family)
return TO_CONN(or_connection_new(socket_family));
case CONN_TYPE_EXIT:
- case CONN_TYPE_AP:
return TO_CONN(edge_connection_new(type, socket_family));
+ case CONN_TYPE_AP:
+ return ENTRY_TO_CONN(entry_connection_new(type, socket_family));
+
case CONN_TYPE_DIR:
return TO_CONN(dir_connection_new(socket_family));
case CONN_TYPE_CONTROL:
return TO_CONN(control_connection_new(socket_family));
+ CASE_ANY_LISTENER_TYPE:
+ return TO_CONN(listener_connection_new(type, socket_family));
+
default: {
connection_t *conn = tor_malloc_zero(sizeof(connection_t));
connection_init(time(NULL), conn, type, socket_family);
@@ -288,15 +353,20 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
conn->magic = OR_CONNECTION_MAGIC;
break;
case CONN_TYPE_EXIT:
- case CONN_TYPE_AP:
conn->magic = EDGE_CONNECTION_MAGIC;
break;
+ case CONN_TYPE_AP:
+ conn->magic = ENTRY_CONNECTION_MAGIC;
+ break;
case CONN_TYPE_DIR:
conn->magic = DIR_CONNECTION_MAGIC;
break;
case CONN_TYPE_CONTROL:
conn->magic = CONTROL_CONNECTION_MAGIC;
break;
+ CASE_ANY_LISTENER_TYPE:
+ conn->magic = LISTENER_CONNECTION_MAGIC;
+ break;
default:
conn->magic = BASE_CONNECTION_MAGIC;
break;
@@ -308,10 +378,13 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
conn->type = type;
conn->socket_family = socket_family;
- if (!connection_is_listener(conn)) { /* listeners never use their buf */
+#ifndef USE_BUFFEREVENTS
+ if (!connection_is_listener(conn)) {
+ /* listeners never use their buf */
conn->inbuf = buf_new();
conn->outbuf = buf_new();
}
+#endif
conn->timestamp_created = now;
conn->timestamp_lastread = now;
@@ -350,6 +423,10 @@ _connection_free(connection_t *conn)
memlen = sizeof(or_connection_t);
break;
case CONN_TYPE_AP:
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
+ mem = TO_ENTRY_CONN(conn);
+ memlen = sizeof(entry_connection_t);
+ break;
case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
mem = TO_EDGE_CONN(conn);
@@ -365,6 +442,11 @@ _connection_free(connection_t *conn)
mem = TO_CONTROL_CONN(conn);
memlen = sizeof(control_connection_t);
break;
+ CASE_ANY_LISTENER_TYPE:
+ tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC);
+ mem = TO_LISTENER_CONN(conn);
+ memlen = sizeof(listener_connection_t);
+ break;
default:
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
mem = conn;
@@ -377,7 +459,8 @@ _connection_free(connection_t *conn)
"bytes on inbuf, %d on outbuf.",
conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
- (int)buf_datalen(conn->inbuf), (int)buf_datalen(conn->outbuf));
+ (int)connection_get_inbuf_len(conn),
+ (int)connection_get_outbuf_len(conn));
}
if (!connection_is_listener(conn)) {
@@ -407,15 +490,21 @@ _connection_free(connection_t *conn)
smartlist_free(or_conn->active_circuit_pqueue);
tor_free(or_conn->nickname);
}
- if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
- tor_free(edge_conn->chosen_exit_name);
- if (edge_conn->socks_request) {
- memset(edge_conn->socks_request, 0xcc, sizeof(socks_request_t));
- tor_free(edge_conn->socks_request);
+ if (conn->type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
+ tor_free(entry_conn->chosen_exit_name);
+ tor_free(entry_conn->original_dest_address);
+ if (entry_conn->socks_request)
+ socks_request_free(entry_conn->socks_request);
+ if (entry_conn->pending_optimistic_data) {
+ generic_buffer_free(entry_conn->pending_optimistic_data);
+ }
+ if (entry_conn->sending_optimistic_data) {
+ generic_buffer_free(entry_conn->sending_optimistic_data);
}
-
- rend_data_free(edge_conn->rend_data);
+ }
+ if (CONN_IS_EDGE(conn)) {
+ rend_data_free(TO_EDGE_CONN(conn)->rend_data);
}
if (conn->type == CONN_TYPE_CONTROL) {
control_connection_t *control_conn = TO_CONTROL_CONN(conn);
@@ -424,6 +513,15 @@ _connection_free(connection_t *conn)
tor_free(conn->read_event); /* Probably already freed by connection_free. */
tor_free(conn->write_event); /* Probably already freed by connection_free. */
+ IF_HAS_BUFFEREVENT(conn, {
+ /* This was a workaround to handle bugs in some old versions of libevent
+ * where callbacks can occur after calling bufferevent_free(). Setting
+ * the callbacks to NULL prevented this. It shouldn't be necessary any
+ * more, but let's not tempt fate for now. */
+ bufferevent_setcb(conn->bufev, NULL, NULL, NULL, NULL);
+ bufferevent_free(conn->bufev);
+ conn->bufev = NULL;
+ });
if (conn->type == CONN_TYPE_DIR) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
@@ -450,6 +548,12 @@ _connection_free(connection_t *conn)
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
}
+#ifdef USE_BUFFEREVENTS
+ if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
+ ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg);
+ TO_OR_CONN(conn)->bucket_cfg = NULL;
+ }
+#endif
memset(mem, 0xCC, memlen); /* poison memory */
tor_free(mem);
@@ -485,39 +589,9 @@ connection_free(connection_t *conn)
_connection_free(conn);
}
-/** Call _connection_free() on every connection in our array, and release all
- * storage held by connection.c. This is used by cpuworkers and dnsworkers
- * when they fork, so they don't keep resources held open (especially
- * sockets).
- *
- * Don't do the checks in connection_free(), because they will
- * fail.
- */
-void
-connection_free_all(void)
-{
- smartlist_t *conns = get_connection_array();
-
- /* We don't want to log any messages to controllers. */
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- if (conn->type == CONN_TYPE_CONTROL)
- TO_CONTROL_CONN(conn)->event_mask = 0);
-
- control_update_global_event_mask();
-
- /* Unlink everything from the identity map. */
- connection_or_clear_identity_map();
-
- SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn));
-
- if (outgoing_addrs) {
- SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr));
- smartlist_free(outgoing_addrs);
- outgoing_addrs = NULL;
- }
-}
-
-/** Do any cleanup needed:
+/**
+ * Called when we're about to finally unlink and free a connection:
+ * perform necessary accounting and cleanup
* - Directory conns that failed to fetch a rendezvous descriptor
* need to inform pending rendezvous streams.
* - OR conns need to call rep_hist_note_*() to record status.
@@ -530,114 +604,20 @@ connection_free_all(void)
void
connection_about_to_close_connection(connection_t *conn)
{
- circuit_t *circ;
- dir_connection_t *dir_conn;
- or_connection_t *or_conn;
- edge_connection_t *edge_conn;
- time_t now = time(NULL);
-
tor_assert(conn->marked_for_close);
- if (CONN_IS_EDGE(conn)) {
- edge_conn = TO_EDGE_CONN(conn);
- if (!edge_conn->edge_has_sent_end) {
- log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
- "hasn't sent end yet?",
- conn->marked_for_close_file, conn->marked_for_close);
- tor_fragile_assert();
- }
- }
-
switch (conn->type) {
case CONN_TYPE_DIR:
- dir_conn = TO_DIR_CONN(conn);
- if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
- /* It's a directory connection and connecting or fetching
- * failed: forget about this router, and maybe try again. */
- connection_dir_request_failed(dir_conn);
- }
- /* If we were trying to fetch a v2 rend desc and did not succeed,
- * retry as needed. (If a fetch is successful, the connection state
- * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
- * refetching is unnecessary.) */
- if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
- dir_conn->rend_data &&
- strlen(dir_conn->rend_data->onion_address) ==
- REND_SERVICE_ID_LEN_BASE32)
- rend_client_refetch_v2_renddesc(dir_conn->rend_data);
+ connection_dir_about_to_close(TO_DIR_CONN(conn));
break;
case CONN_TYPE_OR:
- or_conn = TO_OR_CONN(conn);
- /* Remember why we're closing this connection. */
- if (conn->state != OR_CONN_STATE_OPEN) {
- /* Inform any pending (not attached) circs that they should
- * give up. */
- circuit_n_conn_done(TO_OR_CONN(conn), 0);
- /* now mark things down as needed */
- if (connection_or_nonopen_was_started_here(or_conn)) {
- or_options_t *options = get_options();
- rep_hist_note_connect_failed(or_conn->identity_digest, now);
- entry_guard_register_connect_status(or_conn->identity_digest,0,
- !options->HTTPSProxy, now);
- if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
- int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
- reason);
- if (!authdir_mode_tests_reachability(options))
- control_event_bootstrap_problem(
- orconn_end_reason_to_control_string(reason), reason);
- }
- }
- } else if (conn->hold_open_until_flushed) {
- /* We only set hold_open_until_flushed when we're intentionally
- * closing a connection. */
- rep_hist_note_disconnect(or_conn->identity_digest, now);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
- tls_error_to_orconn_end_reason(or_conn->tls_error));
- } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
- rep_hist_note_connection_died(or_conn->identity_digest, now);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
- tls_error_to_orconn_end_reason(or_conn->tls_error));
- }
- /* Now close all the attached circuits on it. */
- circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
- END_CIRC_REASON_OR_CONN_CLOSED);
+ connection_or_about_to_close(TO_OR_CONN(conn));
break;
case CONN_TYPE_AP:
- edge_conn = TO_EDGE_CONN(conn);
- if (edge_conn->socks_request->has_finished == 0) {
- /* since conn gets removed right after this function finishes,
- * there's no point trying to send back a reply at this point. */
- log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
- " back a socks reply.",
- conn->marked_for_close_file, conn->marked_for_close);
- }
- if (!edge_conn->end_reason) {
- log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
- " set end_reason.",
- conn->marked_for_close_file, conn->marked_for_close);
- }
- if (edge_conn->dns_server_request) {
- log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
- " replied to DNS request.",
- conn->marked_for_close_file, conn->marked_for_close);
- dnsserv_reject_request(edge_conn);
- }
- control_event_stream_bandwidth(edge_conn);
- control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED,
- edge_conn->end_reason);
- circ = circuit_get_by_edge_conn(edge_conn);
- if (circ)
- circuit_detach_stream(circ, edge_conn);
+ connection_ap_about_to_close(TO_ENTRY_CONN(conn));
break;
case CONN_TYPE_EXIT:
- edge_conn = TO_EDGE_CONN(conn);
- circ = circuit_get_by_edge_conn(edge_conn);
- if (circ)
- circuit_detach_stream(circ, edge_conn);
- if (conn->state == EXIT_CONN_STATE_RESOLVING) {
- connection_dns_remove(edge_conn);
- }
+ connection_exit_about_to_close(TO_EDGE_CONN(conn));
break;
}
}
@@ -674,10 +654,9 @@ connection_close_immediate(connection_t *conn)
conn->s = -1;
if (conn->linked)
conn->linked_conn_is_closed = 1;
- if (!connection_is_listener(conn)) {
+ if (conn->outbuf)
buf_clear(conn->outbuf);
- conn->outbuf_flushlen = 0;
- }
+ conn->outbuf_flushlen = 0;
}
/** Mark <b>conn</b> to be closed next time we loop through
@@ -747,48 +726,6 @@ connection_expire_held_open(void)
});
}
-/** Create an AF_INET listenaddr struct.
- * <b>listenaddress</b> provides the host and optionally the port information
- * for the new structure. If no port is provided in <b>listenaddress</b> then
- * <b>listenport</b> is used.
- *
- * If not NULL <b>readable_address</b> will contain a copy of the host part of
- * <b>listenaddress</b>.
- *
- * The listenaddr struct has to be freed by the caller.
- */
-static struct sockaddr_in *
-create_inet_sockaddr(const char *listenaddress, int listenport,
- char **readable_address, socklen_t *socklen_out) {
- struct sockaddr_in *listenaddr = NULL;
- uint32_t addr;
- uint16_t usePort = 0;
-
- if (parse_addr_port(LOG_WARN,
- listenaddress, readable_address, &addr, &usePort)<0) {
- log_warn(LD_CONFIG,
- "Error parsing/resolving ListenAddress %s", listenaddress);
- goto err;
- }
- if (usePort==0) {
- if (listenport != CFG_AUTO_PORT)
- usePort = listenport;
- }
-
- listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in));
- listenaddr->sin_addr.s_addr = htonl(addr);
- listenaddr->sin_family = AF_INET;
- listenaddr->sin_port = htons((uint16_t) usePort);
-
- *socklen_out = sizeof(struct sockaddr_in);
-
- return listenaddr;
-
- err:
- tor_free(listenaddr);
- return NULL;
-}
-
#ifdef HAVE_SYS_UN_H
/** Create an AF_UNIX listenaddr struct.
* <b>listenaddress</b> provides the path to the Unix socket.
@@ -862,7 +799,7 @@ warn_too_many_conns(void)
/** Check whether we should be willing to open an AF_UNIX socket in
* <b>path</b>. Return 0 if we should go ahead and -1 if we shouldn't. */
static int
-check_location_for_unix_socket(or_options_t *options, const char *path)
+check_location_for_unix_socket(const or_options_t *options, const char *path)
{
int r = -1;
char *p = tor_strdup(path);
@@ -923,12 +860,20 @@ make_socket_reuseable(tor_socket_t sock)
static connection_t *
connection_create_listener(const struct sockaddr *listensockaddr,
socklen_t socklen,
- int type, char* address)
+ int type, const char *address,
+ const port_cfg_t *port_cfg)
{
+ listener_connection_t *lis_conn;
connection_t *conn;
tor_socket_t s; /* the socket we're going to make */
+ or_options_t const *options = get_options();
+#if defined(HAVE_PWD_H) && defined(HAVE_SYS_UN_H)
+ struct passwd *pw = NULL;
+#endif
uint16_t usePort = 0, gotPort = 0;
int start_reading = 0;
+ static int global_next_session_group = SESSION_GROUP_FIRST_AUTO;
+ tor_addr_t addr;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
warn_too_many_conns();
@@ -936,7 +881,6 @@ connection_create_listener(const struct sockaddr *listensockaddr,
}
if (listensockaddr->sa_family == AF_INET) {
- tor_addr_t addr;
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
if (is_tcp)
start_reading = 1;
@@ -950,7 +894,8 @@ connection_create_listener(const struct sockaddr *listensockaddr,
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
if (!SOCKET_OK(s)) {
- log_warn(LD_NET,"Socket creation failed.");
+ log_warn(LD_NET,"Socket creation failed: %s",
+ tor_socket_strerror(tor_socket_errno(-1)));
goto err;
}
@@ -998,12 +943,14 @@ connection_create_listener(const struct sockaddr *listensockaddr,
* and listeners at the same time */
tor_assert(type == CONN_TYPE_CONTROL_LISTENER);
- if (check_location_for_unix_socket(get_options(), address) < 0)
+ if (check_location_for_unix_socket(options, address) < 0)
goto err;
log_notice(LD_NET, "Opening %s on %s",
conn_type_to_string(type), address);
+ tor_addr_make_unspec(&addr);
+
if (unlink(address) < 0 && errno != ENOENT) {
log_warn(LD_NET, "Could not unlink %s: %s", address,
strerror(errno));
@@ -1020,7 +967,20 @@ connection_create_listener(const struct sockaddr *listensockaddr,
tor_socket_strerror(tor_socket_errno(s)));
goto err;
}
- if (get_options()->ControlSocketsGroupWritable) {
+#ifdef HAVE_PWD_H
+ if (options->User) {
+ pw = getpwnam(options->User);
+ if (pw == NULL) {
+ log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.",
+ address, options->User);
+ } else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) {
+ log_warn(LD_NET,"Unable to chown() %s socket: %s.",
+ address, strerror(errno));
+ goto err;
+ }
+ }
+#endif
+ if (options->ControlSocketsGroupWritable) {
/* We need to use chmod; fchmod doesn't work on sockets on all
* platforms. */
if (chmod(address, 0660) < 0) {
@@ -1036,6 +996,8 @@ connection_create_listener(const struct sockaddr *listensockaddr,
tor_close_socket(s);
goto err;
}
+#else
+ (void)options;
#endif /* HAVE_SYS_UN_H */
} else {
log_err(LD_BUG,"Got unexpected address family %d.",
@@ -1045,11 +1007,23 @@ connection_create_listener(const struct sockaddr *listensockaddr,
set_socket_nonblocking(s);
- conn = connection_new(type, listensockaddr->sa_family);
+ lis_conn = listener_connection_new(type, listensockaddr->sa_family);
+ conn = TO_CONN(lis_conn);
conn->socket_family = listensockaddr->sa_family;
conn->s = s;
conn->address = tor_strdup(address);
conn->port = gotPort;
+ tor_addr_copy(&conn->addr, &addr);
+
+ if (port_cfg->isolation_flags) {
+ lis_conn->isolation_flags = port_cfg->isolation_flags;
+ if (port_cfg->session_group >= 0) {
+ lis_conn->session_group = port_cfg->session_group;
+ } else {
+ /* XXXX023 This can wrap after ~INT_MAX ports are opened. */
+ lis_conn->session_group = global_next_session_group--;
+ }
+ }
if (connection_add(conn) < 0) { /* no space, forget it */
log_warn(LD_NET,"connection_add for listener failed. Giving up.");
@@ -1146,7 +1120,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
struct sockaddr *remote = (struct sockaddr*)addrbuf;
/* length of the remote address. Must be whatever accept() needs. */
socklen_t remotelen = (socklen_t)sizeof(addrbuf);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
memset(addrbuf, 0, sizeof(addrbuf));
@@ -1260,7 +1234,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
return 0; /* no need to tear down the parent */
}
- if (connection_init_accepted_conn(newconn, conn->type) < 0) {
+ if (connection_init_accepted_conn(newconn, TO_LISTENER_CONN(conn)) < 0) {
if (! newconn->marked_for_close)
connection_mark_for_close(newconn);
return 0;
@@ -1274,7 +1248,8 @@ connection_handle_listener_read(connection_t *conn, int new_type)
* and place it in circuit_wait.
*/
static int
-connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
+connection_init_accepted_conn(connection_t *conn,
+ const listener_connection_t *listener)
{
connection_start_reading(conn);
@@ -1283,16 +1258,20 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0);
return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
case CONN_TYPE_AP:
- switch (listener_type) {
+ TO_ENTRY_CONN(conn)->isolation_flags = listener->isolation_flags;
+ TO_ENTRY_CONN(conn)->session_group = listener->session_group;
+ TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch();
+ TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->_base.type;
+ switch (TO_CONN(listener)->type) {
case CONN_TYPE_AP_LISTENER:
conn->state = AP_CONN_STATE_SOCKS_WAIT;
break;
case CONN_TYPE_AP_TRANS_LISTENER:
- TO_EDGE_CONN(conn)->is_transparent_ap = 1;
+ TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- return connection_ap_process_transparent(TO_EDGE_CONN(conn));
+ return connection_ap_process_transparent(TO_ENTRY_CONN(conn));
case CONN_TYPE_AP_NATD_LISTENER:
- TO_EDGE_CONN(conn)->is_transparent_ap = 1;
+ TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_NATD_WAIT;
break;
}
@@ -1325,8 +1304,8 @@ connection_connect(connection_t *conn, const char *address,
int inprogress = 0;
char addrbuf[256];
struct sockaddr *dest_addr;
- socklen_t dest_addr_len;
- or_options_t *options = get_options();
+ int dest_addr_len;
+ const or_options_t *options = get_options();
int protocol_family;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
@@ -1339,6 +1318,24 @@ connection_connect(connection_t *conn, const char *address,
else
protocol_family = PF_INET;
+ if (get_options()->DisableNetwork) {
+ /* We should never even try to connect anyplace if DisableNetwork is set.
+ * Warn if we do, and refuse to make the connection. */
+ static ratelim_t disablenet_violated = RATELIM_INIT(30*60);
+ char *m;
+#ifdef MS_WINDOWS
+ *socket_error = WSAENETUNREACH;
+#else
+ *socket_error = ENETUNREACH;
+#endif
+ if ((m = rate_limit_log(&disablenet_violated, approx_time()))) {
+ log_warn(LD_BUG, "Tried to open a socket with DisableNetwork set.%s", m);
+ tor_free(m);
+ }
+ tor_fragile_assert();
+ return -1;
+ }
+
s = tor_open_socket(protocol_family,SOCK_STREAM,IPPROTO_TCP);
if (s < 0) {
*socket_error = tor_socket_errno(-1);
@@ -1383,7 +1380,7 @@ connection_connect(connection_t *conn, const char *address,
make_socket_reuseable(s);
- if (connect(s, dest_addr, dest_addr_len) < 0) {
+ if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
/* yuck. kill it. */
@@ -1408,7 +1405,7 @@ connection_connect(connection_t *conn, const char *address,
escaped_safe_str_client(address),
port, inprogress?"in progress":"established", s);
conn->s = s;
- if (connection_add(conn) < 0) /* no space, forget it */
+ if (connection_add_connecting(conn) < 0) /* no space, forget it */
return -1;
return inprogress ? 0 : 1;
}
@@ -1421,6 +1418,7 @@ connection_proxy_state_to_string(int state)
static const char *unknown = "???";
static const char *states[] = {
"PROXY_NONE",
+ "PROXY_INFANT",
"PROXY_HTTPS_WANT_CONNECT_OK",
"PROXY_SOCKS4_WANT_CONNECT_OK",
"PROXY_SOCKS5_WANT_AUTH_METHOD_NONE",
@@ -1449,7 +1447,7 @@ connection_proxy_state_to_string(int state)
int
connection_proxy_connect(connection_t *conn, int type)
{
- or_options_t *options;
+ const or_options_t *options;
tor_assert(conn);
@@ -1641,6 +1639,19 @@ connection_send_socks5_connect(connection_t *conn)
conn->proxy_state = PROXY_SOCKS5_WANT_CONNECT_OK;
}
+/** DOCDOC */
+static int
+connection_fetch_from_buf_socks_client(connection_t *conn,
+ int state, char **reason)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_from_evbuffer_socks_client(input, state, reason);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_socks_client(conn->inbuf, state, reason);
+ }
+}
+
/** Call this from connection_*_process_inbuf() to advance the proxy
* handshake.
*
@@ -1668,17 +1679,17 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS4_WANT_CONNECT_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
if (ret == 1)
conn->proxy_state = PROXY_CONNECTED;
break;
case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* no auth needed, do connect */
if (ret == 1) {
connection_send_socks5_connect(conn);
@@ -1687,9 +1698,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* send auth if needed, otherwise do connect */
if (ret == 1) {
@@ -1724,9 +1735,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* send the connect request */
if (ret == 1) {
connection_send_socks5_connect(conn);
@@ -1735,9 +1746,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_CONNECT_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
if (ret == 1)
conn->proxy_state = PROXY_CONNECTED;
break;
@@ -1770,6 +1781,113 @@ connection_read_proxy_handshake(connection_t *conn)
return ret;
}
+/** Given a list of listener connections in <b>old_conns</b>, and list of
+ * port_cfg_t entries in <b>ports</b>, open a new listener for every port in
+ * <b>ports</b> that does not already have a listener in <b>old_conns</b>.
+ *
+ * Remove from <b>old_conns</b> every connection that has a corresponding
+ * entry in <b>ports</b>. Add to <b>new_conns</b> new every connection we
+ * launch.
+ *
+ * Return 0 on success, -1 on failure.
+ **/
+static int
+retry_listener_ports(smartlist_t *old_conns,
+ const smartlist_t *ports,
+ smartlist_t *new_conns)
+{
+ smartlist_t *launch = smartlist_create();
+ int r = 0;
+
+ smartlist_add_all(launch, ports);
+
+ /* Iterate through old_conns, comparing it to launch: remove from both lists
+ * each pair of elements that corresponds to the same port. */
+ SMARTLIST_FOREACH_BEGIN(old_conns, connection_t *, conn) {
+ const port_cfg_t *found_port = NULL;
+
+ /* Okay, so this is a listener. Is it configured? */
+ SMARTLIST_FOREACH_BEGIN(launch, const port_cfg_t *, wanted) {
+ if (conn->type != wanted->type)
+ continue;
+ if ((conn->socket_family != AF_UNIX && wanted->is_unix_addr) ||
+ (conn->socket_family == AF_UNIX && ! wanted->is_unix_addr))
+ continue;
+
+ if (wanted->is_unix_addr) {
+ if (conn->socket_family == AF_UNIX &&
+ !strcmp(wanted->unix_addr, conn->address)) {
+ found_port = wanted;
+ break;
+ }
+ } else {
+ int port_matches;
+ if (wanted->port == CFG_AUTO_PORT) {
+ port_matches = 1;
+ } else {
+ port_matches = (wanted->port == conn->port);
+ }
+ if (port_matches && tor_addr_eq(&wanted->addr, &conn->addr)) {
+ found_port = wanted;
+ break;
+ }
+ }
+ } SMARTLIST_FOREACH_END(wanted);
+
+ if (found_port) {
+ /* This listener is already running; we don't need to launch it. */
+ //log_debug(LD_NET, "Already have %s on %s:%d",
+ // conn_type_to_string(found_port->type), conn->address, conn->port);
+ smartlist_remove(launch, found_port);
+ /* And we can remove the connection from old_conns too. */
+ SMARTLIST_DEL_CURRENT(old_conns, conn);
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ /* Now open all the listeners that are configured but not opened. */
+ SMARTLIST_FOREACH_BEGIN(launch, const port_cfg_t *, port) {
+ struct sockaddr *listensockaddr;
+ socklen_t listensocklen = 0;
+ char *address=NULL;
+ connection_t *conn;
+ int real_port = port->port == CFG_AUTO_PORT ? 0 : port->port;
+ tor_assert(real_port <= UINT16_MAX);
+
+ if (port->is_unix_addr) {
+ listensockaddr = (struct sockaddr *)
+ create_unix_sockaddr(port->unix_addr,
+ &address, &listensocklen);
+ } else {
+ listensockaddr = tor_malloc(sizeof(struct sockaddr_storage));
+ listensocklen = tor_addr_to_sockaddr(&port->addr,
+ real_port,
+ listensockaddr,
+ sizeof(struct sockaddr_storage));
+ address = tor_dup_addr(&port->addr);
+ }
+
+ if (listensockaddr) {
+ conn = connection_create_listener(listensockaddr, listensocklen,
+ port->type, address, port);
+ tor_free(listensockaddr);
+ tor_free(address);
+ } else {
+ conn = NULL;
+ }
+
+ if (!conn) {
+ r = -1;
+ } else {
+ if (new_conns)
+ smartlist_add(new_conns, conn);
+ }
+ } SMARTLIST_FOREACH_END(port);
+
+ smartlist_free(launch);
+
+ return r;
+}
+
/**
* Launch any configured listener connections of type <b>type</b>. (A
* listener is configured if <b>port_option</b> is non-zero. If any
@@ -1777,168 +1895,73 @@ connection_read_proxy_handshake(connection_t *conn)
* connection binding to each one. Otherwise, create a single
* connection binding to the address <b>default_addr</b>.)
*
- * Only launch the listeners of this type that are not already open, and
- * only close listeners that are no longer wanted. Existing listeners
- * that are still configured are not touched.
- *
- * If <b>disable_all_conns</b> is set, then never open new conns, and
- * close the existing ones.
+ * We assume that we're starting with a list of existing listener connection_t
+ * pointers in <b>old_conns</b>: we do not launch listeners that are already
+ * in that list. Instead, we just remove them from the list.
*
- * Add all old conns that should be closed to <b>replaced_conns</b>.
- * Add all new connections to <b>new_conns</b>.
+ * All new connections we launch are added to <b>new_conns</b>.
*/
static int
-retry_listeners(int type, config_line_t *cfg,
+retry_listeners(smartlist_t *old_conns,
+ int type, const config_line_t *cfg,
int port_option, const char *default_addr,
- smartlist_t *replaced_conns,
smartlist_t *new_conns,
- int disable_all_conns,
- int socket_family)
+ int is_sockaddr_un)
{
- smartlist_t *launch = smartlist_create(), *conns;
- int free_launch_elts = 1;
- int r;
- config_line_t *c;
- connection_t *conn;
- config_line_t *line;
-
- tor_assert(socket_family == AF_INET || socket_family == AF_UNIX);
+ smartlist_t *ports = smartlist_create();
+ tor_addr_t dflt_addr;
+ int retval = 0;
- if (cfg && port_option) {
- for (c = cfg; c; c = c->next) {
- smartlist_add(launch, c);
- }
- free_launch_elts = 0;
- } else if (port_option) {
- line = tor_malloc_zero(sizeof(config_line_t));
- line->key = tor_strdup("");
- line->value = tor_strdup(default_addr);
- smartlist_add(launch, line);
+ if (default_addr) {
+ tor_addr_parse(&dflt_addr, default_addr);
+ } else {
+ tor_addr_make_unspec(&dflt_addr);
}
- /*
- SMARTLIST_FOREACH(launch, config_line_t *, l,
- log_fn(LOG_NOTICE, "#%s#%s", l->key, l->value));
- */
-
- conns = get_connection_array();
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
- if (conn->type != type ||
- conn->socket_family != socket_family ||
- conn->marked_for_close)
- continue;
- /* Okay, so this is a listener. Is it configured? */
- line = NULL;
- SMARTLIST_FOREACH(launch, config_line_t *, wanted,
- {
- char *address=NULL;
- uint16_t port;
- switch (socket_family) {
- case AF_INET:
- if (!parse_addr_port(LOG_WARN,
- wanted->value, &address, NULL, &port)) {
- int addr_matches = !strcasecmp(address, conn->address);
- int port_matches;
- tor_free(address);
- if (port) {
- /* The Listener line has a port */
- port_matches = (port == conn->port);
- } else if (port_option == CFG_AUTO_PORT) {
- /* The Listener line has no port, and the Port line is "auto".
- * "auto" matches anything; transitions from any port to
- * "auto" succeed. */
- port_matches = 1;
- } else {
- /* The Listener line has no port, and the Port line is "auto".
- * "auto" matches anything; transitions from any port to
- * "auto" succeed. */
- port_matches = (port_option == conn->port);
- }
- if (port_matches && addr_matches) {
- line = wanted;
- break;
- }
- }
- break;
- case AF_UNIX:
- if (!strcasecmp(wanted->value, conn->address)) {
- line = wanted;
- break;
- }
- break;
- default:
- tor_assert(0);
- }
- });
- if (!line || disable_all_conns) {
- /* This one isn't configured. Close it. */
- log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d",
- conn_type_to_string(type), conn->address, conn->port);
- if (replaced_conns) {
- smartlist_add(replaced_conns, conn);
- } else {
- connection_close_immediate(conn);
- connection_mark_for_close(conn);
- }
+ if (port_option) {
+ if (!cfg) {
+ port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t));
+ tor_addr_copy(&port->addr, &dflt_addr);
+ port->port = port_option;
+ port->type = type;
+ smartlist_add(ports, port);
} else {
- /* It's configured; we don't need to launch it. */
-// log_debug(LD_NET, "Already have %s on %s:%d",
-// conn_type_to_string(type), conn->address, conn->port);
- smartlist_remove(launch, line);
- if (free_launch_elts)
- config_free_lines(line);
- }
- });
-
- /* Now open all the listeners that are configured but not opened. */
- r = 0;
- if (!disable_all_conns) {
- SMARTLIST_FOREACH_BEGIN(launch, config_line_t *, cfg_line) {
- char *address = NULL;
- struct sockaddr *listensockaddr;
- socklen_t listensocklen = 0;
-
- switch (socket_family) {
- case AF_INET:
- listensockaddr = (struct sockaddr *)
- create_inet_sockaddr(cfg_line->value,
- port_option,
- &address, &listensocklen);
- break;
- case AF_UNIX:
- listensockaddr = (struct sockaddr *)
- create_unix_sockaddr(cfg_line->value,
- &address, &listensocklen);
- break;
- default:
- tor_assert(0);
- }
-
- if (listensockaddr) {
- conn = connection_create_listener(listensockaddr, listensocklen,
- type, address);
- tor_free(listensockaddr);
- tor_free(address);
- } else
- conn = NULL;
-
- if (!conn) {
- r = -1;
+ const config_line_t *c;
+ for (c = cfg; c; c = c->next) {
+ port_cfg_t *port;
+ tor_addr_t addr;
+ uint16_t portval = 0;
+ if (is_sockaddr_un) {
+ size_t len = strlen(c->value);
+ port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1);
+ port->is_unix_addr = 1;
+ memcpy(port->unix_addr, c->value, len+1);
} else {
- if (new_conns)
- smartlist_add(new_conns, conn);
+ if (tor_addr_port_lookup(c->value, &addr, &portval) < 0) {
+ log_warn(LD_CONFIG, "Can't parse/resolve %s %s",
+ c->key, c->value);
+ retval = -1;
+ continue;
+ }
+ port = tor_malloc_zero(sizeof(port_cfg_t));
+ tor_addr_copy(&port->addr, &addr);
}
- } SMARTLIST_FOREACH_END(cfg_line);
+ port->type = type;
+ port->port = portval ? portval : port_option;
+ smartlist_add(ports, port);
+ }
+ }
}
- if (free_launch_elts) {
- SMARTLIST_FOREACH(launch, config_line_t *, cfg_line,
- config_free_lines(cfg_line));
- }
- smartlist_free(launch);
+ if (retval == -1)
+ goto cleanup;
- return r;
+ retval = retry_listener_ports(old_conns, ports, new_conns);
+
+ cleanup:
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, tor_free(p));
+ smartlist_free(ports);
+ return retval;
}
/** Launch listeners for each port you should have open. Only launch
@@ -1952,53 +1975,64 @@ int
retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns)
{
- or_options_t *options = get_options();
+ smartlist_t *listeners = smartlist_create();
+ const or_options_t *options = get_options();
int retval = 0;
const uint16_t old_or_port = router_get_advertised_or_port(options);
const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
- if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
- options->ORPort, "0.0.0.0",
- replaced_conns, new_conns, options->ClientOnly,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
- options->DirPort, "0.0.0.0",
- replaced_conns, new_conns, options->ClientOnly,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
- options->SocksPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
- options->TransPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NATDListenAddress,
- options->NATDPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress,
- options->DNSPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
+ SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
+ if (connection_is_listener(conn) && !conn->marked_for_close)
+ smartlist_add(listeners, conn);
+ } SMARTLIST_FOREACH_END(conn);
+
+ if (! options->ClientOnly && ! options->DisableNetwork) {
+ if (retry_listeners(listeners,
+ CONN_TYPE_OR_LISTENER, options->ORListenAddress,
+ options->ORPort, "0.0.0.0",
+ new_conns, 0) < 0)
+ retval = -1;
+ if (retry_listeners(listeners,
+ CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
+ options->DirPort, "0.0.0.0",
+ new_conns, 0) < 0)
+ retval = -1;
+ }
+
+ if (!options->DisableNetwork) {
+ if (retry_listener_ports(listeners,
+ get_configured_client_ports(),
+ new_conns) < 0)
+ retval = -1;
+ }
+
+ if (retry_listeners(listeners,
+ CONN_TYPE_CONTROL_LISTENER,
options->ControlListenAddress,
options->ControlPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- return -1;
- if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
+ new_conns, 0) < 0)
+ retval = -1;
+ if (retry_listeners(listeners,
+ CONN_TYPE_CONTROL_LISTENER,
options->ControlSocket,
options->ControlSocket ? 1 : 0, NULL,
- replaced_conns, new_conns, 0,
- AF_UNIX)<0)
- return -1;
+ new_conns, 1) < 0)
+ retval = -1;
+
+ /* Any members that were still in 'listeners' don't correspond to
+ * any configured port. Kill 'em. */
+ SMARTLIST_FOREACH_BEGIN(listeners, connection_t *, conn) {
+ log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d",
+ conn_type_to_string(conn->type), conn->address, conn->port);
+ if (replaced_conns) {
+ smartlist_add(replaced_conns, conn);
+ } else {
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn);
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ smartlist_free(listeners);
if (old_or_port != router_get_advertised_or_port(options) ||
old_dir_port != router_get_advertised_dir_port(options, 0)) {
@@ -2012,20 +2046,66 @@ retry_all_listeners(smartlist_t *replaced_conns,
return retval;
}
-/** Return 1 if we should apply rate limiting to <b>conn</b>,
- * and 0 otherwise. Right now this just checks if it's an internal
- * IP address or an internal connection. */
+/** Mark every listener of type other than CONTROL_LISTENER to be closed. */
+void
+connection_mark_all_noncontrol_listeners(void)
+{
+ SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
+ if (conn->marked_for_close)
+ continue;
+ if (conn->type == CONN_TYPE_CONTROL_LISTENER)
+ continue;
+ if (connection_is_listener(conn))
+ connection_mark_for_close(conn);
+ } SMARTLIST_FOREACH_END(conn);
+}
+
+/** Mark every external conection not used for controllers for close. */
+void
+connection_mark_all_noncontrol_connections(void)
+{
+ SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
+ if (conn->marked_for_close)
+ continue;
+ switch (conn->type) {
+ case CONN_TYPE_CPUWORKER:
+ case CONN_TYPE_CONTROL_LISTENER:
+ case CONN_TYPE_CONTROL:
+ break;
+ case CONN_TYPE_AP:
+ connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
+ END_STREAM_REASON_HIBERNATING);
+ break;
+ default:
+ connection_mark_for_close(conn);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+}
+
+/** Return 1 if we should apply rate limiting to <b>conn</b>, and 0
+ * otherwise.
+ * Right now this just checks if it's an internal IP address or an
+ * internal connection. We also check if the connection uses pluggable
+ * transports, since we should then limit it even if it comes from an
+ * internal IP address. */
static int
connection_is_rate_limited(connection_t *conn)
{
- if (conn->linked || /* internal connection */
- tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
- tor_addr_is_internal(&conn->addr, 0)) /* internal address */
- return 0;
+ const or_options_t *options = get_options();
+ if (conn->linked)
+ return 0; /* Internal connection */
+ else if (! options->CountPrivateBandwidth &&
+ (tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
+ tor_addr_is_internal(&conn->addr, 0)))
+ return 0; /* Internal address */
else
return 1;
}
+#ifdef USE_BUFFEREVENTS
+static struct bufferevent_rate_limit_group *global_rate_limit = NULL;
+#else
extern int global_read_bucket, global_write_bucket;
extern int global_relayed_read_bucket, global_relayed_write_bucket;
@@ -2033,11 +2113,13 @@ extern int global_relayed_read_bucket, global_relayed_write_bucket;
* we are likely to run dry again this second, so be stingy with the
* tokens we just put in. */
static int write_buckets_empty_last_second = 0;
+#endif
/** How many seconds of no active local circuits will make the
* connection revert to the "relayed" bandwidth class? */
#define CLIENT_IDLE_TIME_FOR_PRIORITY 30
+#ifndef USE_BUFFEREVENTS
/** Return 1 if <b>conn</b> should use tokens from the "relayed"
* bandwidth rates, else 0. Currently, only OR conns with bandwidth
* class 1, and directory conns that are serving data out, count.
@@ -2148,6 +2230,20 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
return connection_bucket_round_robin(base, priority,
global_bucket, conn_bucket);
}
+#else
+static ssize_t
+connection_bucket_read_limit(connection_t *conn, time_t now)
+{
+ (void) now;
+ return bufferevent_get_max_to_read(conn->bufev);
+}
+ssize_t
+connection_bucket_write_limit(connection_t *conn, time_t now)
+{
+ (void) now;
+ return bufferevent_get_max_to_write(conn->bufev);
+}
+#endif
/** Return 1 if the global write buckets are low enough that we
* shouldn't send <b>attempt</b> bytes of low-priority directory stuff
@@ -2172,8 +2268,12 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
int
global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
{
+#ifdef USE_BUFFEREVENTS
+ ssize_t smaller_bucket = bufferevent_get_max_to_write(conn->bufev);
+#else
int smaller_bucket = global_write_bucket < global_relayed_write_bucket ?
global_write_bucket : global_relayed_write_bucket;
+#endif
if (authdir_mode(get_options()) && priority>1)
return 0; /* there's always room to answer v2 if we're an auth dir */
@@ -2183,12 +2283,14 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
if (smaller_bucket < (int)attempt)
return 1; /* not enough space no matter the priority */
+#ifndef USE_BUFFEREVENTS
if (write_buckets_empty_last_second)
return 1; /* we're already hitting our limits, no more please */
+#endif
if (priority == 1) { /* old-style v1 query */
/* Could we handle *two* of these requests within the next two seconds? */
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int64_t can_write = (int64_t)smaller_bucket
+ 2*(options->RelayBandwidthRate ? options->RelayBandwidthRate :
options->BandwidthRate);
@@ -2200,23 +2302,11 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
return 0;
}
-/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes
- * onto <b>conn</b>. Decrement buckets appropriately. */
+/** DOCDOC */
static void
-connection_buckets_decrement(connection_t *conn, time_t now,
- size_t num_read, size_t num_written)
+record_num_bytes_transferred_impl(connection_t *conn,
+ time_t now, size_t num_read, size_t num_written)
{
- if (num_written >= INT_MAX || num_read >= INT_MAX) {
- log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
- "connection type=%s, state=%s",
- (unsigned long)num_read, (unsigned long)num_written,
- conn_type_to_string(conn->type),
- conn_state_to_string(conn->type, conn->state));
- if (num_written >= INT_MAX) num_written = 1;
- if (num_read >= INT_MAX) num_read = 1;
- tor_fragile_assert();
- }
-
/* Count bytes of answering direct and tunneled directory requests */
if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) {
if (num_read > 0)
@@ -2227,6 +2317,11 @@ connection_buckets_decrement(connection_t *conn, time_t now,
if (!connection_is_rate_limited(conn))
return; /* local IPs are free */
+
+ if (conn->type == CONN_TYPE_OR)
+ rep_hist_note_or_conn_bytes(conn->global_identifier, num_read,
+ num_written, now);
+
if (num_read > 0) {
rep_hist_note_bytes_read(num_read, now);
}
@@ -2235,6 +2330,52 @@ connection_buckets_decrement(connection_t *conn, time_t now,
}
if (conn->type == CONN_TYPE_EXIT)
rep_hist_note_exit_bytes(conn->port, num_written, num_read);
+}
+
+#ifdef USE_BUFFEREVENTS
+/** DOCDOC */
+static void
+record_num_bytes_transferred(connection_t *conn,
+ time_t now, size_t num_read, size_t num_written)
+{
+ /* XXX023 check if this is necessary */
+ if (num_written >= INT_MAX || num_read >= INT_MAX) {
+ log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
+ "connection type=%s, state=%s",
+ (unsigned long)num_read, (unsigned long)num_written,
+ conn_type_to_string(conn->type),
+ conn_state_to_string(conn->type, conn->state));
+ if (num_written >= INT_MAX) num_written = 1;
+ if (num_read >= INT_MAX) num_read = 1;
+ tor_fragile_assert();
+ }
+
+ record_num_bytes_transferred_impl(conn,now,num_read,num_written);
+}
+#endif
+
+#ifndef USE_BUFFEREVENTS
+/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes
+ * onto <b>conn</b>. Decrement buckets appropriately. */
+static void
+connection_buckets_decrement(connection_t *conn, time_t now,
+ size_t num_read, size_t num_written)
+{
+ if (num_written >= INT_MAX || num_read >= INT_MAX) {
+ log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
+ "connection type=%s, state=%s",
+ (unsigned long)num_read, (unsigned long)num_written,
+ conn_type_to_string(conn->type),
+ conn_state_to_string(conn->type, conn->state));
+ if (num_written >= INT_MAX) num_written = 1;
+ if (num_read >= INT_MAX) num_read = 1;
+ tor_fragile_assert();
+ }
+
+ record_num_bytes_transferred_impl(conn, now, num_read, num_written);
+
+ if (!connection_is_rate_limited(conn))
+ return; /* local IPs are free */
if (connection_counts_as_relayed_traffic(conn, now)) {
global_relayed_read_bucket -= (int)num_read;
@@ -2300,7 +2441,7 @@ connection_consider_empty_write_buckets(connection_t *conn)
void
connection_bucket_init(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* start it at max traffic */
global_read_bucket = (int)options->BandwidthBurst;
global_write_bucket = (int)options->BandwidthBurst;
@@ -2313,22 +2454,23 @@ connection_bucket_init(void)
}
}
-/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate
- * <b>rate</b> and bandwidth burst <b>burst</b>, assuming that
- * <b>seconds_elapsed</b> seconds have passed since the last call.
- **/
+/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate per
+ * second <b>rate</b> and bandwidth burst <b>burst</b>, assuming that
+ * <b>milliseconds_elapsed</b> milliseconds have passed since the last
+ * call. */
static void
connection_bucket_refill_helper(int *bucket, int rate, int burst,
- int seconds_elapsed, const char *name)
+ int milliseconds_elapsed,
+ const char *name)
{
int starting_bucket = *bucket;
- if (starting_bucket < burst && seconds_elapsed) {
- if (((burst - starting_bucket)/seconds_elapsed) < rate) {
+ if (starting_bucket < burst && milliseconds_elapsed > 0) {
+ int64_t incr = (((int64_t)rate) * milliseconds_elapsed) / 1000;
+ if ((burst - starting_bucket) < incr) {
*bucket = burst; /* We would overflow the bucket; just set it to
* the maximum. */
} else {
- int incr = rate*seconds_elapsed;
- *bucket += incr;
+ *bucket += (int)incr;
if (*bucket > burst || *bucket < starting_bucket) {
/* If we overflow the burst, or underflow our starting bucket,
* cap the bucket value to burst. */
@@ -2341,41 +2483,46 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst,
}
}
-/** A second has rolled over; increment buckets appropriately. */
+/** Time has passed; increment buckets appropriately. */
void
-connection_bucket_refill(int seconds_elapsed, time_t now)
+connection_bucket_refill(int milliseconds_elapsed, time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *conns = get_connection_array();
- int relayrate, relayburst;
+ int bandwidthrate, bandwidthburst, relayrate, relayburst;
+
+ bandwidthrate = (int)options->BandwidthRate;
+ bandwidthburst = (int)options->BandwidthBurst;
if (options->RelayBandwidthRate) {
relayrate = (int)options->RelayBandwidthRate;
relayburst = (int)options->RelayBandwidthBurst;
} else {
- relayrate = (int)options->BandwidthRate;
- relayburst = (int)options->BandwidthBurst;
+ relayrate = bandwidthrate;
+ relayburst = bandwidthburst;
}
- tor_assert(seconds_elapsed >= 0);
+ tor_assert(milliseconds_elapsed >= 0);
write_buckets_empty_last_second =
global_relayed_write_bucket <= 0 || global_write_bucket <= 0;
/* refill the global buckets */
connection_bucket_refill_helper(&global_read_bucket,
- (int)options->BandwidthRate,
- (int)options->BandwidthBurst,
- seconds_elapsed, "global_read_bucket");
+ bandwidthrate, bandwidthburst,
+ milliseconds_elapsed,
+ "global_read_bucket");
connection_bucket_refill_helper(&global_write_bucket,
- (int)options->BandwidthRate,
- (int)options->BandwidthBurst,
- seconds_elapsed, "global_write_bucket");
+ bandwidthrate, bandwidthburst,
+ milliseconds_elapsed,
+ "global_write_bucket");
connection_bucket_refill_helper(&global_relayed_read_bucket,
- relayrate, relayburst, seconds_elapsed,
+ relayrate, relayburst,
+ milliseconds_elapsed,
"global_relayed_read_bucket");
connection_bucket_refill_helper(&global_relayed_write_bucket,
- relayrate, relayburst, seconds_elapsed,
+ relayrate, relayburst,
+ milliseconds_elapsed,
"global_relayed_write_bucket");
/* refill the per-connection buckets */
@@ -2383,18 +2530,20 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
{
if (connection_speaks_cells(conn)) {
or_connection_t *or_conn = TO_OR_CONN(conn);
+ int orbandwidthrate = or_conn->bandwidthrate;
+ int orbandwidthburst = or_conn->bandwidthburst;
if (connection_bucket_should_increase(or_conn->read_bucket, or_conn)) {
connection_bucket_refill_helper(&or_conn->read_bucket,
- or_conn->bandwidthrate,
- or_conn->bandwidthburst,
- seconds_elapsed,
+ orbandwidthrate,
+ orbandwidthburst,
+ milliseconds_elapsed,
"or_conn->read_bucket");
}
if (connection_bucket_should_increase(or_conn->write_bucket, or_conn)) {
connection_bucket_refill_helper(&or_conn->write_bucket,
- or_conn->bandwidthrate,
- or_conn->bandwidthburst,
- seconds_elapsed,
+ orbandwidthrate,
+ orbandwidthburst,
+ milliseconds_elapsed,
"or_conn->write_bucket");
}
}
@@ -2443,6 +2592,91 @@ connection_bucket_should_increase(int bucket, or_connection_t *conn)
return 1;
}
+#else
+static void
+connection_buckets_decrement(connection_t *conn, time_t now,
+ size_t num_read, size_t num_written)
+{
+ (void) conn;
+ (void) now;
+ (void) num_read;
+ (void) num_written;
+ /* Libevent does this for us. */
+}
+
+void
+connection_bucket_refill(int seconds_elapsed, time_t now)
+{
+ (void) seconds_elapsed;
+ (void) now;
+ /* Libevent does this for us. */
+}
+void
+connection_bucket_init(void)
+{
+ const or_options_t *options = get_options();
+ const struct timeval *tick = tor_libevent_get_one_tick_timeout();
+ struct ev_token_bucket_cfg *bucket_cfg;
+
+ uint64_t rate, burst;
+ if (options->RelayBandwidthRate) {
+ rate = options->RelayBandwidthRate;
+ burst = options->RelayBandwidthBurst;
+ } else {
+ rate = options->BandwidthRate;
+ burst = options->BandwidthBurst;
+ }
+
+ /* This can't overflow, since TokenBucketRefillInterval <= 1000,
+ * and rate started out less than INT32_MAX. */
+ rate = (rate * options->TokenBucketRefillInterval) / 1000;
+
+ bucket_cfg = ev_token_bucket_cfg_new((uint32_t)rate, (uint32_t)burst,
+ (uint32_t)rate, (uint32_t)burst,
+ tick);
+
+ if (!global_rate_limit) {
+ global_rate_limit =
+ bufferevent_rate_limit_group_new(tor_libevent_get_base(), bucket_cfg);
+ } else {
+ bufferevent_rate_limit_group_set_cfg(global_rate_limit, bucket_cfg);
+ }
+ ev_token_bucket_cfg_free(bucket_cfg);
+}
+
+void
+connection_get_rate_limit_totals(uint64_t *read_out, uint64_t *written_out)
+{
+ if (global_rate_limit == NULL) {
+ *read_out = *written_out = 0;
+ } else {
+ bufferevent_rate_limit_group_get_totals(
+ global_rate_limit, read_out, written_out);
+ }
+}
+
+/** DOCDOC */
+void
+connection_enable_rate_limiting(connection_t *conn)
+{
+ if (conn->bufev) {
+ if (!global_rate_limit)
+ connection_bucket_init();
+ tor_add_bufferevent_to_rate_limit_group(conn->bufev, global_rate_limit);
+ }
+}
+
+static void
+connection_consider_empty_write_buckets(connection_t *conn)
+{
+ (void) conn;
+}
+static void
+connection_consider_empty_read_buckets(connection_t *conn)
+{
+ (void) conn;
+}
+#endif
/** Read bytes from conn-\>s and process them.
*
@@ -2501,8 +2735,10 @@ connection_handle_read_impl(connection_t *conn)
if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
connection_edge_end_errno(edge_conn);
- if (edge_conn->socks_request) /* broken, don't send a socks reply back */
- edge_conn->socks_request->has_finished = 1;
+ if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) {
+ /* broken, don't send a socks reply back */
+ TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
}
connection_close_immediate(conn); /* Don't flush; connection is dead. */
connection_mark_for_close(conn);
@@ -2697,7 +2933,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
}
if (n_read > 0) {
- /* change *max_to_read */
+ /* change *max_to_read */
*max_to_read = at_most - n_read;
/* Update edge_conn->n_read */
@@ -2729,11 +2965,212 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
return 0;
}
+#ifdef USE_BUFFEREVENTS
+/* XXXX These generic versions could be simplified by making them
+ type-specific */
+
+/** Callback: Invoked whenever bytes are added to or drained from an input
+ * evbuffer. Used to track the number of bytes read. */
+static void
+evbuffer_inbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *info, void *arg)
+{
+ connection_t *conn = arg;
+ (void) buf;
+ /* XXXX These need to get real counts on the non-nested TLS case. - NM */
+ if (info->n_added) {
+ time_t now = approx_time();
+ conn->timestamp_lastread = now;
+ record_num_bytes_transferred(conn, now, info->n_added, 0);
+ connection_consider_empty_read_buckets(conn);
+ if (conn->type == CONN_TYPE_AP) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ /*XXXX022 check for overflow*/
+ edge_conn->n_read += (int)info->n_added;
+ }
+ }
+}
+
+/** Callback: Invoked whenever bytes are added to or drained from an output
+ * evbuffer. Used to track the number of bytes written. */
+static void
+evbuffer_outbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *info, void *arg)
+{
+ connection_t *conn = arg;
+ (void)buf;
+ if (info->n_deleted) {
+ time_t now = approx_time();
+ conn->timestamp_lastwritten = now;
+ record_num_bytes_transferred(conn, now, 0, info->n_deleted);
+ connection_consider_empty_write_buckets(conn);
+ if (conn->type == CONN_TYPE_AP) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ /*XXXX022 check for overflow*/
+ edge_conn->n_written += (int)info->n_deleted;
+ }
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has read data. */
+void
+connection_handle_read_cb(struct bufferevent *bufev, void *arg)
+{
+ connection_t *conn = arg;
+ (void) bufev;
+ if (!conn->marked_for_close) {
+ if (connection_process_inbuf(conn, 1)<0) /* XXXX Always 1? */
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has written data. */
+void
+connection_handle_write_cb(struct bufferevent *bufev, void *arg)
+{
+ connection_t *conn = arg;
+ struct evbuffer *output;
+ if (connection_flushed_some(conn)<0) {
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ return;
+ }
+
+ output = bufferevent_get_output(bufev);
+ if (!evbuffer_get_length(output)) {
+ connection_finished_flushing(conn);
+ if (conn->marked_for_close && conn->hold_open_until_flushed) {
+ conn->hold_open_until_flushed = 0;
+ if (conn->linked) {
+ /* send eof */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has had an event (like a
+ * connection, or an eof, or an error) occur. */
+void
+connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg)
+{
+ connection_t *conn = arg;
+ (void) bufev;
+ if (event & BEV_EVENT_CONNECTED) {
+ tor_assert(connection_state_is_connecting(conn));
+ if (connection_finished_connecting(conn)<0)
+ return;
+ }
+ if (event & BEV_EVENT_EOF) {
+ if (!conn->marked_for_close) {
+ conn->inbuf_reached_eof = 1;
+ if (connection_reached_eof(conn)<0)
+ return;
+ }
+ }
+ if (event & BEV_EVENT_ERROR) {
+ int socket_error = evutil_socket_geterror(conn->s);
+ if (conn->type == CONN_TYPE_OR &&
+ conn->state == OR_CONN_STATE_CONNECTING) {
+ connection_or_connect_failed(TO_OR_CONN(conn),
+ errno_to_orconn_end_reason(socket_error),
+ tor_socket_strerror(socket_error));
+ } else if (CONN_IS_EDGE(conn)) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ if (!edge_conn->edge_has_sent_end)
+ connection_edge_end_errno(edge_conn);
+ if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) {
+ /* broken, don't send a socks reply back */
+ TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
+ }
+ connection_close_immediate(conn); /* Connection is dead. */
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ }
+}
+
+/** Set up the generic callbacks for the bufferevent on <b>conn</b>. */
+void
+connection_configure_bufferevent_callbacks(connection_t *conn)
+{
+ struct bufferevent *bufev;
+ struct evbuffer *input, *output;
+ tor_assert(conn->bufev);
+ bufev = conn->bufev;
+ bufferevent_setcb(bufev,
+ connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_handle_event_cb,
+ conn);
+ /* Set a fairly high write low-watermark so that we get the write callback
+ called whenever data is written to bring us under 128K. Leave the
+ high-watermark at 0.
+ */
+ bufferevent_setwatermark(bufev, EV_WRITE, 128*1024, 0);
+
+ input = bufferevent_get_input(bufev);
+ output = bufferevent_get_output(bufev);
+ evbuffer_add_cb(input, evbuffer_inbuf_callback, conn);
+ evbuffer_add_cb(output, evbuffer_outbuf_callback, conn);
+}
+#endif
+
/** A pass-through to fetch_from_buf. */
int
connection_fetch_from_buf(char *string, size_t len, connection_t *conn)
{
- return fetch_from_buf(string, len, conn->inbuf);
+ IF_HAS_BUFFEREVENT(conn, {
+ /* XXX overflow -seb */
+ return (int)bufferevent_read(conn->bufev, string, len);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf(string, len, conn->inbuf);
+ }
+}
+
+/** As fetch_from_buf_line(), but read from a connection's input buffer. */
+int
+connection_fetch_from_buf_line(connection_t *conn, char *data,
+ size_t *data_len)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ int r;
+ size_t eol_len=0;
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ struct evbuffer_ptr ptr =
+ evbuffer_search_eol(input, NULL, &eol_len, EVBUFFER_EOL_LF);
+ if (ptr.pos == -1)
+ return 0; /* No EOL found. */
+ if ((size_t)ptr.pos+eol_len >= *data_len) {
+ return -1; /* Too long */
+ }
+ *data_len = ptr.pos+eol_len;
+ r = evbuffer_remove(input, data, ptr.pos+eol_len);
+ tor_assert(r >= 0);
+ data[ptr.pos+eol_len] = '\0';
+ return 1;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_line(conn->inbuf, data, data_len);
+ }
+}
+
+/** As fetch_from_buf_http, but fetches from a conncetion's input buffer_t or
+ * its bufferevent as appropriate. */
+int
+connection_fetch_from_buf_http(connection_t *conn,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used,
+ size_t max_bodylen, int force_complete)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_from_evbuffer_http(input, headers_out, max_headerlen,
+ body_out, body_used, max_bodylen, force_complete);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_http(conn->inbuf, headers_out, max_headerlen,
+ body_out, body_used, max_bodylen, force_complete);
+ }
}
/** Return conn-\>outbuf_flushlen: how many bytes conn wants to flush
@@ -2854,6 +3291,7 @@ connection_handle_write_impl(connection_t *conn, int force)
/* If we just flushed the last bytes, check if this tunneled dir
* request is done. */
+ /* XXXX move this to flushed_some or finished_flushing -NM */
if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id)
geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
DIRREQ_OR_CONN_BUFFER_FLUSHED);
@@ -2909,6 +3347,7 @@ connection_handle_write_impl(connection_t *conn, int force)
if (n_written && conn->type == CONN_TYPE_AP) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+
/* Check for overflow: */
if (PREDICT_LIKELY(UINT32_MAX - edge_conn->n_written > n_written))
edge_conn->n_written += (int)n_written;
@@ -2952,6 +3391,25 @@ connection_handle_write(connection_t *conn, int force)
return res;
}
+/**
+ * Try to flush data that's waiting for a write on <b>conn</b>. Return
+ * -1 on failure, 0 on success.
+ *
+ * Don't use this function for regular writing; the buffers/bufferevents
+ * system should be good enough at scheduling writes there. Instead, this
+ * function is for cases when we're about to exit or something and we want
+ * to report it right away.
+ */
+int
+connection_flush(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ int r = bufferevent_flush(conn->bufev, EV_WRITE, BEV_FLUSH);
+ return (r < 0) ? -1 : 0;
+ });
+ return connection_handle_write(conn, 1);
+}
+
/** OpenSSL TLS record size is 16383; this is close. The goal here is to
* push data out as soon as we know there's enough for a TLS record, so
* during periods of high load we won't read entire megabytes from
@@ -2985,6 +3443,22 @@ _connection_write_to_buf_impl(const char *string, size_t len,
if (conn->marked_for_close && !conn->hold_open_until_flushed)
return;
+ IF_HAS_BUFFEREVENT(conn, {
+ if (zlib) {
+ int done = zlib < 0;
+ r = write_to_evbuffer_zlib(bufferevent_get_output(conn->bufev),
+ TO_DIR_CONN(conn)->zlib_state,
+ string, len, done);
+ } else {
+ r = bufferevent_write(conn->bufev, string, len);
+ }
+ if (r < 0) {
+ /* XXXX mark for close? */
+ log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen.");
+ }
+ return;
+ });
+
old_datalen = buf_datalen(conn->outbuf);
if (zlib) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
@@ -3012,7 +3486,13 @@ _connection_write_to_buf_impl(const char *string, size_t len,
return;
}
- connection_start_writing(conn);
+ /* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
+ * state, we don't want to try to write it right away, since
+ * conn->write_event won't be set yet. Otherwise, write data from
+ * this conn as the socket is available. */
+ if (conn->write_event) {
+ connection_start_writing(conn);
+ }
if (zlib) {
conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
} else {
@@ -3138,8 +3618,7 @@ connection_get_by_type_state_rendquery(int type, int state,
type == CONN_TYPE_AP || type == CONN_TYPE_EXIT);
tor_assert(rendquery);
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
if (conn->type == type &&
!conn->marked_for_close &&
(!state || state == conn->state)) {
@@ -3154,7 +3633,33 @@ connection_get_by_type_state_rendquery(int type, int state,
TO_EDGE_CONN(conn)->rend_data->onion_address))
return conn;
}
- });
+ } SMARTLIST_FOREACH_END(conn);
+ return NULL;
+}
+
+/** Return a directory connection (if any one exists) that is fetching
+ * the item described by <b>state</b>/<b>resource</b> */
+dir_connection_t *
+connection_dir_get_by_purpose_and_resource(int purpose,
+ const char *resource)
+{
+ smartlist_t *conns = get_connection_array();
+
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ dir_connection_t *dirconn;
+ if (conn->type != CONN_TYPE_DIR || conn->marked_for_close ||
+ conn->purpose != purpose)
+ continue;
+ dirconn = TO_DIR_CONN(conn);
+ if (dirconn->requested_resource == NULL) {
+ if (resource == NULL)
+ return dirconn;
+ } else if (resource) {
+ if (0 == strcmp(resource, dirconn->requested_resource))
+ return dirconn;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
return NULL;
}
@@ -3408,6 +3913,9 @@ connection_finished_flushing(connection_t *conn)
// log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s);
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_stop_writing(conn);
+
switch (conn->type) {
case CONN_TYPE_OR:
return connection_or_finished_flushing(TO_OR_CONN(conn));
@@ -3533,11 +4041,23 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn);
tor_assert(conn->type >= _CONN_TYPE_MIN);
tor_assert(conn->type <= _CONN_TYPE_MAX);
+
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ tor_assert(conn->read_event == NULL);
+ tor_assert(conn->write_event == NULL);
+ tor_assert(conn->inbuf == NULL);
+ tor_assert(conn->outbuf == NULL);
+ }
+#endif
+
switch (conn->type) {
case CONN_TYPE_OR:
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
break;
case CONN_TYPE_AP:
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
+ break;
case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
break;
@@ -3547,6 +4067,9 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_CONTROL:
tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
break;
+ CASE_ANY_LISTENER_TYPE:
+ tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC);
+ break;
default:
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
break;
@@ -3560,8 +4083,15 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(!SOCKET_OK(conn->s));
if (conn->outbuf_flushlen > 0) {
- tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw ||
- (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->edge_blocked_on_circ));
+ /* With optimistic data, we may have queued data in
+ * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
+ * */
+ tor_assert((conn->type == CONN_TYPE_EXIT &&
+ conn->state == EXIT_CONN_STATE_RESOLVING) ||
+ connection_is_writing(conn) ||
+ conn->write_blocked_on_bw ||
+ (CONN_IS_EDGE(conn) &&
+ TO_EDGE_CONN(conn)->edge_blocked_on_circ));
}
if (conn->hold_open_until_flushed)
@@ -3571,10 +4101,10 @@ assert_connection_ok(connection_t *conn, time_t now)
* marked_for_close. */
/* buffers */
- if (!connection_is_listener(conn)) {
+ if (conn->inbuf)
assert_buf_ok(conn->inbuf);
+ if (conn->outbuf)
assert_buf_ok(conn->outbuf);
- }
if (conn->type == CONN_TYPE_OR) {
or_connection_t *or_conn = TO_OR_CONN(conn);
@@ -3594,21 +4124,18 @@ assert_connection_ok(connection_t *conn, time_t now)
}
if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
- if (edge_conn->chosen_exit_optional || edge_conn->chosen_exit_retries) {
- tor_assert(conn->type == CONN_TYPE_AP);
- tor_assert(edge_conn->chosen_exit_name);
- }
-
/* XXX unchecked: package window, deliver window. */
if (conn->type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
+ if (entry_conn->chosen_exit_optional || entry_conn->chosen_exit_retries)
+ tor_assert(entry_conn->chosen_exit_name);
- tor_assert(edge_conn->socks_request);
+ tor_assert(entry_conn->socks_request);
if (conn->state == AP_CONN_STATE_OPEN) {
- tor_assert(edge_conn->socks_request->has_finished);
+ tor_assert(entry_conn->socks_request->has_finished);
if (!conn->marked_for_close) {
- tor_assert(edge_conn->cpath_layer);
- assert_cpath_layer_ok(edge_conn->cpath_layer);
+ tor_assert(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
+ assert_cpath_layer_ok(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
}
}
}
@@ -3624,13 +4151,7 @@ assert_connection_ok(connection_t *conn, time_t now)
switch (conn->type)
{
- case CONN_TYPE_OR_LISTENER:
- case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
- case CONN_TYPE_AP_NATD_LISTENER:
- case CONN_TYPE_DIR_LISTENER:
- case CONN_TYPE_CONTROL_LISTENER:
- case CONN_TYPE_AP_DNS_LISTENER:
+ CASE_ANY_LISTENER_TYPE:
tor_assert(conn->state == LISTENER_STATE_READY);
break;
case CONN_TYPE_OR:
@@ -3647,7 +4168,7 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_AP:
tor_assert(conn->state >= _AP_CONN_STATE_MIN);
tor_assert(conn->state <= _AP_CONN_STATE_MAX);
- tor_assert(TO_EDGE_CONN(conn)->socks_request);
+ tor_assert(TO_ENTRY_CONN(conn)->socks_request);
break;
case CONN_TYPE_DIR:
tor_assert(conn->state >= _DIR_CONN_STATE_MIN);
@@ -3668,3 +4189,141 @@ assert_connection_ok(connection_t *conn, time_t now)
}
}
+/** Fills <b>addr</b> and <b>port</b> with the details of the global
+ * proxy server we are using.
+ * <b>conn</b> contains the connection we are using the proxy for.
+ *
+ * Return 0 on success, -1 on failure.
+ */
+int
+get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
+ const connection_t *conn)
+{
+ const or_options_t *options = get_options();
+
+ if (options->HTTPSProxy) {
+ tor_addr_copy(addr, &options->HTTPSProxyAddr);
+ *port = options->HTTPSProxyPort;
+ *proxy_type = PROXY_CONNECT;
+ return 0;
+ } else if (options->Socks4Proxy) {
+ tor_addr_copy(addr, &options->Socks4ProxyAddr);
+ *port = options->Socks4ProxyPort;
+ *proxy_type = PROXY_SOCKS4;
+ return 0;
+ } else if (options->Socks5Proxy) {
+ tor_addr_copy(addr, &options->Socks5ProxyAddr);
+ *port = options->Socks5ProxyPort;
+ *proxy_type = PROXY_SOCKS5;
+ return 0;
+ } else if (options->ClientTransportPlugin ||
+ options->Bridges) {
+ const transport_t *transport = NULL;
+ int r;
+ r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
+ if (r<0)
+ return -1;
+ if (transport) { /* transport found */
+ tor_addr_copy(addr, &transport->addr);
+ *port = transport->port;
+ *proxy_type = transport->socks_version;
+ return 0;
+ }
+ }
+
+ *proxy_type = PROXY_NONE;
+ return 0;
+}
+
+/** Returns the global proxy type used by tor. */
+static int
+get_proxy_type(void)
+{
+ const or_options_t *options = get_options();
+
+ if (options->HTTPSProxy)
+ return PROXY_CONNECT;
+ else if (options->Socks4Proxy)
+ return PROXY_SOCKS4;
+ else if (options->Socks5Proxy)
+ return PROXY_SOCKS5;
+ else if (options->ClientTransportPlugin)
+ return PROXY_PLUGGABLE;
+ else
+ return PROXY_NONE;
+}
+
+/** Log a failed connection to a proxy server.
+ * <b>conn</b> is the connection we use the proxy server for. */
+void
+log_failed_proxy_connection(connection_t *conn)
+{
+ tor_addr_t proxy_addr;
+ uint16_t proxy_port;
+ int proxy_type;
+
+ if (get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, conn) != 0)
+ return; /* if we have no proxy set up, leave this function. */
+
+ log_warn(LD_NET,
+ "The connection to the %s proxy server at %s:%u just failed. "
+ "Make sure that the proxy server is up and running.",
+ proxy_type_to_string(get_proxy_type()), fmt_addr(&proxy_addr),
+ proxy_port);
+}
+
+/** Return string representation of <b>proxy_type</b>. */
+static const char *
+proxy_type_to_string(int proxy_type)
+{
+ switch (proxy_type) {
+ case PROXY_CONNECT: return "HTTP";
+ case PROXY_SOCKS4: return "SOCKS4";
+ case PROXY_SOCKS5: return "SOCKS5";
+ case PROXY_PLUGGABLE: return "pluggable transports SOCKS";
+ case PROXY_NONE: return "NULL";
+ default: tor_assert(0);
+ }
+ return NULL; /*Unreached*/
+}
+
+/** Call _connection_free() on every connection in our array, and release all
+ * storage held by connection.c. This is used by cpuworkers and dnsworkers
+ * when they fork, so they don't keep resources held open (especially
+ * sockets).
+ *
+ * Don't do the checks in connection_free(), because they will
+ * fail.
+ */
+void
+connection_free_all(void)
+{
+ smartlist_t *conns = get_connection_array();
+
+ /* We don't want to log any messages to controllers. */
+ SMARTLIST_FOREACH(conns, connection_t *, conn,
+ if (conn->type == CONN_TYPE_CONTROL)
+ TO_CONTROL_CONN(conn)->event_mask = 0);
+
+ control_update_global_event_mask();
+
+ /* Unlink everything from the identity map. */
+ connection_or_clear_identity_map();
+
+ /* Clear out our list of broken connections */
+ clear_broken_connection_map(0);
+
+ SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn));
+
+ if (outgoing_addrs) {
+ SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr));
+ smartlist_free(outgoing_addrs);
+ outgoing_addrs = NULL;
+ }
+
+#ifdef USE_BUFFEREVENTS
+ if (global_rate_limit)
+ bufferevent_rate_limit_group_free(global_rate_limit);
+#endif
+}
+
diff --git a/src/or/connection.h b/src/or/connection.h
index 576d3a63e1..c4b8bf8abe 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -12,13 +12,18 @@
#ifndef _TOR_CONNECTION_H
#define _TOR_CONNECTION_H
+/* XXXX For buf_datalen in inline function */
+#include "buffers.h"
+
const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state);
dir_connection_t *dir_connection_new(int socket_family);
or_connection_t *or_connection_new(int socket_family);
edge_connection_t *edge_connection_new(int type, int socket_family);
+entry_connection_t *entry_connection_new(int type, int socket_family);
control_connection_t *control_connection_new(int socket_family);
+listener_connection_t *listener_connection_new(int type, int socket_family);
connection_t *connection_new(int type, int socket_family);
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
@@ -31,6 +36,21 @@ void _connection_mark_for_close(connection_t *conn,int line, const char *file);
#define connection_mark_for_close(c) \
_connection_mark_for_close((c), __LINE__, _SHORT_FILE_)
+/**
+ * Mark 'c' for close, but try to hold it open until all the data is written.
+ */
+#define _connection_mark_and_flush(c,line,file) \
+ do { \
+ connection_t *tmp_conn_ = (c); \
+ _connection_mark_for_close(tmp_conn_, (line), (file)); \
+ tmp_conn_->hold_open_until_flushed = 1; \
+ IF_HAS_BUFFEREVENT(tmp_conn_, \
+ connection_start_writing(tmp_conn_)); \
+ } while (0)
+
+#define connection_mark_and_flush(c) \
+ _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_)
+
void connection_expire_held_open(void);
int connection_connect(connection_t *conn, const char *address,
@@ -39,10 +59,16 @@ int connection_connect(connection_t *conn, const char *address,
int connection_proxy_connect(connection_t *conn, int type);
int connection_read_proxy_handshake(connection_t *conn);
+void log_failed_proxy_connection(connection_t *conn);
+int get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
+ const connection_t *conn);
int retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns);
+void connection_mark_all_noncontrol_listeners(void);
+void connection_mark_all_noncontrol_connections(void);
+
ssize_t connection_bucket_write_limit(connection_t *conn, time_t now);
int global_write_bucket_low(connection_t *conn, size_t attempt, int priority);
void connection_bucket_init(void);
@@ -51,10 +77,18 @@ void connection_bucket_refill(int seconds_elapsed, time_t now);
int connection_handle_read(connection_t *conn);
int connection_fetch_from_buf(char *string, size_t len, connection_t *conn);
+int connection_fetch_from_buf_line(connection_t *conn, char *data,
+ size_t *data_len);
+int connection_fetch_from_buf_http(connection_t *conn,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used,
+ size_t max_bodylen, int force_complete);
int connection_wants_to_flush(connection_t *conn);
int connection_outbuf_too_full(connection_t *conn);
int connection_handle_write(connection_t *conn, int force);
+int connection_flush(connection_t *conn);
+
void _connection_write_to_buf_impl(const char *string, size_t len,
connection_t *conn, int zlib);
static void connection_write_to_buf(const char *string, size_t len,
@@ -73,6 +107,29 @@ connection_write_to_buf_zlib(const char *string, size_t len,
_connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1);
}
+static size_t connection_get_inbuf_len(connection_t *conn);
+static size_t connection_get_outbuf_len(connection_t *conn);
+
+static INLINE size_t
+connection_get_inbuf_len(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ return evbuffer_get_length(bufferevent_get_input(conn->bufev));
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return conn->inbuf ? buf_datalen(conn->inbuf) : 0;
+ }
+}
+
+static INLINE size_t
+connection_get_outbuf_len(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ return evbuffer_get_length(bufferevent_get_output(conn->bufev));
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return conn->outbuf ? buf_datalen(conn->outbuf) : 0;
+ }
+}
+
connection_t *connection_get_by_global_id(uint64_t id);
connection_t *connection_get_by_type(int type);
@@ -83,6 +140,8 @@ connection_t *connection_get_by_type_addr_port_purpose(int type,
connection_t *connection_get_by_type_state(int type, int state);
connection_t *connection_get_by_type_state_rendquery(int type, int state,
const char *rendquery);
+dir_connection_t *connection_dir_get_by_purpose_and_resource(
+ int state, const char *resource);
#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
int connection_is_listener(connection_t *conn);
@@ -96,5 +155,19 @@ int connection_or_nonopen_was_started_here(or_connection_t *conn);
void connection_dump_buffer_mem_stats(int severity);
void remove_file_if_very_old(const char *fname, time_t now);
+#ifdef USE_BUFFEREVENTS
+int connection_type_uses_bufferevent(connection_t *conn);
+void connection_configure_bufferevent_callbacks(connection_t *conn);
+void connection_handle_read_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_write_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg);
+void connection_get_rate_limit_totals(uint64_t *read_out,
+ uint64_t *written_out);
+void connection_enable_rate_limiting(connection_t *conn);
+#else
+#define connection_type_uses_bufferevent(c) (0)
+#endif
+
#endif
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 0c5ebdee64..efaad79b6a 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -23,6 +23,7 @@
#include "dirserv.h"
#include "hibernate.h"
#include "main.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -50,23 +51,26 @@
#define SOCKS4_GRANTED 90
#define SOCKS4_REJECT 91
-static int connection_ap_handshake_process_socks(edge_connection_t *conn);
-static int connection_ap_process_natd(edge_connection_t *conn);
+static int connection_ap_handshake_process_socks(entry_connection_t *conn);
+static int connection_ap_process_natd(entry_connection_t *conn);
static int connection_exit_connect_dir(edge_connection_t *exitconn);
static int address_is_in_virtual_range(const char *addr);
-static int consider_plaintext_ports(edge_connection_t *conn, uint16_t port);
+static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port);
static void clear_trackexithost_mappings(const char *exitname);
+static int connection_ap_supports_optimistic_data(const entry_connection_t *);
/** An AP stream has failed/finished. If it hasn't already sent back
* a socks reply, send one now (based on endreason). Also set
* has_sent_end to 1, and mark the conn.
*/
void
-_connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+_connection_mark_unattached_ap(entry_connection_t *conn, int endreason,
int line, const char *file)
{
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- conn->edge_has_sent_end = 1; /* no circ yet */
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ ENTRY_TO_EDGE_CONN(conn)->edge_has_sent_end = 1; /* no circ yet */
/* If this is a rendezvous stream and it is failing without ever
* being attached to a circuit, assume that an attempt to connect to
@@ -75,14 +79,15 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
* XXX023 This condition doesn't limit to only streams failing
* without ever being attached. That sloppiness should be harmless,
* but we should fix it someday anyway. */
- if ((conn->on_circuit != NULL || conn->edge_has_sent_end) &&
- connection_edge_is_rendezvous_stream(conn)) {
- rend_client_note_connection_attempt_ended(conn->rend_data->onion_address);
+ if ((edge_conn->on_circuit != NULL || edge_conn->edge_has_sent_end) &&
+ connection_edge_is_rendezvous_stream(edge_conn)) {
+ rend_client_note_connection_attempt_ended(
+ edge_conn->rend_data->onion_address);
}
- if (conn->_base.marked_for_close) {
+ if (base_conn->marked_for_close) {
/* This call will warn as appropriate. */
- _connection_mark_for_close(TO_CONN(conn), line, file);
+ _connection_mark_for_close(base_conn, line, file);
return;
}
@@ -102,9 +107,9 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
conn->socks_request->has_finished = 1;
}
- _connection_mark_for_close(TO_CONN(conn), line, file);
- conn->_base.hold_open_until_flushed = 1;
- conn->end_reason = endreason;
+ _connection_mark_and_flush(base_conn, line, file);
+
+ ENTRY_TO_EDGE_CONN(conn)->end_reason = endreason;
}
/** There was an EOF. Send an end and mark the connection for close.
@@ -112,7 +117,7 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
int
connection_edge_reached_eof(edge_connection_t *conn)
{
- if (buf_datalen(conn->_base.inbuf) &&
+ if (connection_get_inbuf_len(TO_CONN(conn)) &&
connection_state_is_open(TO_CONN(conn))) {
/* it still has stuff to process. don't let it die yet. */
return 0;
@@ -122,8 +127,11 @@ connection_edge_reached_eof(edge_connection_t *conn)
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
connection_edge_end(conn, END_STREAM_REASON_DONE);
- if (conn->socks_request) /* eof, so don't send a socks reply back */
- conn->socks_request->has_finished = 1;
+ if (conn->_base.type == CONN_TYPE_AP) {
+ /* eof, so don't send a socks reply back */
+ if (EDGE_TO_ENTRY_CONN(conn)->socks_request)
+ EDGE_TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
connection_mark_for_close(TO_CONN(conn));
}
return 0;
@@ -146,13 +154,13 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
switch (conn->_base.state) {
case AP_CONN_STATE_SOCKS_WAIT:
- if (connection_ap_handshake_process_socks(conn) < 0) {
+ if (connection_ap_handshake_process_socks(EDGE_TO_ENTRY_CONN(conn)) <0) {
/* already marked */
return -1;
}
return 0;
case AP_CONN_STATE_NATD_WAIT:
- if (connection_ap_process_natd(conn) < 0) {
+ if (connection_ap_process_natd(EDGE_TO_ENTRY_CONN(conn)) < 0) {
/* already marked */
return -1;
}
@@ -165,10 +173,26 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
return -1;
}
return 0;
+ case AP_CONN_STATE_CONNECT_WAIT:
+ if (connection_ap_supports_optimistic_data(EDGE_TO_ENTRY_CONN(conn))) {
+ log_info(LD_EDGE,
+ "data from edge while in '%s' state. Sending it anyway. "
+ "package_partial=%d, buflen=%ld",
+ conn_state_to_string(conn->_base.type, conn->_base.state),
+ package_partial,
+ (long)connection_get_inbuf_len(TO_CONN(conn)));
+ if (connection_edge_package_raw_inbuf(conn, package_partial, NULL)<0) {
+ /* (We already sent an end cell if possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ return -1;
+ }
+ return 0;
+ }
+ /* Fall through if the connection is on a circuit without optimistic
+ * data support. */
case EXIT_CONN_STATE_CONNECTING:
case AP_CONN_STATE_RENDDESC_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
- case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_RESOLVE_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT:
log_info(LD_EDGE,
@@ -193,9 +217,10 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn)
log_info(LD_EDGE,
"CircID %d: At an edge. Marking connection for close.", circ_id);
if (conn->_base.type == CONN_TYPE_AP) {
- connection_mark_unattached_ap(conn, END_STREAM_REASON_DESTROY);
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DESTROY);
control_event_stream_bandwidth(conn);
- control_event_stream_status(conn, STREAM_EVENT_CLOSED,
+ control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED,
END_STREAM_REASON_DESTROY);
conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
} else {
@@ -203,8 +228,7 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn)
conn->edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
}
conn->cpath_layer = NULL;
@@ -348,7 +372,6 @@ connection_edge_finished_flushing(edge_connection_t *conn)
switch (conn->_base.state) {
case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN:
- connection_stop_writing(TO_CONN(conn));
connection_edge_consider_sending_sendme(conn);
return 0;
case AP_CONN_STATE_SOCKS_WAIT:
@@ -357,7 +380,7 @@ connection_edge_finished_flushing(edge_connection_t *conn)
case AP_CONN_STATE_CIRCUIT_WAIT:
case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT:
- connection_stop_writing(TO_CONN(conn));
+ case AP_CONN_STATE_RESOLVE_WAIT:
return 0;
default:
log_warn(LD_BUG, "Called in unexpected state %d.",conn->_base.state);
@@ -387,8 +410,9 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
rep_hist_note_exit_stream_opened(conn->port);
conn->state = EXIT_CONN_STATE_OPEN;
- connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
- if (connection_wants_to_flush(conn)) /* in case there are any queued relay
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
+ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay
* cells */
connection_start_writing(conn);
/* deliver a 'connected' relay cell back through the circuit. */
@@ -420,13 +444,79 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
return connection_edge_process_inbuf(edge_conn, 1);
}
+/** Common code to connection_(ap|exit)_about_to_close. */
+static void
+connection_edge_about_to_close(edge_connection_t *edge_conn)
+{
+ if (!edge_conn->edge_has_sent_end) {
+ connection_t *conn = TO_CONN(edge_conn);
+ log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
+ "hasn't sent end yet?",
+ conn->marked_for_close_file, conn->marked_for_close);
+ tor_fragile_assert();
+ }
+}
+
+/* Called when we're about to finally unlink and free an AP (client)
+ * connection: perform necessary accounting and cleanup */
+void
+connection_ap_about_to_close(entry_connection_t *entry_conn)
+{
+ circuit_t *circ;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ connection_t *conn = ENTRY_TO_CONN(entry_conn);
+
+ if (entry_conn->socks_request->has_finished == 0) {
+ /* since conn gets removed right after this function finishes,
+ * there's no point trying to send back a reply at this point. */
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
+ " back a socks reply.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ }
+ if (!edge_conn->end_reason) {
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+ " set end_reason.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ }
+ if (entry_conn->dns_server_request) {
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+ " replied to DNS request.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ dnsserv_reject_request(entry_conn);
+ }
+ control_event_stream_bandwidth(edge_conn);
+ control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED,
+ edge_conn->end_reason);
+ circ = circuit_get_by_edge_conn(edge_conn);
+ if (circ)
+ circuit_detach_stream(circ, edge_conn);
+}
+
+/* Called when we're about to finally unlink and free an exit
+ * connection: perform necessary accounting and cleanup */
+void
+connection_exit_about_to_close(edge_connection_t *edge_conn)
+{
+ circuit_t *circ;
+ connection_t *conn = TO_CONN(edge_conn);
+
+ connection_edge_about_to_close(edge_conn);
+
+ circ = circuit_get_by_edge_conn(edge_conn);
+ if (circ)
+ circuit_detach_stream(circ, edge_conn);
+ if (conn->state == EXIT_CONN_STATE_RESOLVING) {
+ connection_dns_remove(edge_conn);
+ }
+}
+
/** Define a schedule for how long to wait between retrying
* application connections. Rather than waiting a fixed amount of
* time between each retry, we wait 10 seconds each for the first
* two tries, and 15 seconds for each retry after
* that. Hopefully this will improve the expected user experience. */
static int
-compute_retry_timeout(edge_connection_t *conn)
+compute_retry_timeout(entry_connection_t *conn)
{
int timeout = get_options()->CircuitStreamTimeout;
if (timeout) /* if our config options override the default, use them */
@@ -449,41 +539,43 @@ void
connection_ap_expire_beginning(void)
{
edge_connection_t *conn;
+ entry_connection_t *entry_conn;
circuit_t *circ;
time_t now = time(NULL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int severity;
int cutoff;
int seconds_idle, seconds_since_born;
smartlist_t *conns = get_connection_array();
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, c) {
- if (c->type != CONN_TYPE_AP || c->marked_for_close)
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ if (base_conn->type != CONN_TYPE_AP || base_conn->marked_for_close)
continue;
- conn = TO_EDGE_CONN(c);
+ entry_conn = TO_ENTRY_CONN(base_conn);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
/* if it's an internal linked connection, don't yell its status. */
- severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port)
+ severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port)
? LOG_INFO : LOG_NOTICE;
- seconds_idle = (int)( now - conn->_base.timestamp_lastread );
- seconds_since_born = (int)( now - conn->_base.timestamp_created );
+ seconds_idle = (int)( now - base_conn->timestamp_lastread );
+ seconds_since_born = (int)( now - base_conn->timestamp_created );
- if (conn->_base.state == AP_CONN_STATE_OPEN)
+ if (base_conn->state == AP_CONN_STATE_OPEN)
continue;
/* We already consider SocksTimeout in
* connection_ap_handshake_attach_circuit(), but we need to consider
* it here too because controllers that put streams in controller_wait
* state never ask Tor to attach the circuit. */
- if (AP_CONN_STATE_IS_UNATTACHED(conn->_base.state)) {
+ if (AP_CONN_STATE_IS_UNATTACHED(base_conn->state)) {
if (seconds_since_born >= options->SocksTimeout) {
log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. "
"Giving up. (%s)",
seconds_since_born,
- safe_str_client(conn->socks_request->address),
- conn->socks_request->port,
- conn_state_to_string(CONN_TYPE_AP, conn->_base.state));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+ safe_str_client(entry_conn->socks_request->address),
+ entry_conn->socks_request->port,
+ conn_state_to_string(CONN_TYPE_AP, base_conn->state));
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
}
continue;
}
@@ -491,14 +583,14 @@ connection_ap_expire_beginning(void)
/* We're in state connect_wait or resolve_wait now -- waiting for a
* reply to our relay cell. See if we want to retry/give up. */
- cutoff = compute_retry_timeout(conn);
+ cutoff = compute_retry_timeout(entry_conn);
if (seconds_idle < cutoff)
continue;
circ = circuit_get_by_edge_conn(conn);
if (!circ) { /* it's vanished? */
log_info(LD_APP,"Conn is waiting (address %s), but lost its circ.",
- safe_str_client(conn->socks_request->address));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+ safe_str_client(entry_conn->socks_request->address));
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
continue;
}
if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
@@ -507,9 +599,9 @@ connection_ap_expire_beginning(void)
"Rend stream is %d seconds late. Giving up on address"
" '%s.onion'.",
seconds_idle,
- safe_str_client(conn->socks_request->address));
+ safe_str_client(entry_conn->socks_request->address));
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
}
continue;
}
@@ -518,9 +610,10 @@ connection_ap_expire_beginning(void)
"We tried for %d seconds to connect to '%s' using exit %s."
" Retrying on a new circuit.",
seconds_idle,
- safe_str_client(conn->socks_request->address),
+ safe_str_client(entry_conn->socks_request->address),
conn->cpath_layer ?
- extend_info_describe(conn->cpath_layer->extend_info): "*unnamed*");
+ extend_info_describe(conn->cpath_layer->extend_info):
+ "*unnamed*");
/* send an end down the circuit */
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
/* un-mark it as ending, since we're going to reuse it */
@@ -534,15 +627,16 @@ connection_ap_expire_beginning(void)
circ->timestamp_dirty -= options->MaxCircuitDirtiness;
/* give our stream another 'cutoff' seconds to try */
conn->_base.timestamp_lastread += cutoff;
- if (conn->num_socks_retries < 250) /* avoid overflow */
- conn->num_socks_retries++;
+ if (entry_conn->num_socks_retries < 250) /* avoid overflow */
+ entry_conn->num_socks_retries++;
/* move it back into 'pending' state, and try to attach. */
- if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ),
+ if (connection_ap_detach_retriable(entry_conn, TO_ORIGIN_CIRCUIT(circ),
END_STREAM_REASON_TIMEOUT)<0) {
- if (!conn->_base.marked_for_close)
- connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
+ if (!base_conn->marked_for_close)
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_CANT_ATTACH);
}
- } SMARTLIST_FOREACH_END(conn);
+ } SMARTLIST_FOREACH_END(base_conn);
}
/** Tell any AP streams that are waiting for a new circuit to try again,
@@ -551,7 +645,7 @@ connection_ap_expire_beginning(void)
void
connection_ap_attach_pending(void)
{
- edge_connection_t *edge_conn;
+ entry_connection_t *entry_conn;
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
@@ -559,10 +653,10 @@ connection_ap_attach_pending(void)
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (connection_ap_handshake_attach_circuit(edge_conn) < 0) {
- if (!edge_conn->_base.marked_for_close)
- connection_mark_unattached_ap(edge_conn,
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (connection_ap_handshake_attach_circuit(entry_conn) < 0) {
+ if (!conn->marked_for_close)
+ connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_CANT_ATTACH);
}
});
@@ -577,7 +671,7 @@ void
connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state)
{
- edge_connection_t *edge_conn;
+ entry_connection_t *entry_conn;
char digest[DIGEST_LEN];
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -585,27 +679,27 @@ connection_ap_fail_onehop(const char *failed_digest,
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (!edge_conn->want_onehop)
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (!entry_conn->want_onehop)
continue;
- if (hexdigest_to_digest(edge_conn->chosen_exit_name, digest) < 0 ||
+ if (hexdigest_to_digest(entry_conn->chosen_exit_name, digest) < 0 ||
tor_memneq(digest, failed_digest, DIGEST_LEN))
continue;
if (tor_digest_is_zero(digest)) {
/* we don't know the digest; have to compare addr:port */
tor_addr_t addr;
if (!build_state || !build_state->chosen_exit ||
- !edge_conn->socks_request || !edge_conn->socks_request->address)
+ !entry_conn->socks_request || !entry_conn->socks_request->address)
continue;
- if (tor_addr_from_str(&addr, edge_conn->socks_request->address)<0 ||
+ if (tor_addr_parse(&addr, entry_conn->socks_request->address)<0 ||
!tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
- build_state->chosen_exit->port != edge_conn->socks_request->port)
+ build_state->chosen_exit->port != entry_conn->socks_request->port)
continue;
}
log_info(LD_APP, "Closing one-hop stream to '%s/%s' because the OR conn "
- "just failed.", edge_conn->chosen_exit_name,
- edge_conn->socks_request->address);
- connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_TIMEOUT);
+ "just failed.", entry_conn->chosen_exit_name,
+ entry_conn->socks_request->address);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
} SMARTLIST_FOREACH_END(conn);
}
@@ -616,8 +710,8 @@ connection_ap_fail_onehop(const char *failed_digest,
void
circuit_discard_optional_exit_enclaves(extend_info_t *info)
{
- edge_connection_t *edge_conn;
- routerinfo_t *r1, *r2;
+ entry_connection_t *entry_conn;
+ const node_t *r1, *r2;
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -625,32 +719,32 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (!edge_conn->chosen_exit_optional &&
- !edge_conn->chosen_exit_retries)
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (!entry_conn->chosen_exit_optional &&
+ !entry_conn->chosen_exit_retries)
continue;
- r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
- r2 = router_get_by_digest(info->identity_digest);
+ r1 = node_get_by_nickname(entry_conn->chosen_exit_name, 0);
+ r2 = node_get_by_id(info->identity_digest);
if (!r1 || !r2 || r1 != r2)
continue;
- tor_assert(edge_conn->socks_request);
- if (edge_conn->chosen_exit_optional) {
+ tor_assert(entry_conn->socks_request);
+ if (entry_conn->chosen_exit_optional) {
log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.",
- safe_str_client(edge_conn->chosen_exit_name),
- escaped_safe_str_client(edge_conn->socks_request->address));
- edge_conn->chosen_exit_optional = 0;
- tor_free(edge_conn->chosen_exit_name); /* clears it */
+ safe_str_client(entry_conn->chosen_exit_name),
+ escaped_safe_str_client(entry_conn->socks_request->address));
+ entry_conn->chosen_exit_optional = 0;
+ tor_free(entry_conn->chosen_exit_name); /* clears it */
/* if this port is dangerous, warn or reject it now that we don't
* think it'll be using an enclave. */
- consider_plaintext_ports(edge_conn, edge_conn->socks_request->port);
+ consider_plaintext_ports(entry_conn, entry_conn->socks_request->port);
}
- if (edge_conn->chosen_exit_retries) {
- if (--edge_conn->chosen_exit_retries == 0) { /* give up! */
- clear_trackexithost_mappings(edge_conn->chosen_exit_name);
- tor_free(edge_conn->chosen_exit_name); /* clears it */
+ if (entry_conn->chosen_exit_retries) {
+ if (--entry_conn->chosen_exit_retries == 0) { /* give up! */
+ clear_trackexithost_mappings(entry_conn->chosen_exit_name);
+ tor_free(entry_conn->chosen_exit_name); /* clears it */
/* if this port is dangerous, warn or reject it now that we don't
* think it'll be using an enclave. */
- consider_plaintext_ports(edge_conn, edge_conn->socks_request->port);
+ consider_plaintext_ports(entry_conn, entry_conn->socks_request->port);
}
}
} SMARTLIST_FOREACH_END(conn);
@@ -664,20 +758,27 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
* Returns -1 on err, 1 on success, 0 on not-yet-sure.
*/
int
-connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ,
+connection_ap_detach_retriable(entry_connection_t *conn,
+ origin_circuit_t *circ,
int reason)
{
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE, reason);
- conn->_base.timestamp_lastread = time(NULL);
+ ENTRY_TO_CONN(conn)->timestamp_lastread = time(NULL);
+
+ if (conn->pending_optimistic_data) {
+ generic_buffer_set_to_copy(&conn->sending_optimistic_data,
+ conn->pending_optimistic_data);
+ }
+
if (!get_options()->LeaveStreamsUnattached || conn->use_begindir) {
/* If we're attaching streams ourself, or if this connection is
* a tunneled directory connection, then just attach it. */
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
- circuit_detach_stream(TO_CIRCUIT(circ),conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
return connection_ap_handshake_attach_circuit(conn);
} else {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
- circuit_detach_stream(TO_CIRCUIT(circ),conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
return 0;
}
}
@@ -825,7 +926,7 @@ clear_trackexithost_mappings(const char *exitname)
* host is unknown or no longer allowed, or for which the source address
* is no longer in trackexithosts. */
void
-addressmap_clear_excluded_trackexithosts(or_options_t *options)
+addressmap_clear_excluded_trackexithosts(const or_options_t *options)
{
const routerset_t *allow_nodes = options->ExitNodes;
const routerset_t *exclude_nodes = options->_ExcludeExitNodesUnion;
@@ -841,9 +942,12 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
size_t len;
const char *target = ent->new_address, *dot;
char *nodename;
- routerinfo_t *ri; /* XXX023 Use node_t. */
+ const node_t *node;
- if (strcmpend(target, ".exit")) {
+ if (!target) {
+ /* DNS resolving in progress */
+ continue;
+ } else if (strcmpend(target, ".exit")) {
/* Not a .exit mapping */
continue;
} else if (ent->source != ADDRMAPSRC_TRACKEXIT) {
@@ -854,15 +958,15 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
if (len < 6)
continue; /* malformed. */
dot = target + len - 6; /* dot now points to just before .exit */
- while(dot > target && *dot != '.')
- dot--;
+ while (dot > target && *dot != '.')
+ dot--;
if (*dot == '.') dot++;
nodename = tor_strndup(dot, len-5-(dot-target));;
- ri = router_get_by_nickname(nodename, 0);
+ node = node_get_by_nickname(nodename, 0);
tor_free(nodename);
- if (!ri ||
- (allow_nodes && !routerset_contains_router(allow_nodes, ri)) ||
- routerset_contains_router(exclude_nodes, ri) ||
+ if (!node ||
+ (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||
+ routerset_contains_node(exclude_nodes, node) ||
!hostname_in_track_host_exits(options, address)) {
/* We don't know this one, or we want to be rid of it. */
addressmap_ent_remove(address, ent);
@@ -876,7 +980,7 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
* no longer allowed by AutomapHostsOnResolve, or for which the
* target address is no longer in the virtual network. */
void
-addressmap_clear_invalid_automaps(or_options_t *options)
+addressmap_clear_invalid_automaps(const or_options_t *options)
{
int clear_all = !options->AutomapHostsOnResolve;
const smartlist_t *suffixes = options->AutomapHostsSuffixes;
@@ -1323,7 +1427,6 @@ static char *
addressmap_get_virtual_address(int type)
{
char buf[64];
- struct in_addr in;
tor_assert(addressmap);
if (type == RESOLVED_TYPE_HOSTNAME) {
@@ -1337,6 +1440,7 @@ addressmap_get_virtual_address(int type)
} else if (type == RESOLVED_TYPE_IPV4) {
// This is an imperfect estimate of how many addresses are available, but
// that's ok.
+ struct in_addr in;
uint32_t available = 1u << (32-virtual_addr_netmask_bits);
while (available) {
/* Don't hand out any .0 or .255 address. */
@@ -1528,9 +1632,9 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
/** Check if <b>conn</b> is using a dangerous port. Then warn and/or
* reject depending on our config options. */
static int
-consider_plaintext_ports(edge_connection_t *conn, uint16_t port)
+consider_plaintext_ports(entry_connection_t *conn, uint16_t port)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int reject = smartlist_string_num_isin(options->RejectPlaintextPorts, port);
if (smartlist_string_num_isin(options->WarnPlaintextPorts, port)) {
@@ -1563,14 +1667,14 @@ consider_plaintext_ports(edge_connection_t *conn, uint16_t port)
* documentation for arguments and return value.
*/
int
-connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
+connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->LeaveStreamsUnattached) {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
return 0;
}
return connection_ap_handshake_rewrite_and_attach(conn, circ, cpath);
@@ -1592,13 +1696,13 @@ connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
* <b>cpath</b> is NULL.
*/
int
-connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
+connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
struct in_addr addr_tmp;
/* We set this to true if this is an address we should automatically
* remap to a local address in VirtualAddrNetwork */
@@ -1609,6 +1713,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
address, and we remap it to one because of an entry in the addressmap. */
int remapped_to_exit = 0;
time_t now = time(NULL);
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_strlower(socks->address); /* normalize it */
strlcpy(orig_address, socks->address, sizeof(orig_address));
@@ -1616,6 +1721,9 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
safe_str_client(socks->address),
socks->port);
+ if (! conn->original_dest_address)
+ conn->original_dest_address = tor_strdup(conn->socks_request->address);
+
if (socks->command == SOCKS_COMMAND_RESOLVE &&
!tor_inet_aton(socks->address, &addr_tmp) &&
options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) {
@@ -1661,7 +1769,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* Don't let people try to do a reverse lookup on 10.0.0.1. */
tor_addr_t addr;
int ok;
- ok = tor_addr_parse_reverse_lookup_name(
+ ok = tor_addr_parse_PTR_name(
&addr, socks->address, AF_UNSPEC, 1);
if (ok == 1 && tor_addr_is_internal(&addr, 0)) {
connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR,
@@ -1721,15 +1829,14 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* If StrictNodes is not set, then .exit overrides ExcludeNodes. */
routerset_t *excludeset = options->StrictNodes ?
options->_ExcludeExitNodesUnion : options->ExcludeExitNodes;
- /*XXX023 make this a node_t. */
- routerinfo_t *router;
+ const node_t *node;
tor_assert(!automap);
if (s) {
/* The address was of the form "(stuff).(name).exit */
if (s[1] != '\0') {
conn->chosen_exit_name = tor_strdup(s+1);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ node = node_get_by_nickname(conn->chosen_exit_name, 1);
if (remapped_to_exit) /* 5 tries before it expires the addressmap */
conn->chosen_exit_retries = TRACKHOSTEXITS_RETRIES;
*s = 0;
@@ -1744,15 +1851,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
}
} else {
/* It looks like they just asked for "foo.exit". */
+
conn->chosen_exit_name = tor_strdup(socks->address);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (router) {
+ node = node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (node) {
*socks->address = 0;
- strlcpy(socks->address, router->address, sizeof(socks->address));
+ node_get_address_string(node, socks->address, sizeof(socks->address));
}
}
/* Now make sure that the chosen exit exists... */
- if (!router) {
+ if (!node) {
log_warn(LD_APP,
"Unrecognized relay in exit address '%s.exit'. Refusing.",
safe_str_client(socks->address));
@@ -1760,7 +1868,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
/* ...and make sure that it isn't excluded. */
- if (routerset_contains_router(excludeset, router)) {
+ if (routerset_contains_node(excludeset, node)) {
log_warn(LD_APP,
"Excluded relay in exit address '%s.exit'. Refusing.",
safe_str_client(socks->address));
@@ -1813,7 +1921,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
if (options->ClientRejectInternalAddresses &&
!conn->use_begindir && !conn->chosen_exit_name && !circ) {
tor_addr_t addr;
- if (tor_addr_from_str(&addr, socks->address) >= 0 &&
+ if (tor_addr_parse(&addr, socks->address) >= 0 &&
tor_addr_is_internal(&addr, 0)) {
/* If this is an explicit private address with no chosen exit node,
* then we really don't want to try to connect to it. That's
@@ -1835,17 +1943,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */
- routerinfo_t *r =
+ const node_t *r =
router_find_exact_exit_enclave(socks->address, socks->port);
if (r) {
log_info(LD_APP,
"Redirecting address %s to exit at enclave router %s",
- safe_str_client(socks->address),
- router_describe(r));
+ safe_str_client(socks->address), node_describe(r));
/* use the hex digest, not nickname, in case there are two
routers with this nickname */
conn->chosen_exit_name =
- tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
+ tor_strdup(hex_str(r->identity, DIGEST_LEN));
conn->chosen_exit_optional = 1;
}
}
@@ -1865,12 +1972,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
} else {
tor_fragile_assert();
}
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if ((circ && connection_ap_handshake_attach_chosen_circuit(
conn, circ, cpath) < 0) ||
(!circ &&
connection_ap_handshake_attach_circuit(conn) < 0)) {
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
@@ -1880,6 +1987,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
rend_cache_entry_t *entry;
int r;
rend_service_authorization_t *client_auth;
+ rend_data_t *rend_data;
tor_assert(!automap);
if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
/* if it's a resolve request, fail it right now, rather than
@@ -1901,16 +2009,17 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
- conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
- strlcpy(conn->rend_data->onion_address, socks->address,
- sizeof(conn->rend_data->onion_address));
+ ENTRY_TO_EDGE_CONN(conn)->rend_data = rend_data =
+ tor_malloc_zero(sizeof(rend_data_t));
+ strlcpy(rend_data->onion_address, socks->address,
+ sizeof(rend_data->onion_address));
log_info(LD_REND,"Got a hidden service request for ID '%s'",
- safe_str_client(conn->rend_data->onion_address));
+ safe_str_client(rend_data->onion_address));
/* see if we already have it cached */
- r = rend_cache_lookup_entry(conn->rend_data->onion_address, -1, &entry);
+ r = rend_cache_lookup_entry(rend_data->onion_address, -1, &entry);
if (r<0) {
log_warn(LD_BUG,"Invalid service name '%s'",
- safe_str_client(conn->rend_data->onion_address));
+ safe_str_client(rend_data->onion_address));
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
}
@@ -1921,24 +2030,24 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* Look up if we have client authorization for it. */
client_auth = rend_client_lookup_service_authorization(
- conn->rend_data->onion_address);
+ rend_data->onion_address);
if (client_auth) {
log_info(LD_REND, "Using previously configured client authorization "
"for hidden service request.");
- memcpy(conn->rend_data->descriptor_cookie,
+ memcpy(rend_data->descriptor_cookie,
client_auth->descriptor_cookie, REND_DESC_COOKIE_LEN);
- conn->rend_data->auth_type = client_auth->auth_type;
+ rend_data->auth_type = client_auth->auth_type;
}
if (r==0) {
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
- safe_str_client(conn->rend_data->onion_address));
- rend_client_refetch_v2_renddesc(conn->rend_data);
+ safe_str_client(rend_data->onion_address));
+ rend_client_refetch_v2_renddesc(rend_data);
} else { /* r > 0 */
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
log_info(LD_REND, "Descriptor is here. Great.");
if (connection_ap_handshake_attach_circuit(conn) < 0) {
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
@@ -1960,10 +2069,10 @@ get_pf_socket(void)
#ifdef OPENBSD
/* only works on OpenBSD */
- pf = open("/dev/pf", O_RDONLY);
+ pf = tor_open_cloexec("/dev/pf", O_RDONLY, 0);
#else
/* works on NetBSD and FreeBSD */
- pf = open("/dev/pf", O_RDWR);
+ pf = tor_open_cloexec("/dev/pf", O_RDWR, 0);
#endif
if (pf < 0) {
@@ -1984,7 +2093,7 @@ get_pf_socket(void)
* else return 0.
*/
static int
-connection_ap_get_original_destination(edge_connection_t *conn,
+connection_ap_get_original_destination(entry_connection_t *conn,
socks_request_t *req)
{
#ifdef TRANS_NETFILTER
@@ -1993,9 +2102,9 @@ connection_ap_get_original_destination(edge_connection_t *conn,
socklen_t orig_dst_len = sizeof(orig_dst);
tor_addr_t addr;
- if (getsockopt(conn->_base.s, SOL_IP, SO_ORIGINAL_DST,
+ if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
- int e = tor_socket_errno(conn->_base.s);
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
return -1;
}
@@ -2012,9 +2121,9 @@ connection_ap_get_original_destination(edge_connection_t *conn,
tor_addr_t addr;
int pf = -1;
- if (getsockname(conn->_base.s, (struct sockaddr*)&proxy_addr,
+ if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&proxy_addr,
&proxy_addr_len) < 0) {
- int e = tor_socket_errno(conn->_base.s);
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
log_warn(LD_NET, "getsockname() to determine transocks destination "
"failed: %s", tor_socket_strerror(e));
return -1;
@@ -2026,16 +2135,16 @@ connection_ap_get_original_destination(edge_connection_t *conn,
if (proxy_sa->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)proxy_sa;
pnl.af = AF_INET;
- pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&conn->_base.addr);
- pnl.sport = htons(conn->_base.port);
+ pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&ENTRY_TO_CONN(conn)->addr);
+ pnl.sport = htons(ENTRY_TO_CONN(conn)->port);
pnl.daddr.v4.s_addr = sin->sin_addr.s_addr;
pnl.dport = sin->sin_port;
} else if (proxy_sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)proxy_sa;
pnl.af = AF_INET6;
- memcpy(&pnl.saddr.v6, tor_addr_to_in6(&conn->_base.addr),
+ memcpy(&pnl.saddr.v6, tor_addr_to_in6(&ENTRY_TO_CONN(conn)->addr),
sizeof(struct in6_addr));
- pnl.sport = htons(conn->_base.port);
+ pnl.sport = htons(ENTRY_TO_CONN(conn)->port);
memcpy(&pnl.daddr.v6, &sin6->sin6_addr, sizeof(struct in6_addr));
pnl.dport = sin6->sin6_port;
} else {
@@ -2086,38 +2195,43 @@ connection_ap_get_original_destination(edge_connection_t *conn,
* else return 0.
*/
static int
-connection_ap_handshake_process_socks(edge_connection_t *conn)
+connection_ap_handshake_process_socks(entry_connection_t *conn)
{
socks_request_t *socks;
int sockshere;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ int had_reply = 0;
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- tor_assert(conn->_base.state == AP_CONN_STATE_SOCKS_WAIT);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_SOCKS_WAIT);
tor_assert(conn->socks_request);
socks = conn->socks_request;
log_debug(LD_APP,"entered.");
- sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks,
- options->TestSocks, options->SafeSocks);
+ IF_HAS_BUFFEREVENT(base_conn, {
+ struct evbuffer *input = bufferevent_get_input(base_conn->bufev);
+ sockshere = fetch_from_evbuffer_socks(input, socks,
+ options->TestSocks, options->SafeSocks);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ sockshere = fetch_from_buf_socks(base_conn->inbuf, socks,
+ options->TestSocks, options->SafeSocks);
+ };
+
+ if (socks->replylen) {
+ had_reply = 1;
+ connection_write_to_buf((const char*)socks->reply, socks->replylen,
+ base_conn);
+ socks->replylen = 0;
+ }
+
if (sockshere == 0) {
- if (socks->replylen) {
- connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn));
- /* zero it out so we can do another round of negotiation */
- socks->replylen = 0;
- } else {
- log_debug(LD_APP,"socks handshake not all here yet.");
- }
+ log_debug(LD_APP,"socks handshake not all here yet.");
return 0;
} else if (sockshere == -1) {
- if (socks->replylen) { /* we should send reply back */
- log_debug(LD_APP,"reply is already set for us. Using it.");
- connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
- END_STREAM_REASON_SOCKSPROTOCOL);
-
- } else {
+ if (!had_reply) {
log_warn(LD_APP,"Fetching socks handshake failed. Closing.");
connection_ap_handshake_socks_reply(conn, NULL, 0,
END_STREAM_REASON_SOCKSPROTOCOL);
@@ -2144,12 +2258,11 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
* for close), else return 0.
*/
int
-connection_ap_process_transparent(edge_connection_t *conn)
+connection_ap_process_transparent(entry_connection_t *conn)
{
socks_request_t *socks;
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
socks = conn->socks_request;
@@ -2185,7 +2298,7 @@ connection_ap_process_transparent(edge_connection_t *conn)
* for close), else return 0.
*/
static int
-connection_ap_process_natd(edge_connection_t *conn)
+connection_ap_process_natd(entry_connection_t *conn)
{
char tmp_buf[36], *tbuf, *daddr;
size_t tlen = 30;
@@ -2193,8 +2306,7 @@ connection_ap_process_natd(edge_connection_t *conn)
socks_request_t *socks;
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- tor_assert(conn->_base.state == AP_CONN_STATE_NATD_WAIT);
+ tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_NATD_WAIT);
tor_assert(conn->socks_request);
socks = conn->socks_request;
@@ -2202,7 +2314,7 @@ connection_ap_process_natd(edge_connection_t *conn)
/* look for LF-terminated "[DEST ip_addr port]"
* where ip_addr is a dotted-quad and port is in string form */
- err = fetch_from_buf_line(conn->_base.inbuf, tmp_buf, &tlen);
+ err = connection_fetch_from_buf_line(ENTRY_TO_CONN(conn), tmp_buf, &tlen);
if (err == 0)
return 0;
if (err < 0) {
@@ -2246,7 +2358,7 @@ connection_ap_process_natd(edge_connection_t *conn)
control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT;
return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
}
@@ -2276,28 +2388,46 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ)
return test_stream_id;
}
+/** Return true iff <b>conn</b> is linked to a circuit and configured to use
+ * an exit that supports optimistic data. */
+static int
+connection_ap_supports_optimistic_data(const entry_connection_t *conn)
+{
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ /* We can only send optimistic data if we're connected to an open
+ general circuit. */
+ if (edge_conn->on_circuit == NULL ||
+ edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
+ return 0;
+
+ return conn->may_use_optimistic_data;
+}
+
/** Write a relay begin cell, using destaddr and destport from ap_conn's
* socks_request field, and send it down circ.
*
* If ap_conn is broken, mark it for close and return -1. Else return 0.
*/
int
-connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
+connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
{
char payload[CELL_PAYLOAD_SIZE];
int payload_len;
int begin_type;
origin_circuit_t *circ;
- tor_assert(ap_conn->on_circuit);
- circ = TO_ORIGIN_CIRCUIT(ap_conn->on_circuit);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ connection_t *base_conn = TO_CONN(edge_conn);
+ tor_assert(edge_conn->on_circuit);
+ circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit);
- tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
- tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
tor_assert(SOCKS_COMMAND_IS_CONNECT(ap_conn->socks_request->command));
- ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
- if (ap_conn->stream_id==0) {
+ edge_conn->stream_id = get_unique_stream_id_by_circ(circ);
+ if (edge_conn->stream_id==0) {
/* XXXX023 Instead of closing this stream, we should make it get
* retried on another circuit. */
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
@@ -2315,8 +2445,10 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
ap_conn->socks_request->port);
payload_len = (int)strlen(payload)+1;
- log_debug(LD_APP,
- "Sending relay cell to begin stream %d.", ap_conn->stream_id);
+ log_info(LD_APP,
+ "Sending relay cell %d to begin stream %d.",
+ (int)ap_conn->use_begindir,
+ edge_conn->stream_id);
begin_type = ap_conn->use_begindir ?
RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN;
@@ -2324,17 +2456,31 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
tor_assert(circ->build_state->onehop_tunnel == 0);
}
- if (connection_edge_send_command(ap_conn, begin_type,
+ if (connection_edge_send_command(edge_conn, begin_type,
begin_type == RELAY_COMMAND_BEGIN ? payload : NULL,
begin_type == RELAY_COMMAND_BEGIN ? payload_len : 0) < 0)
return -1; /* circuit is closed, don't continue */
- ap_conn->package_window = STREAMWINDOW_START;
- ap_conn->deliver_window = STREAMWINDOW_START;
- ap_conn->_base.state = AP_CONN_STATE_CONNECT_WAIT;
+ edge_conn->package_window = STREAMWINDOW_START;
+ edge_conn->deliver_window = STREAMWINDOW_START;
+ base_conn->state = AP_CONN_STATE_CONNECT_WAIT;
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
- ap_conn->_base.s, circ->_base.n_circ_id);
+ base_conn->s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0);
+
+ /* If there's queued-up data, send it now */
+ if ((connection_get_inbuf_len(base_conn) ||
+ ap_conn->sending_optimistic_data) &&
+ connection_ap_supports_optimistic_data(ap_conn)) {
+ log_info(LD_APP, "Sending up to %ld + %ld bytes of queued-up data",
+ (long)connection_get_inbuf_len(base_conn),
+ ap_conn->sending_optimistic_data ?
+ (long)generic_buffer_len(ap_conn->sending_optimistic_data) : 0);
+ if (connection_edge_package_raw_inbuf(edge_conn, 1, NULL) < 0) {
+ connection_mark_for_close(base_conn);
+ }
+ }
+
return 0;
}
@@ -2344,25 +2490,27 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
* If ap_conn is broken, mark it for close and return -1. Else return 0.
*/
int
-connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
+connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
{
int payload_len, command;
const char *string_addr;
char inaddr_buf[REVERSE_LOOKUP_NAME_BUF_LEN];
origin_circuit_t *circ;
- tor_assert(ap_conn->on_circuit);
- circ = TO_ORIGIN_CIRCUIT(ap_conn->on_circuit);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ connection_t *base_conn = TO_CONN(edge_conn);
+ tor_assert(edge_conn->on_circuit);
+ circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit);
- tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
- tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
command = ap_conn->socks_request->command;
tor_assert(SOCKS_COMMAND_IS_RESOLVE(command));
- ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
- if (ap_conn->stream_id==0) {
+ edge_conn->stream_id = get_unique_stream_id_by_circ(circ);
+ if (edge_conn->stream_id==0) {
/* XXXX023 Instead of closing this stream, we should make it get
* retried on another circuit. */
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
@@ -2385,7 +2533,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
/* We're doing a reverse lookup. The input could be an IP address, or
* could be an .in-addr.arpa or .ip6.arpa address */
- r = tor_addr_parse_reverse_lookup_name(&addr, a, AF_INET, 1);
+ r = tor_addr_parse_PTR_name(&addr, a, AF_INET, 1);
if (r <= 0) {
log_warn(LD_APP, "Rejecting ill-formed reverse lookup of %s",
safe_str_client(a));
@@ -2393,7 +2541,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
return -1;
}
- r = tor_addr_to_reverse_lookup_name(inaddr_buf, sizeof(inaddr_buf), &addr);
+ r = tor_addr_to_PTR_name(inaddr_buf, sizeof(inaddr_buf), &addr);
if (r < 0) {
log_warn(LD_BUG, "Couldn't generate reverse lookup hostname of %s",
safe_str_client(a));
@@ -2407,18 +2555,18 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
}
log_debug(LD_APP,
- "Sending relay cell to begin stream %d.", ap_conn->stream_id);
+ "Sending relay cell to begin stream %d.", edge_conn->stream_id);
- if (connection_edge_send_command(ap_conn,
+ if (connection_edge_send_command(edge_conn,
RELAY_COMMAND_RESOLVE,
string_addr, payload_len) < 0)
return -1; /* circuit is closed, don't continue */
- tor_free(ap_conn->_base.address); /* Maybe already set by dnsserv. */
- ap_conn->_base.address = tor_strdup("(Tor_internal)");
- ap_conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
+ tor_free(base_conn->address); /* Maybe already set by dnsserv. */
+ base_conn->address = tor_strdup("(Tor_internal)");
+ base_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
- ap_conn->_base.s, circ->_base.n_circ_id);
+ base_conn->s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0);
return 0;
@@ -2429,19 +2577,25 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
* and call connection_ap_handshake_attach_circuit(conn) on it.
*
* Return the other end of the linked connection pair, or -1 if error.
+ * DOCDOC partner.
*/
-edge_connection_t *
-connection_ap_make_link(char *address, uint16_t port,
- const char *digest, int use_begindir, int want_onehop)
+entry_connection_t *
+connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
+ const char *digest,
+ int session_group, int isolation_flags,
+ int use_begindir, int want_onehop)
{
- edge_connection_t *conn;
+ entry_connection_t *conn;
+ connection_t *base_conn;
log_info(LD_APP,"Making internal %s tunnel to %s:%d ...",
want_onehop ? "direct" : "anonymized",
safe_str_client(address), port);
- conn = edge_connection_new(CONN_TYPE_AP, AF_INET);
- conn->_base.linked = 1; /* so that we can add it safely below. */
+ conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ base_conn = ENTRY_TO_CONN(conn);
+ base_conn->linked = 1; /* so that we can add it safely below. */
/* populate conn->socks_request */
@@ -2462,22 +2616,30 @@ connection_ap_make_link(char *address, uint16_t port,
digest, DIGEST_LEN);
}
- conn->_base.address = tor_strdup("(Tor_internal)");
- tor_addr_make_unspec(&conn->_base.addr);
- conn->_base.port = 0;
+ /* Populate isolation fields. */
+ conn->socks_request->listener_type = CONN_TYPE_DIR_LISTENER;
+ conn->original_dest_address = tor_strdup(address);
+ conn->session_group = session_group;
+ conn->isolation_flags = isolation_flags;
- if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */
- connection_free(TO_CONN(conn));
+ base_conn->address = tor_strdup("(Tor_internal)");
+ tor_addr_make_unspec(&base_conn->addr);
+ base_conn->port = 0;
+
+ connection_link_connections(partner, base_conn);
+
+ if (connection_add(base_conn) < 0) { /* no space, forget it */
+ connection_free(base_conn);
return NULL;
}
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
/* attaching to a dirty circuit is fine */
if (connection_ap_handshake_attach_circuit(conn) < 0) {
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return NULL;
}
@@ -2490,7 +2652,7 @@ connection_ap_make_link(char *address, uint16_t port,
* or resolve error. Takes the same arguments as does
* connection_ap_handshake_socks_resolved(). */
static void
-tell_controller_about_resolved_result(edge_connection_t *conn,
+tell_controller_about_resolved_result(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
@@ -2502,13 +2664,11 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
answer_type == RESOLVED_TYPE_HOSTNAME)) {
return; /* we already told the controller. */
} else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
- struct in_addr in;
- char buf[INET_NTOA_BUF_LEN];
- in.s_addr = get_uint32(answer);
- tor_inet_ntoa(&in, buf, sizeof(buf));
+ char *cp = tor_dup_ip(get_uint32(answer));
control_event_address_mapped(conn->socks_request->address,
- buf, expires, NULL);
- } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len <256) {
+ cp, expires, NULL);
+ tor_free(cp);
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
char *cp = tor_strndup(answer, answer_len);
control_event_address_mapped(conn->socks_request->address,
cp, expires, NULL);
@@ -2531,7 +2691,7 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
/* XXXX023 the use of the ttl and expires fields is nutty. Let's make this
* interface and those that use it less ugly. */
void
-connection_ap_handshake_socks_resolved(edge_connection_t *conn,
+connection_ap_handshake_socks_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const uint8_t *answer,
@@ -2556,7 +2716,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
}
}
- if (conn->is_dns_request) {
+ if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request) {
if (conn->dns_server_request) {
/* We had a request on our DNS port: answer it. */
dnsserv_resolved(conn, answer_type, answer_len, (char*)answer, ttl);
@@ -2636,7 +2796,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
* be 0 or REASON_DONE. Send endreason to the controller, if appropriate.
*/
void
-connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
+connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen, int endreason)
{
char buf[256];
@@ -2655,7 +2815,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
return;
}
if (replylen) { /* we already have a reply in mind */
- connection_write_to_buf(reply, replylen, TO_CONN(conn));
+ connection_write_to_buf(reply, replylen, ENTRY_TO_CONN(conn));
conn->socks_request->has_finished = 1;
return;
}
@@ -2663,7 +2823,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
memset(buf,0,SOCKS4_NETWORK_LEN);
buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT);
/* leave version, destport, destip zero */
- connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, TO_CONN(conn));
+ connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, ENTRY_TO_CONN(conn));
} else if (conn->socks_request->socks_version == 5) {
buf[0] = 5; /* version 5 */
buf[1] = (char)status;
@@ -2671,7 +2831,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
buf[3] = 1; /* ipv4 addr */
memset(buf+4,0,6); /* Set external addr/port to 0.
The spec doesn't seem to say what to do here. -RD */
- connection_write_to_buf(buf,10,TO_CONN(conn));
+ connection_write_to_buf(buf,10,ENTRY_TO_CONN(conn));
}
/* If socks_version isn't 4 or 5, don't send anything.
* This can happen in the case of AP bridges. */
@@ -2705,7 +2865,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
char *address=NULL;
uint16_t port;
or_circuit_t *or_circ = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
assert_circuit_ok(circ);
if (!CIRCUIT_IS_ORIGIN(circ))
@@ -2737,9 +2897,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
END_STREAM_REASON_TORPROTOCOL, NULL);
return 0;
}
- if (parse_addr_port(LOG_PROTOCOL_WARN,
- (char*)(cell->payload+RELAY_HEADER_SIZE),
- &address,NULL,&port)<0) {
+ if (tor_addr_port_split(LOG_PROTOCOL_WARN,
+ (char*)(cell->payload+RELAY_HEADER_SIZE),
+ &address,&port)<0) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Unable to parse addr:port in relay begin cell. Closing.");
relay_send_end_cell_from_edge(rh.stream_id, circ,
@@ -2988,12 +3148,13 @@ connection_exit_connect(edge_connection_t *edge_conn)
}
conn->state = EXIT_CONN_STATE_OPEN;
- if (connection_wants_to_flush(conn)) {
+ if (connection_get_outbuf_len(conn)) {
/* in case there are any queued data cells */
log_warn(LD_BUG,"newly connected conn had data waiting!");
// connection_start_writing(conn);
}
- connection_watch_events(conn, READ_EVENT);
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_watch_events(conn, READ_EVENT);
/* also, deliver a 'connected' cell back through the circuit. */
if (connection_edge_is_rendezvous_stream(edge_conn)) {
@@ -3103,12 +3264,11 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
* resolved.)
*/
int
-connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
+connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
tor_assert(exit);
@@ -3116,10 +3276,10 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
* make sure the exit node of the existing circuit matches exactly.
*/
if (conn->chosen_exit_name) {
- routerinfo_t *chosen_exit =
- router_get_by_nickname(conn->chosen_exit_name, 1);
- if (!chosen_exit || tor_memneq(chosen_exit->cache_info.identity_digest,
- exit->cache_info.identity_digest, DIGEST_LEN)) {
+ const node_t *chosen_exit =
+ node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (!chosen_exit || tor_memneq(chosen_exit->identity,
+ exit->identity, DIGEST_LEN)) {
/* doesn't match */
// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
// conn->chosen_exit_name, exit->nickname);
@@ -3130,12 +3290,13 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir) {
struct in_addr in;
- uint32_t addr = 0;
+ tor_addr_t addr, *addrp = NULL;
addr_policy_result_t r;
- if (tor_inet_aton(conn->socks_request->address, &in))
- addr = ntohl(in.s_addr);
- r = compare_addr_to_addr_policy(addr, conn->socks_request->port,
- exit->exit_policy);
+ if (tor_inet_aton(conn->socks_request->address, &in)) {
+ tor_addr_from_in(&addr, &in);
+ addrp = &addr;
+ }
+ r = compare_tor_addr_to_node_policy(addrp, conn->socks_request->port,exit);
if (r == ADDR_POLICY_REJECTED)
return 0; /* We know the address, and the exit policy rejects it. */
if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
@@ -3143,17 +3304,11 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
* addresses with this port. Since the user didn't ask for
* this node, err on the side of caution. */
} else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
- /* Can't support reverse lookups without eventdns. */
- if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR &&
- exit->has_old_dnsworkers)
- return 0;
-
/* Don't send DNS requests to non-exit servers by default. */
- if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy))
+ if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit))
return 0;
}
- if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) {
+ if (routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) {
/* Not a suitable exit. Refuse it. */
return 0;
}
@@ -3208,3 +3363,205 @@ parse_extended_hostname(char *address, int allowdotexit)
return BAD_HOSTNAME;
}
+/** Return true iff the (possibly NULL) <b>alen</b>-byte chunk of memory at
+ * <b>a</b> is equal to the (possibly NULL) <b>blen</b>-byte chunk of memory
+ * at <b>b</b>. */
+static int
+memeq_opt(const char *a, size_t alen, const char *b, size_t blen)
+{
+ if (a == NULL) {
+ return (b == NULL);
+ } else if (b == NULL) {
+ return 0;
+ } else if (alen != blen) {
+ return 0;
+ } else {
+ return tor_memeq(a, b, alen);
+ }
+}
+
+/**
+ * Return true iff none of the isolation flags and fields in <b>conn</b>
+ * should prevent it from being attached to <b>circ</b>.
+ */
+int
+connection_edge_compatible_with_circuit(const entry_connection_t *conn,
+ const origin_circuit_t *circ)
+{
+ const uint8_t iso = conn->isolation_flags;
+ const socks_request_t *sr = conn->socks_request;
+
+ /* If circ has never been used for an isolated connection, we can
+ * totally use it for this one. */
+ if (!circ->isolation_values_set)
+ return 1;
+
+ /* If circ has been used for connections having more than one value
+ * for some field f, it will have the corresponding bit set in
+ * isolation_flags_mixed. If isolation_flags_mixed has any bits
+ * in common with iso, then conn must be isolated from at least
+ * one stream that has been attached to circ. */
+ if ((iso & circ->isolation_flags_mixed) != 0) {
+ /* For at least one field where conn is isolated, the circuit
+ * already has mixed streams. */
+ return 0;
+ }
+
+ if (! conn->original_dest_address) {
+ log_warn(LD_BUG, "Reached connection_edge_compatible_with_circuit without "
+ "having set conn->original_dest_address");
+ ((entry_connection_t*)conn)->original_dest_address =
+ tor_strdup(conn->socks_request->address);
+ }
+
+ if ((iso & ISO_STREAM) &&
+ (circ->associated_isolated_stream_global_id !=
+ ENTRY_TO_CONN(conn)->global_identifier))
+ return 0;
+
+ if ((iso & ISO_DESTPORT) && conn->socks_request->port != circ->dest_port)
+ return 0;
+ if ((iso & ISO_DESTADDR) &&
+ strcasecmp(conn->original_dest_address, circ->dest_address))
+ return 0;
+ if ((iso & ISO_SOCKSAUTH) &&
+ (! memeq_opt(sr->username, sr->usernamelen,
+ circ->socks_username, circ->socks_username_len) ||
+ ! memeq_opt(sr->password, sr->passwordlen,
+ circ->socks_password, circ->socks_password_len)))
+ return 0;
+ if ((iso & ISO_CLIENTPROTO) &&
+ (conn->socks_request->listener_type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ return 0;
+ if ((iso & ISO_CLIENTADDR) &&
+ !tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr))
+ return 0;
+ if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group)
+ return 0;
+ if ((iso & ISO_NYM_EPOCH) && conn->nym_epoch != circ->nym_epoch)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * If <b>dry_run</b> is false, update <b>circ</b>'s isolation flags and fields
+ * to reflect having had <b>conn</b> attached to it, and return 0. Otherwise,
+ * if <b>dry_run</b> is true, then make no changes to <b>circ</b>, and return
+ * a bitfield of isolation flags that we would have to set in
+ * isolation_flags_mixed to add <b>conn</b> to <b>circ</b>, or -1 if
+ * <b>circ</b> has had no streams attached to it.
+ */
+int
+connection_edge_update_circuit_isolation(const entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run)
+{
+ const socks_request_t *sr = conn->socks_request;
+ if (! conn->original_dest_address) {
+ log_warn(LD_BUG, "Reached connection_update_circuit_isolation without "
+ "having set conn->original_dest_address");
+ ((entry_connection_t*)conn)->original_dest_address =
+ tor_strdup(conn->socks_request->address);
+ }
+
+ if (!circ->isolation_values_set) {
+ if (dry_run)
+ return -1;
+ circ->associated_isolated_stream_global_id =
+ ENTRY_TO_CONN(conn)->global_identifier;
+ circ->dest_port = conn->socks_request->port;
+ circ->dest_address = tor_strdup(conn->original_dest_address);
+ circ->client_proto_type = conn->socks_request->listener_type;
+ circ->client_proto_socksver = conn->socks_request->socks_version;
+ tor_addr_copy(&circ->client_addr, &ENTRY_TO_CONN(conn)->addr);
+ circ->session_group = conn->session_group;
+ circ->nym_epoch = conn->nym_epoch;
+ circ->socks_username = sr->username ?
+ tor_memdup(sr->username, sr->usernamelen) : NULL;
+ circ->socks_password = sr->password ?
+ tor_memdup(sr->password, sr->passwordlen) : NULL;
+ circ->socks_username_len = sr->usernamelen;
+ circ->socks_password_len = sr->passwordlen;
+
+ circ->isolation_values_set = 1;
+ return 0;
+ } else {
+ uint8_t mixed = 0;
+ if (conn->socks_request->port != circ->dest_port)
+ mixed |= ISO_DESTPORT;
+ if (strcasecmp(conn->original_dest_address, circ->dest_address))
+ mixed |= ISO_DESTADDR;
+ if (!memeq_opt(sr->username, sr->usernamelen,
+ circ->socks_username, circ->socks_username_len) ||
+ !memeq_opt(sr->password, sr->passwordlen,
+ circ->socks_password, circ->socks_password_len))
+ mixed |= ISO_SOCKSAUTH;
+ if ((conn->socks_request->listener_type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ mixed |= ISO_CLIENTPROTO;
+ if (!tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr))
+ mixed |= ISO_CLIENTADDR;
+ if (conn->session_group != circ->session_group)
+ mixed |= ISO_SESSIONGRP;
+ if (conn->nym_epoch != circ->nym_epoch)
+ mixed |= ISO_NYM_EPOCH;
+
+ if (dry_run)
+ return mixed;
+
+ if ((mixed & conn->isolation_flags) != 0) {
+ log_warn(LD_BUG, "Updating a circuit with seemingly incompatible "
+ "isolation flags.");
+ }
+ circ->isolation_flags_mixed |= mixed;
+ return 0;
+ }
+}
+
+/**
+ * Clear the isolation settings on <b>circ</b>.
+ *
+ * This only works on an open circuit that has never had a stream attached to
+ * it, and whose isolation settings are hypothetical. (We set hypothetical
+ * isolation settings on circuits as we're launching them, so that we
+ * know whether they can handle more streams or whether we need to launch
+ * even more circuits. Once the circuit is open, if it turns out that
+ * we no longer have any streams to attach to it, we clear the isolation flags
+ * and data so that other streams can have a chance.)
+ */
+void
+circuit_clear_isolation(origin_circuit_t *circ)
+{
+ if (circ->isolation_any_streams_attached) {
+ log_warn(LD_BUG, "Tried to clear the isolation status of a dirty circuit");
+ return;
+ }
+ if (TO_CIRCUIT(circ)->state != CIRCUIT_STATE_OPEN) {
+ log_warn(LD_BUG, "Tried to clear the isolation status of a non-open "
+ "circuit");
+ return;
+ }
+
+ circ->isolation_values_set = 0;
+ circ->isolation_flags_mixed = 0;
+ circ->associated_isolated_stream_global_id = 0;
+ circ->client_proto_type = 0;
+ circ->client_proto_socksver = 0;
+ circ->dest_port = 0;
+ tor_addr_make_unspec(&circ->client_addr);
+ tor_free(circ->dest_address);
+ circ->session_group = -1;
+ circ->nym_epoch = 0;
+ if (circ->socks_username) {
+ memset(circ->socks_username, 0x11, circ->socks_username_len);
+ tor_free(circ->socks_username);
+ }
+ if (circ->socks_password) {
+ memset(circ->socks_password, 0x05, circ->socks_password_len);
+ tor_free(circ->socks_password);
+ }
+ circ->socks_username_len = circ->socks_password_len = 0;
+}
+
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 8ba2fafd08..830667e601 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -15,7 +15,7 @@
#define connection_mark_unattached_ap(conn, endreason) \
_connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_)
-void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+void _connection_mark_unattached_ap(entry_connection_t *conn, int endreason,
int line, const char *file);
int connection_edge_reached_eof(edge_connection_t *conn);
int connection_edge_process_inbuf(edge_connection_t *conn,
@@ -27,16 +27,22 @@ int connection_edge_flushed_some(edge_connection_t *conn);
int connection_edge_finished_flushing(edge_connection_t *conn);
int connection_edge_finished_connecting(edge_connection_t *conn);
-int connection_ap_handshake_send_begin(edge_connection_t *ap_conn);
-int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn);
+void connection_ap_about_to_close(entry_connection_t *edge_conn);
+void connection_exit_about_to_close(edge_connection_t *edge_conn);
-edge_connection_t *connection_ap_make_link(char *address, uint16_t port,
+int connection_ap_handshake_send_begin(entry_connection_t *ap_conn);
+int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn);
+
+entry_connection_t *connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
const char *digest,
+ int session_group,
+ int isolation_flags,
int use_begindir, int want_onehop);
-void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
+void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen,
int endreason);
-void connection_ap_handshake_socks_resolved(edge_connection_t *conn,
+void connection_ap_handshake_socks_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const uint8_t *answer,
@@ -47,22 +53,23 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
void connection_exit_connect(edge_connection_t *conn);
int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
-int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit);
+int connection_ap_can_use_exit(const entry_connection_t *conn,
+ const node_t *exit);
void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
void connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state);
void circuit_discard_optional_exit_enclaves(extend_info_t *info);
-int connection_ap_detach_retriable(edge_connection_t *conn,
+int connection_ap_detach_retriable(entry_connection_t *conn,
origin_circuit_t *circ,
int reason);
-int connection_ap_process_transparent(edge_connection_t *conn);
+int connection_ap_process_transparent(entry_connection_t *conn);
int address_is_invalid_destination(const char *address, int client);
void addressmap_init(void);
-void addressmap_clear_excluded_trackexithosts(or_options_t *options);
-void addressmap_clear_invalid_automaps(or_options_t *options);
+void addressmap_clear_excluded_trackexithosts(const or_options_t *options);
+void addressmap_clear_invalid_automaps(const or_options_t *options);
void addressmap_clean(time_t now);
void addressmap_clear_configured(void);
void addressmap_clear_transient(void);
@@ -81,10 +88,10 @@ void client_dns_set_addressmap(const char *address, uint32_t val,
const char *addressmap_register_virtual_address(int type, char *new_address);
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
time_t max_expires, int want_expiry);
-int connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
+int connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
+int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
@@ -98,5 +105,12 @@ hostname_type_t parse_extended_hostname(char *address, int allowdotexit);
int get_pf_socket(void);
#endif
+int connection_edge_compatible_with_circuit(const entry_connection_t *conn,
+ const origin_circuit_t *circ);
+int connection_edge_update_circuit_isolation(const entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run);
+void circuit_clear_isolation(origin_circuit_t *circ);
+
#endif
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index c019f6592b..e178f3a8c0 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -13,6 +13,7 @@
#include "or.h"
#include "buffers.h"
#include "circuitbuild.h"
+#include "circuitlist.h"
#include "command.h"
#include "config.h"
#include "connection.h"
@@ -22,21 +23,33 @@
#include "geoip.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "reasons.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#endif
+
static int connection_tls_finish_handshake(or_connection_t *conn);
+static int connection_or_launch_v3_or_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
-static int connection_or_send_versions(or_connection_t *conn);
-static int connection_init_or_handshake_state(or_connection_t *conn,
- int started_here);
static int connection_or_check_valid_tls_handshake(or_connection_t *conn,
int started_here,
char *digest_rcvd_out);
+static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn);
+static void connection_or_close_connection_cb(void *_conn);
+
+#ifdef USE_BUFFEREVENTS
+static void connection_or_handle_event_cb(struct bufferevent *bufev,
+ short event, void *arg);
+#include <event2/buffer.h>/*XXXX REMOVE */
+#endif
+
/**************************************************************/
/** Map from identity digest of connected OR or desired OR to a connection_t
@@ -136,6 +149,142 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
#endif
}
+/**************************************************************/
+
+/** Map from a string describing what a non-open OR connection was doing when
+ * failed, to an intptr_t describing the count of connections that failed that
+ * way. Note that the count is stored _as_ the pointer.
+ */
+static strmap_t *broken_connection_counts;
+
+/** If true, do not record information in <b>broken_connection_counts</b>. */
+static int disable_broken_connection_counts = 0;
+
+/** Record that an OR connection failed in <b>state</b>. */
+static void
+note_broken_connection(const char *state)
+{
+ void *ptr;
+ intptr_t val;
+ if (disable_broken_connection_counts)
+ return;
+
+ if (!broken_connection_counts)
+ broken_connection_counts = strmap_new();
+
+ ptr = strmap_get(broken_connection_counts, state);
+ val = (intptr_t)ptr;
+ val++;
+ ptr = (void*)val;
+ strmap_set(broken_connection_counts, state, ptr);
+}
+
+/** Forget all recorded states for failed connections. If
+ * <b>stop_recording</b> is true, don't record any more. */
+void
+clear_broken_connection_map(int stop_recording)
+{
+ if (broken_connection_counts)
+ strmap_free(broken_connection_counts, NULL);
+ broken_connection_counts = NULL;
+ if (stop_recording)
+ disable_broken_connection_counts = 1;
+}
+
+/** Write a detailed description the state of <b>orconn</b> into the
+ * <b>buflen</b>-byte buffer at <b>buf</b>. This description includes not
+ * only the OR-conn level state but also the TLS state. It's useful for
+ * diagnosing broken handshakes. */
+static void
+connection_or_get_state_description(or_connection_t *orconn,
+ char *buf, size_t buflen)
+{
+ connection_t *conn = TO_CONN(orconn);
+ const char *conn_state;
+ char tls_state[256];
+
+ tor_assert(conn->type == CONN_TYPE_OR);
+
+ conn_state = conn_state_to_string(conn->type, conn->state);
+ tor_tls_get_state_description(orconn->tls, tls_state, sizeof(tls_state));
+
+ tor_snprintf(buf, buflen, "%s with SSL state %s", conn_state, tls_state);
+}
+
+/** Record the current state of <b>orconn</b> as the state of a broken
+ * connection. */
+static void
+connection_or_note_state_when_broken(or_connection_t *orconn)
+{
+ char buf[256];
+ if (disable_broken_connection_counts)
+ return;
+ connection_or_get_state_description(orconn, buf, sizeof(buf));
+ log_info(LD_HANDSHAKE,"Connection died in state '%s'", buf);
+ note_broken_connection(buf);
+}
+
+/** Helper type used to sort connection states and find the most frequent. */
+typedef struct broken_state_count_t {
+ intptr_t count;
+ const char *state;
+} broken_state_count_t;
+
+/** Helper function used to sort broken_state_count_t by frequency. */
+static int
+broken_state_count_compare(const void **a_ptr, const void **b_ptr)
+{
+ const broken_state_count_t *a = *a_ptr, *b = *b_ptr;
+ if (b->count < a->count)
+ return -1;
+ else if (b->count == a->count)
+ return 0;
+ else
+ return 1;
+}
+
+/** Upper limit on the number of different states to report for connection
+ * failure. */
+#define MAX_REASONS_TO_REPORT 10
+
+/** Report a list of the top states for failed OR connections at log level
+ * <b>severity</b>, in log domain <b>domain</b>. */
+void
+connection_or_report_broken_states(int severity, int domain)
+{
+ int total = 0;
+ smartlist_t *items;
+
+ if (!broken_connection_counts || disable_broken_connection_counts)
+ return;
+
+ items = smartlist_create();
+ STRMAP_FOREACH(broken_connection_counts, state, void *, countptr) {
+ broken_state_count_t *c = tor_malloc(sizeof(broken_state_count_t));
+ c->count = (intptr_t)countptr;
+ total += (int)c->count;
+ c->state = state;
+ smartlist_add(items, c);
+ } STRMAP_FOREACH_END;
+
+ smartlist_sort(items, broken_state_count_compare);
+
+ log(severity, domain, "%d connections have failed%s", total,
+ smartlist_len(items) > MAX_REASONS_TO_REPORT ? ". Top reasons:" : ":");
+
+ SMARTLIST_FOREACH_BEGIN(items, const broken_state_count_t *, c) {
+ if (c_sl_idx > MAX_REASONS_TO_REPORT)
+ break;
+ log(severity, domain,
+ " %d connections died in state %s", (int)c->count, c->state);
+ } SMARTLIST_FOREACH_END(c);
+
+ SMARTLIST_FOREACH(items, broken_state_count_t *, c, tor_free(c));
+ smartlist_free(items);
+}
+
+/**************************************************************/
+
/** Pack the cell_t host-order structure <b>src</b> into network-order
* in the buffer <b>dest</b>. See tor-spec.txt for details about the
* wire format.
@@ -178,7 +327,8 @@ var_cell_pack_header(const var_cell_t *cell, char *hdr_out)
var_cell_t *
var_cell_new(uint16_t payload_len)
{
- var_cell_t *cell = tor_malloc(sizeof(var_cell_t)+payload_len-1);
+ size_t size = STRUCT_OFFSET(var_cell_t, payload) + payload_len;
+ var_cell_t *cell = tor_malloc(size);
cell->payload_len = payload_len;
cell->command = 0;
cell->circ_id = 0;
@@ -227,8 +377,17 @@ connection_or_process_inbuf(or_connection_t *conn)
}
return ret;
+ case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
+#ifdef USE_BUFFEREVENTS
+ if (tor_tls_server_got_renegotiate(conn->tls))
+ connection_or_tls_renegotiated_cb(conn->tls, conn);
+ if (conn->_base.marked_for_close)
+ return 0;
+ /* fall through. */
+#endif
case OR_CONN_STATE_OPEN:
- case OR_CONN_STATE_OR_HANDSHAKING:
+ case OR_CONN_STATE_OR_HANDSHAKING_V2:
+ case OR_CONN_STATE_OR_HANDSHAKING_V3:
return connection_or_process_cells_from_inbuf(conn);
default:
return 0; /* don't do anything */
@@ -248,7 +407,7 @@ connection_or_process_inbuf(or_connection_t *conn)
int
connection_or_flushed_some(or_connection_t *conn)
{
- size_t datalen = buf_datalen(conn->_base.outbuf);
+ size_t datalen = connection_get_outbuf_len(TO_CONN(conn));
/* If we're under the low water mark, add cells until we're just over the
* high water mark. */
if (datalen < OR_CONN_LOWWATER) {
@@ -280,8 +439,8 @@ connection_or_finished_flushing(or_connection_t *conn)
switch (conn->_base.state) {
case OR_CONN_STATE_PROXY_HANDSHAKING:
case OR_CONN_STATE_OPEN:
- case OR_CONN_STATE_OR_HANDSHAKING:
- connection_stop_writing(TO_CONN(conn));
+ case OR_CONN_STATE_OR_HANDSHAKING_V2:
+ case OR_CONN_STATE_OR_HANDSHAKING_V3:
break;
default:
log_err(LD_BUG,"Called in unexpected state %d.", conn->_base.state);
@@ -296,7 +455,7 @@ connection_or_finished_flushing(or_connection_t *conn)
int
connection_or_finished_connecting(or_connection_t *or_conn)
{
- int proxy_type;
+ const int proxy_type = or_conn->proxy_type;
connection_t *conn;
tor_assert(or_conn);
conn = TO_CONN(or_conn);
@@ -306,15 +465,6 @@ connection_or_finished_connecting(or_connection_t *or_conn)
conn->address,conn->port);
control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
- proxy_type = PROXY_NONE;
-
- if (get_options()->HTTPSProxy)
- proxy_type = PROXY_CONNECT;
- else if (get_options()->Socks4Proxy)
- proxy_type = PROXY_SOCKS4;
- else if (get_options()->Socks5Proxy)
- proxy_type = PROXY_SOCKS5;
-
if (proxy_type != PROXY_NONE) {
/* start proxy handshake */
if (connection_proxy_connect(conn, proxy_type) < 0) {
@@ -335,6 +485,54 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return 0;
}
+/* Called when we're about to finally unlink and free an OR connection:
+ * perform necessary accounting and cleanup */
+void
+connection_or_about_to_close(or_connection_t *or_conn)
+{
+ time_t now = time(NULL);
+ connection_t *conn = TO_CONN(or_conn);
+
+ if (or_conn->pending_action)
+ tor_cancel_libevent_action(or_conn->pending_action);
+
+ /* Remember why we're closing this connection. */
+ if (conn->state != OR_CONN_STATE_OPEN) {
+ /* Inform any pending (not attached) circs that they should
+ * give up. */
+ circuit_n_conn_done(TO_OR_CONN(conn), 0);
+ /* now mark things down as needed */
+ if (connection_or_nonopen_was_started_here(or_conn)) {
+ const or_options_t *options = get_options();
+ connection_or_note_state_when_broken(or_conn);
+ rep_hist_note_connect_failed(or_conn->identity_digest, now);
+ entry_guard_register_connect_status(or_conn->identity_digest,0,
+ !options->HTTPSProxy, now);
+ if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
+ int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
+ control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
+ reason);
+ if (!authdir_mode_tests_reachability(options))
+ control_event_bootstrap_problem(
+ orconn_end_reason_to_control_string(reason), reason);
+ }
+ }
+ } else if (conn->hold_open_until_flushed) {
+ /* We only set hold_open_until_flushed when we're intentionally
+ * closing a connection. */
+ rep_hist_note_disconnect(or_conn->identity_digest, now);
+ control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+ tls_error_to_orconn_end_reason(or_conn->tls_error));
+ } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
+ rep_hist_note_connection_died(or_conn->identity_digest, now);
+ control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+ tls_error_to_orconn_end_reason(or_conn->tls_error));
+ }
+ /* Now close all the attached circuits on it. */
+ circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
+ END_CIRC_REASON_OR_CONN_CLOSED);
+}
+
/** Return 1 if identity digest <b>id_digest</b> is known to be a
* currently or recently running relay. Otherwise return 0. */
int
@@ -342,7 +540,7 @@ connection_or_digest_is_known_relay(const char *id_digest)
{
if (router_get_consensus_status_by_id(id_digest))
return 1; /* It's in the consensus: "yes" */
- if (router_get_by_digest(id_digest))
+ if (router_get_by_id_digest(id_digest))
return 1; /* Not in the consensus, but we have a descriptor for
* it. Probably it was in a recent consensus. "Yes". */
return 0;
@@ -359,7 +557,7 @@ connection_or_digest_is_known_relay(const char *id_digest)
*/
static void
connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
- or_options_t *options)
+ const or_options_t *options)
{
int rate, burst; /* per-connection rate limiting params */
if (connection_or_digest_is_known_relay(conn->identity_digest)) {
@@ -382,6 +580,27 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
conn->bandwidthrate = rate;
conn->bandwidthburst = burst;
+#ifdef USE_BUFFEREVENTS
+ {
+ const struct timeval *tick = tor_libevent_get_one_tick_timeout();
+ struct ev_token_bucket_cfg *cfg, *old_cfg;
+ int64_t rate64 = (((int64_t)rate) * options->TokenBucketRefillInterval)
+ / 1000;
+ /* This can't overflow, since TokenBucketRefillInterval <= 1000,
+ * and rate started out less than INT_MAX. */
+ int rate_per_tick = (int) rate64;
+
+ cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick,
+ burst, tick);
+ old_cfg = conn->bucket_cfg;
+ if (conn->_base.bufev)
+ tor_set_bufferevent_rate_limit(conn->_base.bufev, cfg);
+ if (old_cfg)
+ ev_token_bucket_cfg_free(old_cfg);
+ conn->bucket_cfg = cfg;
+ (void) reset; /* No way to do this with libevent yet. */
+ }
+#else
if (reset) { /* set up the token buckets to be full */
conn->read_bucket = conn->write_bucket = burst;
return;
@@ -392,13 +611,15 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
conn->read_bucket = burst;
if (conn->write_bucket > burst)
conn->write_bucket = burst;
+#endif
}
/** Either our set of relays or our per-conn rate limits have changed.
* Go through all the OR connections and update their token buckets to make
* sure they don't exceed their maximum values. */
void
-connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options)
+connection_or_update_token_buckets(smartlist_t *conns,
+ const or_options_t *options)
{
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
@@ -410,13 +631,13 @@ connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options)
/** If we don't necessarily know the router we're connecting to, but we
* have an addr/port/id_digest, then fill in as much as we can. Start
* by checking to see if this describes a router we know. */
-static void
+void
connection_or_init_conn_from_address(or_connection_t *conn,
const tor_addr_t *addr, uint16_t port,
const char *id_digest,
int started_here)
{
- routerinfo_t *r = router_get_by_digest(id_digest);
+ const node_t *r = node_get_by_id(id_digest);
connection_or_set_identity_digest(conn, id_digest);
connection_or_update_token_buckets_helper(conn, 1, get_options());
@@ -424,8 +645,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
tor_addr_copy(&conn->_base.addr, addr);
tor_addr_copy(&conn->real_addr, addr);
if (r) {
+ tor_addr_t node_addr;
+ node_get_addr(r, &node_addr);
/* XXXX proposal 118 will make this more complex. */
- if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr))
+ if (tor_addr_eq(&conn->_base.addr, &node_addr))
conn->is_canonical = 1;
if (!started_here) {
/* Override the addr/port, so our log messages will make sense.
@@ -438,12 +661,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
* right IP address and port 56244, that wouldn't be as helpful. now we
* log the "right" port too, so we know if it's moria1 or moria2.
*/
- tor_addr_from_ipv4h(&conn->_base.addr, r->addr);
- conn->_base.port = r->or_port;
+ tor_addr_copy(&conn->_base.addr, &node_addr);
+ conn->_base.port = node_get_orport(r);
}
- conn->nickname = tor_strdup(r->nickname);
+ conn->nickname = tor_strdup(node_get_nickname(r));
tor_free(conn->_base.address);
- conn->_base.address = tor_strdup(r->address);
+ conn->_base.address = tor_dup_addr(&node_addr);
} else {
const char *n;
/* If we're an authoritative directory server, we may know a
@@ -548,6 +771,11 @@ connection_or_get_for_extend(const char *digest,
tor_assert(tor_memeq(conn->identity_digest, digest, DIGEST_LEN));
if (conn->_base.marked_for_close)
continue;
+ /* Never return a connection on which the other end appears to be
+ * a client. */
+ if (conn->is_connection_with_client) {
+ continue;
+ }
/* Never return a non-open connection. */
if (conn->_base.state != OR_CONN_STATE_OPEN) {
/* If the address matches, don't launch a new connection for this
@@ -787,11 +1015,15 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
const char *id_digest)
{
or_connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int socket_error = 0;
- int using_proxy = 0;
tor_addr_t addr;
+ int r;
+ tor_addr_t proxy_addr;
+ uint16_t proxy_port;
+ int proxy_type;
+
tor_assert(_addr);
tor_assert(id_digest);
tor_addr_copy(&addr, _addr);
@@ -808,19 +1040,22 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
conn->_base.state = OR_CONN_STATE_CONNECTING;
control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
- /* use a proxy server if available */
- if (options->HTTPSProxy) {
- using_proxy = 1;
- tor_addr_copy(&addr, &options->HTTPSProxyAddr);
- port = options->HTTPSProxyPort;
- } else if (options->Socks4Proxy) {
- using_proxy = 1;
- tor_addr_copy(&addr, &options->Socks4ProxyAddr);
- port = options->Socks4ProxyPort;
- } else if (options->Socks5Proxy) {
- using_proxy = 1;
- tor_addr_copy(&addr, &options->Socks5ProxyAddr);
- port = options->Socks5ProxyPort;
+ conn->is_outgoing = 1;
+
+ /* If we are using a proxy server, find it and use it. */
+ r = get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, TO_CONN(conn));
+ if (r == 0) {
+ conn->proxy_type = proxy_type;
+ if (proxy_type != PROXY_NONE) {
+ tor_addr_copy(&addr, &proxy_addr);
+ port = proxy_port;
+ conn->_base.proxy_state = PROXY_INFANT;
+ }
+ } else {
+ log_warn(LD_GENERAL, "Tried to connect through proxy, but proxy address "
+ "could not be found.");
+ connection_free(TO_CONN(conn));
+ return NULL;
}
switch (connection_connect(TO_CONN(conn), conn->_base.address,
@@ -828,7 +1063,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
case -1:
/* If the connection failed immediately, and we're using
* a proxy, our proxy is down. Don't blame the Tor server. */
- if (!using_proxy)
+ if (conn->_base.proxy_state == PROXY_INFANT)
entry_guard_register_connect_status(conn->identity_digest,
0, 1, time(NULL));
connection_or_connect_failed(conn,
@@ -863,19 +1098,50 @@ int
connection_tls_start_handshake(or_connection_t *conn, int receiving)
{
conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING;
+ tor_assert(!conn->tls);
conn->tls = tor_tls_new(conn->_base.s, receiving);
- tor_tls_set_logged_address(conn->tls, // XXX client and relay?
- escaped_safe_str(conn->_base.address));
if (!conn->tls) {
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
+ tor_tls_set_logged_address(conn->tls, // XXX client and relay?
+ escaped_safe_str(conn->_base.address));
+ tor_tls_set_renegotiate_callbacks(conn->tls,
+ connection_or_tls_renegotiated_cb,
+ connection_or_close_connection_cb,
+ conn);
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(TO_CONN(conn))) {
+ const int filtering = get_options()->_UseFilteringSSLBufferevents;
+ struct bufferevent *b =
+ tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s,
+ receiving, filtering);
+ if (!b) {
+ log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing.");
+ return -1;
+ }
+ conn->_base.bufev = b;
+ if (conn->bucket_cfg)
+ tor_set_bufferevent_rate_limit(conn->_base.bufev, conn->bucket_cfg);
+ connection_enable_rate_limiting(TO_CONN(conn));
+
+ connection_configure_bufferevent_callbacks(TO_CONN(conn));
+ bufferevent_setcb(b,
+ connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_or_handle_event_cb,/* overriding this one*/
+ TO_CONN(conn));
+ }
+#endif
connection_start_reading(TO_CONN(conn));
log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s);
note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C);
- if (connection_tls_continue_handshake(conn) < 0) {
- return -1;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ /* ???? */;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ if (connection_tls_continue_handshake(conn) < 0)
+ return -1;
}
return 0;
}
@@ -888,10 +1154,6 @@ connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn)
or_connection_t *conn = _conn;
(void)tls;
- /* Don't invoke this again. */
- tor_tls_set_renegotiate_callback(tls, NULL, NULL);
- tor_tls_block_renegotiation(tls);
-
if (connection_tls_finish_handshake(conn) < 0) {
/* XXXX_TLS double-check that it's ok to do this from inside read. */
/* XXXX_TLS double-check that this verifies certificates. */
@@ -899,6 +1161,34 @@ connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn)
}
}
+/*DOCDOC*/
+static void
+close_connection_libevent_cb(void *_conn)
+{
+ or_connection_t *or_conn = _conn;
+ connection_t *conn = TO_CONN(or_conn);
+
+ or_conn->pending_action = NULL;
+
+ connection_stop_reading(conn);
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+}
+
+/* DOCDOC */
+static void
+connection_or_close_connection_cb(void *_conn)
+{
+ /* We can't close their connection from in here since it's an OpenSSL
+ callback, so we set a libevent event that triggers in the next event
+ loop and closes the connection. */
+ or_connection_t *or_conn = _conn;
+ if (or_conn->_base.marked_for_close || or_conn->pending_action)
+ return;
+ or_conn->pending_action =
+ tor_run_in_libevent_loop(close_connection_libevent_cb, or_conn);
+}
+
/** Move forward with the tls handshake. If it finishes, hand
* <b>conn</b> to connection_tls_finish_handshake().
*
@@ -929,19 +1219,22 @@ connection_tls_continue_handshake(or_connection_t *conn)
if (! tor_tls_used_v1_handshake(conn->tls)) {
if (!tor_tls_is_server(conn->tls)) {
if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
- log_debug(LD_OR, "Done with initial SSL handshake (client-side). "
- "Requesting renegotiation.");
- conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
- goto again;
+ if (tor_tls_received_v3_certificate(conn->tls)) {
+ log_info(LD_OR, "Client got a v3 cert! Moving on to v3 "
+ "handshake.");
+ return connection_or_launch_v3_or_handshake(conn);
+ } else {
+ log_debug(LD_OR, "Done with initial SSL handshake (client-side)."
+ " Requesting renegotiation.");
+ conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
+ goto again;
+ }
}
// log_notice(LD_OR,"Done. state was %d.", conn->_base.state);
} else {
- /* improved handshake, but not a client. */
+ /* v2/v3 handshake, but not a client. */
log_debug(LD_OR, "Done with initial SSL handshake (server-side). "
- "Expecting renegotiation.");
- tor_tls_set_renegotiate_callback(conn->tls,
- connection_or_tls_renegotiated_cb,
- conn);
+ "Expecting renegotiation or VERSIONS cell");
conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
connection_stop_writing(TO_CONN(conn));
connection_start_reading(TO_CONN(conn));
@@ -963,6 +1256,82 @@ connection_tls_continue_handshake(or_connection_t *conn)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+static void
+connection_or_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg)
+{
+ struct or_connection_t *conn = TO_OR_CONN(arg);
+
+ /* XXXX cut-and-paste code; should become a function. */
+ if (event & BEV_EVENT_CONNECTED) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ if (tor_tls_finish_handshake(conn->tls) < 0) {
+ log_warn(LD_OR, "Problem finishing handshake");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+
+ if (! tor_tls_used_v1_handshake(conn->tls)) {
+ if (!tor_tls_is_server(conn->tls)) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ if (tor_tls_received_v3_certificate(conn->tls)) {
+ log_info(LD_OR, "Client got a v3 cert!");
+ if (connection_or_launch_v3_or_handshake(conn) < 0)
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ } else {
+ conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
+ tor_tls_unblock_renegotiation(conn->tls);
+ if (bufferevent_ssl_renegotiate(conn->_base.bufev)<0) {
+ log_warn(LD_OR, "Start_renegotiating went badly.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ tor_tls_unblock_renegotiation(conn->tls);
+ return; /* ???? */
+ }
+ }
+ } else if (tor_tls_get_num_server_handshakes(conn->tls) == 1) {
+ /* v2 or v3 handshake, as a server. Only got one handshake, so
+ * wait for the next one. */
+ conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
+ /* return 0; */
+ return; /* ???? */
+ } else {
+ const int handshakes = tor_tls_get_num_server_handshakes(conn->tls);
+ tor_assert(handshakes >= 2);
+ if (handshakes == 2) {
+ /* v2 handshake, as a server. Two handshakes happened already,
+ * so we treat renegotiation as done.
+ */
+ connection_or_tls_renegotiated_cb(conn->tls, conn);
+ } else {
+ log_warn(LD_OR, "More than two handshakes done on connection. "
+ "Closing.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ return;
+ }
+ }
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ if (connection_tls_finish_handshake(conn) < 0)
+ connection_mark_for_close(TO_CONN(conn)); /* ???? */
+ return;
+ }
+
+ if (event & BEV_EVENT_ERROR) {
+ unsigned long err;
+ while ((err = bufferevent_get_openssl_error(bufev))) {
+ tor_tls_log_one_error(conn->tls, err, LOG_WARN, LD_OR,
+ "handshaking (with bufferevent)");
+ }
+ }
+
+ connection_handle_event_cb(bufev, event, arg);
+}
+#endif
+
/** Return 1 if we initiated this connection, or 0 if it started
* out as an incoming connection.
*/
@@ -977,6 +1346,29 @@ connection_or_nonopen_was_started_here(or_connection_t *conn)
return !tor_tls_is_server(conn->tls);
}
+/** Set the circid_type field of <b>conn</b> (which determines which part of
+ * the circuit ID space we're willing to use) based on comparing our ID to
+ * <b>identity_rcvd</b> */
+void
+connection_or_set_circid_type(or_connection_t *conn,
+ crypto_pk_env_t *identity_rcvd)
+{
+ const int started_here = connection_or_nonopen_was_started_here(conn);
+ crypto_pk_env_t *our_identity =
+ started_here ? get_tlsclient_identity_key() :
+ get_server_identity_key();
+
+ if (identity_rcvd) {
+ if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) {
+ conn->circ_id_type = CIRC_ID_TYPE_LOWER;
+ } else {
+ conn->circ_id_type = CIRC_ID_TYPE_HIGHER;
+ }
+ } else {
+ conn->circ_id_type = CIRC_ID_TYPE_NEITHER;
+ }
+}
+
/** <b>Conn</b> just completed its handshake. Return 0 if all is well, and
* return -1 if he is lying, broken, or otherwise something is wrong.
*
@@ -1008,16 +1400,13 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
char *digest_rcvd_out)
{
crypto_pk_env_t *identity_rcvd=NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
const char *safe_address =
started_here ? conn->_base.address :
safe_str_client(conn->_base.address);
const char *conn_type = started_here ? "outgoing" : "incoming";
- crypto_pk_env_t *our_identity =
- started_here ? get_tlsclient_identity_key() :
- get_server_identity_key();
- int has_cert = 0, has_identity=0;
+ int has_cert = 0;
check_no_tls_errors();
has_cert = tor_tls_peer_has_cert(conn->tls);
@@ -1052,21 +1441,46 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
}
if (identity_rcvd) {
- has_identity = 1;
crypto_pk_get_digest(identity_rcvd, digest_rcvd_out);
- if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) {
- conn->circ_id_type = CIRC_ID_TYPE_LOWER;
- } else {
- conn->circ_id_type = CIRC_ID_TYPE_HIGHER;
- }
- crypto_free_pk_env(identity_rcvd);
} else {
memset(digest_rcvd_out, 0, DIGEST_LEN);
- conn->circ_id_type = CIRC_ID_TYPE_NEITHER;
}
- if (started_here && tor_digest_is_zero(conn->identity_digest)) {
- connection_or_set_identity_digest(conn, digest_rcvd_out);
+ connection_or_set_circid_type(conn, identity_rcvd);
+ crypto_free_pk_env(identity_rcvd);
+
+ if (started_here)
+ return connection_or_client_learned_peer_id(conn,
+ (const uint8_t*)digest_rcvd_out);
+
+ return 0;
+}
+
+/** Called when we (as a connection initiator) have definitively,
+ * authenticatedly, learned that ID of the Tor instance on the other
+ * side of <b>conn</b> is <b>peer_id</b>. For v1 and v2 handshakes,
+ * this is right after we get a certificate chain in a TLS handshake
+ * or renegotiation. For v3 handshakes, this is right after we get a
+ * certificate chain in a CERTS cell.
+ *
+ * If we want any particular ID before, record the one we got.
+ *
+ * If we wanted an ID, but we didn't get it, log a warning and return -1.
+ *
+ * If we're testing reachability, remember what we learned.
+ *
+ * Return 0 on success, -1 on failure.
+ */
+int
+connection_or_client_learned_peer_id(or_connection_t *conn,
+ const uint8_t *peer_id)
+{
+ int as_expected = 1;
+ const or_options_t *options = get_options();
+ int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
+
+ if (tor_digest_is_zero(conn->identity_digest)) {
+ connection_or_set_identity_digest(conn, (const char*)peer_id);
tor_free(conn->nickname);
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
conn->nickname[0] = '$';
@@ -1078,43 +1492,39 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
/* if it's a bridge and we didn't know its identity fingerprint, now
* we do -- remember it for future attempts. */
learned_router_identity(&conn->_base.addr, conn->_base.port,
- digest_rcvd_out);
+ (const char*)peer_id);
}
- if (started_here) {
- int as_advertised = 1;
- tor_assert(has_cert);
- tor_assert(has_identity);
- if (tor_memneq(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) {
- /* I was aiming for a particular digest. I didn't get it! */
- char seen[HEX_DIGEST_LEN+1];
- char expected[HEX_DIGEST_LEN+1];
- base16_encode(seen, sizeof(seen), digest_rcvd_out, DIGEST_LEN);
- base16_encode(expected, sizeof(expected), conn->identity_digest,
- DIGEST_LEN);
- log_fn(severity, LD_HANDSHAKE,
- "Tried connecting to router at %s:%d, but identity key was not "
- "as expected: wanted %s but got %s.",
- conn->_base.address, conn->_base.port, expected, seen);
- entry_guard_register_connect_status(conn->identity_digest, 0, 1,
- time(NULL));
- control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
- END_OR_CONN_REASON_OR_IDENTITY);
- if (!authdir_mode_tests_reachability(options))
- control_event_bootstrap_problem("foo", END_OR_CONN_REASON_OR_IDENTITY);
- as_advertised = 0;
- }
- if (authdir_mode_tests_reachability(options)) {
- dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
- digest_rcvd_out, as_advertised);
- }
- if (!as_advertised)
- return -1;
+ if (tor_memneq(peer_id, conn->identity_digest, DIGEST_LEN)) {
+ /* I was aiming for a particular digest. I didn't get it! */
+ char seen[HEX_DIGEST_LEN+1];
+ char expected[HEX_DIGEST_LEN+1];
+ base16_encode(seen, sizeof(seen), (const char*)peer_id, DIGEST_LEN);
+ base16_encode(expected, sizeof(expected), conn->identity_digest,
+ DIGEST_LEN);
+ log_fn(severity, LD_HANDSHAKE,
+ "Tried connecting to router at %s:%d, but identity key was not "
+ "as expected: wanted %s but got %s.",
+ conn->_base.address, conn->_base.port, expected, seen);
+ entry_guard_register_connect_status(conn->identity_digest, 0, 1,
+ time(NULL));
+ control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
+ END_OR_CONN_REASON_OR_IDENTITY);
+ if (!authdir_mode_tests_reachability(options))
+ control_event_bootstrap_problem("foo", END_OR_CONN_REASON_OR_IDENTITY);
+ as_expected = 0;
+ }
+ if (authdir_mode_tests_reachability(options)) {
+ dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
+ (const char*)peer_id, as_expected);
}
+ if (!as_expected)
+ return -1;
+
return 0;
}
-/** The tls handshake is finished.
+/** The v1/v2 TLS handshake is finished.
*
* Make sure we are happy with the person we just handshaked with.
*
@@ -1124,6 +1534,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
* If all is successful, call circuit_n_conn_done() to handle events
* that have been pending on the <tls handshake completion. Also set the
* directory to be dirty (only matters if I'm an authdirserver).
+ *
+ * If this is a v2 TLS handshake, send a versions cell.
*/
static int
connection_tls_finish_handshake(or_connection_t *conn)
@@ -1131,7 +1543,9 @@ connection_tls_finish_handshake(or_connection_t *conn)
char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn);
- log_debug(LD_HANDSHAKE,"tls handshake with %s done. verifying.",
+ log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done. verifying.",
+ started_here?"outgoing":"incoming",
+ conn,
safe_str_client(conn->_base.address));
directory_set_dirty();
@@ -1148,28 +1562,50 @@ connection_tls_finish_handshake(or_connection_t *conn)
connection_or_init_conn_from_address(conn, &conn->_base.addr,
conn->_base.port, digest_rcvd, 0);
}
- tor_tls_block_renegotiation(conn->tls);
return connection_or_set_state_open(conn);
} else {
- conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING;
+ conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V2;
if (connection_init_or_handshake_state(conn, started_here) < 0)
return -1;
if (!started_here) {
connection_or_init_conn_from_address(conn, &conn->_base.addr,
conn->_base.port, digest_rcvd, 0);
}
- return connection_or_send_versions(conn);
+ return connection_or_send_versions(conn, 0);
}
}
+/**
+ * Called as client when initial TLS handshake is done, and we notice
+ * that we got a v3-handshake signalling certificate from the server.
+ * Set up structures, do bookkeeping, and send the versions cell.
+ * Return 0 on success and -1 on failure.
+ */
+static int
+connection_or_launch_v3_or_handshake(or_connection_t *conn)
+{
+ tor_assert(connection_or_nonopen_was_started_here(conn));
+ tor_assert(tor_tls_received_v3_certificate(conn->tls));
+
+ circuit_build_times_network_is_live(&circ_times);
+
+ conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
+ if (connection_init_or_handshake_state(conn, 1) < 0)
+ return -1;
+
+ return connection_or_send_versions(conn, 1);
+}
+
/** Allocate a new connection handshake state for the connection
* <b>conn</b>. Return 0 on success, -1 on failure. */
-static int
+int
connection_init_or_handshake_state(or_connection_t *conn, int started_here)
{
or_handshake_state_t *s;
s = conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t));
s->started_here = started_here ? 1 : 0;
+ s->digest_sent_data = 1;
+ s->digest_received_data = 1;
return 0;
}
@@ -1179,10 +1615,89 @@ or_handshake_state_free(or_handshake_state_t *state)
{
if (!state)
return;
+ crypto_free_digest_env(state->digest_sent);
+ crypto_free_digest_env(state->digest_received);
+ tor_cert_free(state->auth_cert);
+ tor_cert_free(state->id_cert);
memset(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state);
}
+/**
+ * Remember that <b>cell</b> has been transmitted (if <b>incoming</b> is
+ * false) or received (if <b>incoming is true) during a V3 handshake using
+ * <b>state</b>.
+ *
+ * (We don't record the cell, but we keep a digest of everything sent or
+ * received during the v3 handshake, and the client signs it in an
+ * authenticate cell.)
+ */
+void
+or_handshake_state_record_cell(or_handshake_state_t *state,
+ const cell_t *cell,
+ int incoming)
+{
+ crypto_digest_env_t *d, **dptr;
+ packed_cell_t packed;
+ if (incoming) {
+ if (!state->digest_received_data)
+ return;
+ } else {
+ if (!state->digest_sent_data)
+ return;
+ }
+ if (!incoming) {
+ log_warn(LD_BUG, "We shouldn't be sending any non-variable-length cells "
+ "while making a handshake digest. But we think we are sending "
+ "one with type %d.", (int)cell->command);
+ }
+ dptr = incoming ? &state->digest_received : &state->digest_sent;
+ if (! *dptr)
+ *dptr = crypto_new_digest256_env(DIGEST_SHA256);
+
+ d = *dptr;
+ /* Re-packing like this is a little inefficient, but we don't have to do
+ this very often at all. */
+ cell_pack(&packed, cell);
+ crypto_digest_add_bytes(d, packed.body, sizeof(packed.body));
+ memset(&packed, 0, sizeof(packed));
+}
+
+/** Remember that a variable-length <b>cell</b> has been transmitted (if
+ * <b>incoming</b> is false) or received (if <b>incoming is true) during a V3
+ * handshake using <b>state</b>.
+ *
+ * (We don't record the cell, but we keep a digest of everything sent or
+ * received during the v3 handshake, and the client signs it in an
+ * authenticate cell.)
+ */
+void
+or_handshake_state_record_var_cell(or_handshake_state_t *state,
+ const var_cell_t *cell,
+ int incoming)
+{
+ crypto_digest_env_t *d, **dptr;
+ char buf[VAR_CELL_HEADER_SIZE];
+ if (incoming) {
+ if (!state->digest_received_data)
+ return;
+ } else {
+ if (!state->digest_sent_data)
+ return;
+ }
+ dptr = incoming ? &state->digest_received : &state->digest_sent;
+ if (! *dptr)
+ *dptr = crypto_new_digest256_env(DIGEST_SHA256);
+
+ d = *dptr;
+
+ var_cell_pack_header(cell, buf);
+ crypto_digest_add_bytes(d, buf, sizeof(buf));
+ crypto_digest_add_bytes(d, (const char *)cell->payload, cell->payload_len);
+
+ memset(buf, 0, sizeof(buf));
+}
+
/** Set <b>conn</b>'s state to OR_CONN_STATE_OPEN, and tell other subsystems
* as appropriate. Called when we are done with all TLS and OR handshaking.
*/
@@ -1212,7 +1727,7 @@ connection_or_set_state_open(or_connection_t *conn)
router_set_status(conn->identity_digest, 1);
} else {
/* only report it to the geoip module if it's not a known router */
- if (!router_get_by_digest(conn->identity_digest)) {
+ if (!router_get_by_id_digest(conn->identity_digest)) {
if (tor_addr_family(&TO_CONN(conn)->addr) == AF_INET) {
/*XXXX IP6 support ipv6 geoip.*/
uint32_t a = tor_addr_to_ipv4h(&TO_CONN(conn)->addr);
@@ -1223,8 +1738,12 @@ connection_or_set_state_open(or_connection_t *conn)
or_handshake_state_free(conn->handshake_state);
conn->handshake_state = NULL;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ connection_start_reading(TO_CONN(conn));
+ }
- connection_start_reading(TO_CONN(conn));
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
return 0;
@@ -1246,6 +1765,9 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn));
+ if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
+ or_handshake_state_record_cell(conn->handshake_state, cell, 0);
+
if (cell->command != CELL_PADDING)
conn->timestamp_last_added_nonpadding = approx_time();
}
@@ -1265,16 +1787,24 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell,
connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn));
connection_write_to_buf((char*)cell->payload,
cell->payload_len, TO_CONN(conn));
+ if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
+ or_handshake_state_record_var_cell(conn->handshake_state, cell, 0);
if (cell->command != CELL_PADDING)
conn->timestamp_last_added_nonpadding = approx_time();
}
-/** See whether there's a variable-length cell waiting on <b>conn</b>'s
+/** See whether there's a variable-length cell waiting on <b>or_conn</b>'s
* inbuf. Return values as for fetch_var_cell_from_buf(). */
static int
-connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out)
+connection_fetch_var_cell_from_buf(or_connection_t *or_conn, var_cell_t **out)
{
- return fetch_var_cell_from_buf(conn->_base.inbuf, out, conn->link_proto);
+ connection_t *conn = TO_CONN(or_conn);
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_var_cell_from_evbuffer(input, out, or_conn->link_proto);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_var_cell_from_buf(conn->inbuf, out, or_conn->link_proto);
+ }
}
/** Process cells from <b>conn</b>'s inbuf.
@@ -1292,7 +1822,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
while (1) {
log_debug(LD_OR,
"%d: starting, inbuf_datalen %d (%d pending in tls object).",
- conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
+ conn->_base.s,(int)connection_get_inbuf_len(TO_CONN(conn)),
tor_tls_get_pending_bytes(conn->tls));
if (connection_fetch_var_cell_from_buf(conn, &var_cell)) {
if (!var_cell)
@@ -1303,8 +1833,8 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
} else {
char buf[CELL_NETWORK_SIZE];
cell_t cell;
- if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response
- available? */
+ if (connection_get_inbuf_len(TO_CONN(conn))
+ < CELL_NETWORK_SIZE) /* whole response available? */
return 0; /* not yet */
circuit_build_times_network_is_live(&circ_times);
@@ -1343,7 +1873,7 @@ connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason)
}
/** Array of recognized link protocol versions. */
-static const uint16_t or_protocol_versions[] = { 1, 2 };
+static const uint16_t or_protocol_versions[] = { 1, 2, 3 };
/** Number of versions in <b>or_protocol_versions</b>. */
static const int n_or_protocol_versions =
(int)( sizeof(or_protocol_versions)/sizeof(uint16_t) );
@@ -1362,20 +1892,33 @@ is_or_protocol_version_known(uint16_t v)
}
/** Send a VERSIONS cell on <b>conn</b>, telling the other host about the
- * link protocol versions that this Tor can support. */
-static int
-connection_or_send_versions(or_connection_t *conn)
+ * link protocol versions that this Tor can support.
+ *
+ * If <b>v3_plus</b>, this is part of a V3 protocol handshake, so only
+ * allow protocol version v3 or later. If not <b>v3_plus</b>, this is
+ * not part of a v3 protocol handshake, so don't allow protocol v3 or
+ * later.
+ **/
+int
+connection_or_send_versions(or_connection_t *conn, int v3_plus)
{
var_cell_t *cell;
int i;
+ int n_versions = 0;
+ const int min_version = v3_plus ? 3 : 0;
+ const int max_version = v3_plus ? UINT16_MAX : 2;
tor_assert(conn->handshake_state &&
!conn->handshake_state->sent_versions_at);
cell = var_cell_new(n_or_protocol_versions * 2);
cell->command = CELL_VERSIONS;
for (i = 0; i < n_or_protocol_versions; ++i) {
uint16_t v = or_protocol_versions[i];
- set_uint16(cell->payload+(2*i), htons(v));
+ if (v < min_version || v > max_version)
+ continue;
+ set_uint16(cell->payload+(2*n_versions), htons(v));
+ ++n_versions;
}
+ cell->payload_len = n_versions * 2;
connection_or_write_var_cell_to_buf(cell, conn);
conn->handshake_state->sent_versions_at = time(NULL);
@@ -1391,10 +1934,12 @@ connection_or_send_netinfo(or_connection_t *conn)
{
cell_t cell;
time_t now = time(NULL);
- routerinfo_t *me;
+ const routerinfo_t *me;
int len;
uint8_t *out;
+ tor_assert(conn->handshake_state);
+
memset(&cell, 0, sizeof(cell_t));
cell.command = CELL_NETINFO;
@@ -1403,13 +1948,20 @@ connection_or_send_netinfo(or_connection_t *conn)
/* Their address. */
out = cell.payload + 4;
- len = append_address_to_payload(out, &conn->_base.addr);
+ /* We use &conn->real_addr below, unless it hasn't yet been set. If it
+ * hasn't yet been set, we know that _base.addr hasn't been tampered with
+ * yet either. */
+ len = append_address_to_payload(out, !tor_addr_is_null(&conn->real_addr)
+ ? &conn->real_addr : &conn->_base.addr);
if (len<0)
return -1;
out += len;
- /* My address. */
- if ((me = router_get_my_routerinfo())) {
+ /* My address -- only include it if I'm a public relay, or if I'm a
+ * bridge and this is an incoming connection. If I'm a bridge and this
+ * is an outgoing connection, act like a normal client and omit it. */
+ if ((public_server_mode(get_options()) || !conn->is_outgoing) &&
+ (me = router_get_my_routerinfo())) {
tor_addr_t my_addr;
*out++ = 1; /* only one address is supported. */
@@ -1421,8 +1973,285 @@ connection_or_send_netinfo(or_connection_t *conn)
*out = 0;
}
+ conn->handshake_state->digest_sent_data = 0;
connection_or_write_cell_to_buf(&cell, conn);
return 0;
}
+/** Send a CERTS cell on the connection <b>conn</b>. Return 0 on success, -1
+ * on failure. */
+int
+connection_or_send_certs_cell(or_connection_t *conn)
+{
+ const tor_cert_t *link_cert = NULL, *id_cert = NULL;
+ const uint8_t *link_encoded = NULL, *id_encoded = NULL;
+ size_t link_len, id_len;
+ var_cell_t *cell;
+ size_t cell_len;
+ ssize_t pos;
+ int server_mode;
+
+ tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3);
+
+ if (! conn->handshake_state)
+ return -1;
+ server_mode = ! conn->handshake_state->started_here;
+ if (tor_tls_get_my_certs(server_mode, &link_cert, &id_cert) < 0)
+ return -1;
+ tor_cert_get_der(link_cert, &link_encoded, &link_len);
+ tor_cert_get_der(id_cert, &id_encoded, &id_len);
+
+ cell_len = 1 /* 1 byte: num certs in cell */ +
+ 2 * ( 1 + 2 ) /* For each cert: 1 byte for type, 2 for length */ +
+ link_len + id_len;
+ cell = var_cell_new(cell_len);
+ cell->command = CELL_CERTS;
+ cell->payload[0] = 2;
+ pos = 1;
+
+ if (server_mode)
+ cell->payload[pos] = OR_CERT_TYPE_TLS_LINK; /* Link cert */
+ else
+ cell->payload[pos] = OR_CERT_TYPE_AUTH_1024; /* client authentication */
+ set_uint16(&cell->payload[pos+1], htons(link_len));
+ memcpy(&cell->payload[pos+3], link_encoded, link_len);
+ pos += 3 + link_len;
+
+ cell->payload[pos] = OR_CERT_TYPE_ID_1024; /* ID cert */
+ set_uint16(&cell->payload[pos+1], htons(id_len));
+ memcpy(&cell->payload[pos+3], id_encoded, id_len);
+ pos += 3 + id_len;
+
+ tor_assert(pos == (int)cell_len); /* Otherwise we just smashed the heap */
+
+ connection_or_write_var_cell_to_buf(cell, conn);
+ var_cell_free(cell);
+
+ return 0;
+}
+
+/** Send an AUTH_CHALLENGE cell on the connection <b>conn</b>. Return 0
+ * on success, -1 on failure. */
+int
+connection_or_send_auth_challenge_cell(or_connection_t *conn)
+{
+ var_cell_t *cell;
+ uint8_t *cp;
+ uint8_t challenge[OR_AUTH_CHALLENGE_LEN];
+ tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3);
+
+ if (! conn->handshake_state)
+ return -1;
+
+ if (crypto_rand((char*)challenge, OR_AUTH_CHALLENGE_LEN) < 0)
+ return -1;
+ cell = var_cell_new(OR_AUTH_CHALLENGE_LEN + 4);
+ cell->command = CELL_AUTH_CHALLENGE;
+ memcpy(cell->payload, challenge, OR_AUTH_CHALLENGE_LEN);
+ cp = cell->payload + OR_AUTH_CHALLENGE_LEN;
+ set_uint16(cp, htons(1)); /* We recognize one authentication type. */
+ set_uint16(cp+2, htons(AUTHTYPE_RSA_SHA256_TLSSECRET));
+
+ connection_or_write_var_cell_to_buf(cell, conn);
+ var_cell_free(cell);
+ memset(challenge, 0, sizeof(challenge));
+
+ return 0;
+}
+
+/** Compute the main body of an AUTHENTICATE cell that a client can use
+ * to authenticate itself on a v3 handshake for <b>conn</b>. Write it to the
+ * <b>outlen</b>-byte buffer at <b>out</b>.
+ *
+ * If <b>server</b> is true, only calculate the first
+ * V3_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's
+ * determined by the rest of the handshake, and which match the provided value
+ * exactly.
+ *
+ * If <b>server</b> is false and <b>signing_key</b> is NULL, calculate the
+ * first V3_AUTH_BODY_LEN bytes of the authenticator (that is, everything
+ * that should be signed), but don't actually sign it.
+ *
+ * If <b>server</b> is false and <b>signing_key</b> is provided, calculate the
+ * entire authenticator, signed with <b>signing_key</b>.
+ * DOCDOC return value
+ */
+int
+connection_or_compute_authenticate_cell_body(or_connection_t *conn,
+ uint8_t *out, size_t outlen,
+ crypto_pk_env_t *signing_key,
+ int server)
+{
+ uint8_t *ptr;
+
+ /* assert state is reasonable XXXX */
+
+ if (outlen < V3_AUTH_FIXED_PART_LEN ||
+ (!server && outlen < V3_AUTH_BODY_LEN))
+ return -1;
+
+ ptr = out;
+
+ /* Type: 8 bytes. */
+ memcpy(ptr, "AUTH0001", 8);
+ ptr += 8;
+
+ {
+ const tor_cert_t *id_cert=NULL, *link_cert=NULL;
+ const digests_t *my_digests, *their_digests;
+ const uint8_t *my_id, *their_id, *client_id, *server_id;
+ if (tor_tls_get_my_certs(0, &link_cert, &id_cert))
+ return -1;
+ my_digests = tor_cert_get_id_digests(id_cert);
+ their_digests = tor_cert_get_id_digests(conn->handshake_state->id_cert);
+ tor_assert(my_digests);
+ tor_assert(their_digests);
+ my_id = (uint8_t*)my_digests->d[DIGEST_SHA256];
+ their_id = (uint8_t*)their_digests->d[DIGEST_SHA256];
+
+ client_id = server ? their_id : my_id;
+ server_id = server ? my_id : their_id;
+
+ /* Client ID digest: 32 octets. */
+ memcpy(ptr, client_id, 32);
+ ptr += 32;
+
+ /* Server ID digest: 32 octets. */
+ memcpy(ptr, server_id, 32);
+ ptr += 32;
+ }
+
+ {
+ crypto_digest_env_t *server_d, *client_d;
+ if (server) {
+ server_d = conn->handshake_state->digest_sent;
+ client_d = conn->handshake_state->digest_received;
+ } else {
+ client_d = conn->handshake_state->digest_sent;
+ server_d = conn->handshake_state->digest_received;
+ }
+
+ /* Server log digest : 32 octets */
+ crypto_digest_get_digest(server_d, (char*)ptr, 32);
+ ptr += 32;
+
+ /* Client log digest : 32 octets */
+ crypto_digest_get_digest(client_d, (char*)ptr, 32);
+ ptr += 32;
+ }
+
+ {
+ /* Digest of cert used on TLS link : 32 octets. */
+ const tor_cert_t *cert = NULL;
+ tor_cert_t *freecert = NULL;
+ if (server) {
+ tor_tls_get_my_certs(1, &cert, NULL);
+ } else {
+ freecert = tor_tls_get_peer_cert(conn->tls);
+ cert = freecert;
+ }
+ if (!cert)
+ return -1;
+ memcpy(ptr, tor_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32);
+
+ if (freecert)
+ tor_cert_free(freecert);
+ ptr += 32;
+ }
+
+ /* HMAC of clientrandom and serverrandom using master key : 32 octets */
+ tor_tls_get_tlssecrets(conn->tls, ptr);
+ ptr += 32;
+
+ tor_assert(ptr - out == V3_AUTH_FIXED_PART_LEN);
+
+ if (server)
+ return V3_AUTH_FIXED_PART_LEN; // ptr-out
+
+ /* Time: 8 octets. */
+ {
+ uint64_t now = time(NULL);
+ if ((time_t)now < 0)
+ return -1;
+ set_uint32(ptr, htonl((uint32_t)(now>>32)));
+ set_uint32(ptr+4, htonl((uint32_t)now));
+ ptr += 8;
+ }
+
+ /* Nonce: 16 octets. */
+ crypto_rand((char*)ptr, 16);
+ ptr += 16;
+
+ tor_assert(ptr - out == V3_AUTH_BODY_LEN);
+
+ if (!signing_key)
+ return V3_AUTH_BODY_LEN; // ptr - out
+
+ {
+ int siglen;
+ char d[32];
+ crypto_digest256(d, (char*)out, ptr-out, DIGEST_SHA256);
+ siglen = crypto_pk_private_sign(signing_key,
+ (char*)ptr, outlen - (ptr-out),
+ d, 32);
+ if (siglen < 0)
+ return -1;
+
+ ptr += siglen;
+ tor_assert(ptr <= out+outlen);
+ return (int)(ptr - out);
+ }
+}
+
+/** Send an AUTHENTICATE cell on the connection <b>conn</b>. Return 0 on
+ * success, -1 on failure */
+int
+connection_or_send_authenticate_cell(or_connection_t *conn, int authtype)
+{
+ var_cell_t *cell;
+ crypto_pk_env_t *pk = tor_tls_get_my_client_auth_key();
+ int authlen;
+ size_t cell_maxlen;
+ /* XXXX make sure we're actually supposed to send this! */
+
+ if (!pk) {
+ log_warn(LD_BUG, "Can't compute authenticate cell: no client auth key");
+ return -1;
+ }
+ if (authtype != AUTHTYPE_RSA_SHA256_TLSSECRET) {
+ log_warn(LD_BUG, "Tried to send authenticate cell with unknown "
+ "authentication type %d", authtype);
+ return -1;
+ }
+
+ cell_maxlen = 4 + /* overhead */
+ V3_AUTH_BODY_LEN + /* Authentication body */
+ crypto_pk_keysize(pk) + /* Max signature length */
+ 16 /* add a few extra bytes just in case. */;
+
+ cell = var_cell_new(cell_maxlen);
+ cell->command = CELL_AUTHENTICATE;
+ set_uint16(cell->payload, htons(AUTHTYPE_RSA_SHA256_TLSSECRET));
+ /* skip over length ; we don't know that yet. */
+
+ authlen = connection_or_compute_authenticate_cell_body(conn,
+ cell->payload+4,
+ cell_maxlen-4,
+ pk,
+ 0 /* not server */);
+ if (authlen < 0) {
+ log_warn(LD_BUG, "Unable to compute authenticate cell!");
+ var_cell_free(cell);
+ return -1;
+ }
+ tor_assert(authlen + 4 <= cell->payload_len);
+ set_uint16(cell->payload+2, htons(authlen));
+ cell->payload_len = authlen + 4;
+
+ connection_or_write_var_cell_to_buf(cell, conn);
+ var_cell_free(cell);
+
+ return 0;
+}
+
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 70ef96a335..62a15b1cf2 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -14,6 +14,7 @@
void connection_or_remove_from_identity_map(or_connection_t *conn);
void connection_or_clear_identity_map(void);
+void clear_broken_connection_map(int disable);
or_connection_t *connection_or_get_for_extend(const char *digest,
const tor_addr_t *target_addr,
const char **msg_out,
@@ -25,19 +26,40 @@ int connection_or_process_inbuf(or_connection_t *conn);
int connection_or_flushed_some(or_connection_t *conn);
int connection_or_finished_flushing(or_connection_t *conn);
int connection_or_finished_connecting(or_connection_t *conn);
+void connection_or_about_to_close(or_connection_t *conn);
int connection_or_digest_is_known_relay(const char *id_digest);
void connection_or_update_token_buckets(smartlist_t *conns,
- or_options_t *options);
+ const or_options_t *options);
void connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg);
or_connection_t *connection_or_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest);
+void connection_or_report_broken_states(int severity, int domain);
+
int connection_tls_start_handshake(or_connection_t *conn, int receiving);
int connection_tls_continue_handshake(or_connection_t *conn);
+int connection_init_or_handshake_state(or_connection_t *conn,
+ int started_here);
+void connection_or_init_conn_from_address(or_connection_t *conn,
+ const tor_addr_t *addr,
+ uint16_t port,
+ const char *id_digest,
+ int started_here);
+int connection_or_client_learned_peer_id(or_connection_t *conn,
+ const uint8_t *peer_id);
+void connection_or_set_circid_type(or_connection_t *conn,
+ crypto_pk_env_t *identity_rcvd);
void or_handshake_state_free(or_handshake_state_t *state);
+void or_handshake_state_record_cell(or_handshake_state_t *state,
+ const cell_t *cell,
+ int incoming);
+void or_handshake_state_record_var_cell(or_handshake_state_t *state,
+ const var_cell_t *cell,
+ int incoming);
+
int connection_or_set_state_open(or_connection_t *conn);
void connection_or_write_cell_to_buf(const cell_t *cell,
or_connection_t *conn);
@@ -45,7 +67,16 @@ void connection_or_write_var_cell_to_buf(const var_cell_t *cell,
or_connection_t *conn);
int connection_or_send_destroy(circid_t circ_id, or_connection_t *conn,
int reason);
+int connection_or_send_versions(or_connection_t *conn, int v3_plus);
int connection_or_send_netinfo(or_connection_t *conn);
+int connection_or_send_certs_cell(or_connection_t *conn);
+int connection_or_send_auth_challenge_cell(or_connection_t *conn);
+int connection_or_compute_authenticate_cell_body(or_connection_t *conn,
+ uint8_t *out, size_t outlen,
+ crypto_pk_env_t *signing_key,
+ int server);
+int connection_or_send_authenticate_cell(or_connection_t *conn, int type);
+
int is_or_protocol_version_known(uint16_t version);
void cell_pack(packed_cell_t *dest, const cell_t *src);
diff --git a/src/or/control.c b/src/or/control.c
index 1e411ec9c1..e2d0eece02 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -18,6 +18,7 @@
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
+#include "connection_or.h"
#include "control.h"
#include "directory.h"
#include "dirserv.h"
@@ -26,12 +27,18 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#ifndef MS_WINDOWS
+#include <pwd.h>
+#include <sys/resource.h>
+#endif
+
#include "procmon.h"
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
@@ -66,7 +73,9 @@
#define EVENT_CLIENTS_SEEN 0x0015
#define EVENT_NEWCONSENSUS 0x0016
#define EVENT_BUILDTIMEOUT_SET 0x0017
-#define _EVENT_MAX 0x0017
+#define EVENT_SIGNAL 0x0018
+#define EVENT_CONF_CHANGED 0x0019
+#define _EVENT_MAX 0x0019
/* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */
/** Bitfield: The bit 1&lt;&lt;e is set if <b>any</b> open control
@@ -168,7 +177,7 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len,
static int handle_control_usefeature(control_connection_t *conn,
uint32_t len,
const char *body);
-static int write_stream_target_to_buf(edge_connection_t *conn, char *buf,
+static int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
size_t len);
static void orconn_target_get_name(char *buf, size_t len,
or_connection_t *conn);
@@ -494,8 +503,8 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
va_end(ap);
if (len < 0) {
- log_warn(LD_BUG, "Unable to format string for controller.");
- return;
+ log_err(LD_BUG, "Unable to format string for controller.");
+ tor_assert(0);
}
connection_write_to_buf(buf, (size_t)len, TO_CONN(conn));
@@ -509,7 +518,7 @@ control_ports_write_to_file(void)
{
smartlist_t *lines;
char *joined = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!options->ControlPortWriteToFile)
return;
@@ -593,7 +602,7 @@ send_control_event_string(uint16_t event, event_format_t which,
else if (event == EVENT_STATUS_SERVER)
is_err = !strcmpstart(msg, "STATUS_SERVER ERR ");
if (is_err)
- connection_handle_write(TO_CONN(control_conn), 1);
+ connection_flush(TO_CONN(control_conn));
}
}
} SMARTLIST_FOREACH_END(conn);
@@ -647,7 +656,7 @@ get_circ(const char *id)
}
/** Given a text stream <b>id</b>, return the corresponding AP connection. */
-static edge_connection_t *
+static entry_connection_t *
get_stream(const char *id)
{
uint64_t n_id;
@@ -659,7 +668,7 @@ get_stream(const char *id)
conn = connection_get_by_global_id(n_id);
if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close)
return NULL;
- return TO_EDGE_CONN(conn);
+ return TO_ENTRY_CONN(conn);
}
/** Helper for setconf and resetconf. Acts like setconf, except
@@ -728,7 +737,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp));
smartlist_free(entries);
- if (config_get_lines(config, &lines) < 0) {
+ if (config_get_lines(config, &lines, 0) < 0) {
log_warn(LD_CONTROL,"Controller gave us config lines we can't parse.");
connection_write_str_to_buf("551 Couldn't parse configuration\r\n",
conn);
@@ -798,7 +807,7 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
smartlist_t *unrecognized = smartlist_create();
char *msg = NULL;
size_t msg_len;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int i, len;
(void) body_len; /* body is NUL-terminated; so we can ignore len. */
@@ -874,7 +883,7 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len,
const char *msg = NULL;
(void) len;
- retval = options_init_from_string(body, CMD_RUN_TOR, NULL, &errstring);
+ retval = options_init_from_string(NULL, body, CMD_RUN_TOR, NULL, &errstring);
if (retval != SETOPT_OK)
log_warn(LD_CONTROL,
@@ -910,13 +919,45 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len,
return 0;
}
+struct control_event_t {
+ uint16_t event_code;
+ const char *event_name;
+};
+static const struct control_event_t control_event_table[] = {
+ { EVENT_CIRCUIT_STATUS, "CIRC" },
+ { EVENT_STREAM_STATUS, "STREAM" },
+ { EVENT_OR_CONN_STATUS, "ORCONN" },
+ { EVENT_BANDWIDTH_USED, "BW" },
+ { EVENT_DEBUG_MSG, "DEBUG" },
+ { EVENT_INFO_MSG, "INFO" },
+ { EVENT_NOTICE_MSG, "NOTICE" },
+ { EVENT_WARN_MSG, "WARN" },
+ { EVENT_ERR_MSG, "ERR" },
+ { EVENT_NEW_DESC, "NEWDESC" },
+ { EVENT_ADDRMAP, "ADDRMAP" },
+ { EVENT_AUTHDIR_NEWDESCS, "AUTHDIR_NEWDESCS" },
+ { EVENT_DESCCHANGED, "DESCCHANGED" },
+ { EVENT_NS, "NS" },
+ { EVENT_STATUS_GENERAL, "STATUS_GENERAL" },
+ { EVENT_STATUS_CLIENT, "STATUS_CLIENT" },
+ { EVENT_STATUS_SERVER, "STATUS_SERVER" },
+ { EVENT_GUARD, "GUARD" },
+ { EVENT_STREAM_BANDWIDTH_USED, "STREAM_BW" },
+ { EVENT_CLIENTS_SEEN, "CLIENTS_SEEN" },
+ { EVENT_NEWCONSENSUS, "NEWCONSENSUS" },
+ { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" },
+ { EVENT_SIGNAL, "SIGNAL" },
+ { EVENT_CONF_CHANGED, "CONF_CHANGED"},
+ { 0, NULL },
+};
+
/** Called when we get a SETEVENTS message: update conn->event_mask,
* and reply with DONE or ERROR. */
static int
handle_control_setevents(control_connection_t *conn, uint32_t len,
const char *body)
{
- uint16_t event_code;
+ int event_code = -1;
uint32_t event_mask = 0;
smartlist_t *events = smartlist_create();
@@ -928,56 +969,22 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
{
if (!strcasecmp(ev, "EXTENDED")) {
continue;
- } else if (!strcasecmp(ev, "CIRC"))
- event_code = EVENT_CIRCUIT_STATUS;
- else if (!strcasecmp(ev, "STREAM"))
- event_code = EVENT_STREAM_STATUS;
- else if (!strcasecmp(ev, "ORCONN"))
- event_code = EVENT_OR_CONN_STATUS;
- else if (!strcasecmp(ev, "BW"))
- event_code = EVENT_BANDWIDTH_USED;
- else if (!strcasecmp(ev, "DEBUG"))
- event_code = EVENT_DEBUG_MSG;
- else if (!strcasecmp(ev, "INFO"))
- event_code = EVENT_INFO_MSG;
- else if (!strcasecmp(ev, "NOTICE"))
- event_code = EVENT_NOTICE_MSG;
- else if (!strcasecmp(ev, "WARN"))
- event_code = EVENT_WARN_MSG;
- else if (!strcasecmp(ev, "ERR"))
- event_code = EVENT_ERR_MSG;
- else if (!strcasecmp(ev, "NEWDESC"))
- event_code = EVENT_NEW_DESC;
- else if (!strcasecmp(ev, "ADDRMAP"))
- event_code = EVENT_ADDRMAP;
- else if (!strcasecmp(ev, "AUTHDIR_NEWDESCS"))
- event_code = EVENT_AUTHDIR_NEWDESCS;
- else if (!strcasecmp(ev, "DESCCHANGED"))
- event_code = EVENT_DESCCHANGED;
- else if (!strcasecmp(ev, "NS"))
- event_code = EVENT_NS;
- else if (!strcasecmp(ev, "STATUS_GENERAL"))
- event_code = EVENT_STATUS_GENERAL;
- else if (!strcasecmp(ev, "STATUS_CLIENT"))
- event_code = EVENT_STATUS_CLIENT;
- else if (!strcasecmp(ev, "STATUS_SERVER"))
- event_code = EVENT_STATUS_SERVER;
- else if (!strcasecmp(ev, "GUARD"))
- event_code = EVENT_GUARD;
- else if (!strcasecmp(ev, "STREAM_BW"))
- event_code = EVENT_STREAM_BANDWIDTH_USED;
- else if (!strcasecmp(ev, "CLIENTS_SEEN"))
- event_code = EVENT_CLIENTS_SEEN;
- else if (!strcasecmp(ev, "NEWCONSENSUS"))
- event_code = EVENT_NEWCONSENSUS;
- else if (!strcasecmp(ev, "BUILDTIMEOUT_SET"))
- event_code = EVENT_BUILDTIMEOUT_SET;
- else {
- connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
- ev);
- SMARTLIST_FOREACH(events, char *, e, tor_free(e));
- smartlist_free(events);
- return 0;
+ } else {
+ int i;
+ for (i = 0; control_event_table[i].event_name != NULL; ++i) {
+ if (!strcasecmp(ev, control_event_table[i].event_name)) {
+ event_code = control_event_table[i].event_code;
+ break;
+ }
+ }
+
+ if (event_code == -1) {
+ connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
+ ev);
+ SMARTLIST_FOREACH(events, char *, e, tor_free(e));
+ smartlist_free(events);
+ return 0;
+ }
}
event_mask |= (1 << event_code);
}
@@ -1039,7 +1046,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
const char *body)
{
int used_quoted_string = 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const char *errstr = NULL;
char *password;
size_t password_len;
@@ -1048,7 +1055,10 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
int bad_cookie=0, bad_password=0;
smartlist_t *sl = NULL;
- if (TOR_ISXDIGIT(body[0])) {
+ if (!len) {
+ password = tor_strdup("");
+ password_len = 0;
+ } else if (TOR_ISXDIGIT(body[0])) {
cp = body;
while (TOR_ISXDIGIT(*cp))
++cp;
@@ -1065,9 +1075,6 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
tor_free(password);
return 0;
}
- } else if (TOR_ISSPACE(body[0])) {
- password = tor_strdup("");
- password_len = 0;
} else {
if (!decode_escaped_string(body, len, &password, &password_len)) {
connection_write_str_to_buf("551 Invalid quoted string. You need "
@@ -1248,7 +1255,7 @@ handle_control_signal(control_connection_t *conn, uint32_t len,
send_control_done(conn);
/* Flush the "done" first if the signal might make us shut down. */
if (sig == SIGTERM || sig == SIGINT)
- connection_handle_write(TO_CONN(conn), 1);
+ connection_flush(TO_CONN(conn));
process_signal(sig);
@@ -1371,17 +1378,24 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
if (!strcmp(question, "version")) {
*answer = tor_strdup(get_version());
} else if (!strcmp(question, "config-file")) {
- *answer = tor_strdup(get_torrc_fname());
+ *answer = tor_strdup(get_torrc_fname(0));
+ } else if (!strcmp(question, "config-defaults-file")) {
+ *answer = tor_strdup(get_torrc_fname(1));
} else if (!strcmp(question, "config-text")) {
*answer = options_dump(get_options(), 1);
} else if (!strcmp(question, "info/names")) {
*answer = list_getinfo_options();
} else if (!strcmp(question, "events/names")) {
- *answer = tor_strdup("CIRC STREAM ORCONN BW DEBUG INFO NOTICE WARN ERR "
- "NEWDESC ADDRMAP AUTHDIR_NEWDESCS DESCCHANGED "
- "NS STATUS_GENERAL STATUS_CLIENT STATUS_SERVER "
- "GUARD STREAM_BW CLIENTS_SEEN NEWCONSENSUS "
- "BUILDTIMEOUT_SET");
+ int i;
+ smartlist_t *event_names = smartlist_create();
+
+ for (i = 0; control_event_table[i].event_name != NULL; ++i) {
+ smartlist_add(event_names, (char *)control_event_table[i].event_name);
+ }
+
+ *answer = smartlist_join_strings(event_names, " ", 0, NULL);
+
+ smartlist_free(event_names);
} else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
} else if (!strcmp(question, "address")) {
@@ -1391,6 +1405,61 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
return -1;
}
*answer = tor_dup_ip(addr);
+ } else if (!strcmp(question, "traffic/read")) {
+ tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_read()));
+ } else if (!strcmp(question, "traffic/written")) {
+ tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_written()));
+ } else if (!strcmp(question, "process/pid")) {
+ int myPid = -1;
+
+ #ifdef MS_WINDOWS
+ myPid = _getpid();
+ #else
+ myPid = getpid();
+ #endif
+
+ tor_asprintf(answer, "%d", myPid);
+ } else if (!strcmp(question, "process/uid")) {
+ #ifdef MS_WINDOWS
+ *answer = tor_strdup("-1");
+ #else
+ int myUid = geteuid();
+ tor_asprintf(answer, "%d", myUid);
+ #endif
+ } else if (!strcmp(question, "process/user")) {
+ #ifdef MS_WINDOWS
+ *answer = tor_strdup("");
+ #else
+ int myUid = geteuid();
+ struct passwd *myPwEntry = getpwuid(myUid);
+
+ if (myPwEntry) {
+ *answer = tor_strdup(myPwEntry->pw_name);
+ } else {
+ *answer = tor_strdup("");
+ }
+ #endif
+ } else if (!strcmp(question, "process/descriptor-limit")) {
+ /** platform specifc limits are from the set_max_file_descriptors function
+ * of src/common/compat.c */
+ /* XXXX023 This is duplicated code from compat.c; it should turn into a
+ * function. */
+ #ifdef HAVE_GETRLIMIT
+ struct rlimit descriptorLimit;
+
+ if (getrlimit(RLIMIT_NOFILE, &descriptorLimit) == 0) {
+ tor_asprintf(answer, U64_FORMAT,
+ U64_PRINTF_ARG(descriptorLimit.rlim_max));
+ } else {
+ *answer = tor_strdup("-1");
+ }
+ #elif defined(CYGWIN) || defined(__CYGWIN__)
+ *answer = tor_strdup("3200");
+ #elif defined(MS_WINDOWS)
+ *answer = tor_strdup("15000");
+ #else
+ *answer = tor_strdup("15000");
+ #endif
} else if (!strcmp(question, "dir-usage")) {
*answer = directory_dump_request_log();
} else if (!strcmp(question, "fingerprint")) {
@@ -1416,8 +1485,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
* NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
* not be NUL-terminated. */
static char *
-munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri,
- signed_descriptor_t *ei)
+munge_extrainfo_into_routerinfo(const char *ri_body,
+ const signed_descriptor_t *ri,
+ const signed_descriptor_t *ei)
{
char *out = NULL, *outp;
int i;
@@ -1519,16 +1589,19 @@ getinfo_helper_dir(control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg)
{
+ const routerinfo_t *ri;
(void) control_conn;
if (!strcmpstart(question, "desc/id/")) {
- routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
+ ri = router_get_by_hexdigest(question+strlen("desc/id/"));
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
*answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
}
} else if (!strcmpstart(question, "desc/name/")) {
- routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
+ /* XXX023 Setting 'warn_if_unnamed' here is a bit silly -- the
+ * warning goes to the user, not to the controller. */
+ ri = router_get_by_nickname(question+strlen("desc/name/"),1);
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
@@ -1538,7 +1611,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_create();
if (routerlist && routerlist->routers) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
+ SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
@@ -1554,7 +1627,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_create();
if (routerlist && routerlist->routers) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
+ SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
signed_descriptor_t *ei = extrainfo_get_by_descriptor_digest(
@@ -1571,9 +1644,28 @@ getinfo_helper_dir(control_connection_t *control_conn,
*answer = smartlist_join_strings(sl, "", 0, NULL);
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
+ } else if (!strcmpstart(question, "md/id/")) {
+ const node_t *node = node_get_by_hex_id(question+strlen("md/id/"));
+ const microdesc_t *md = NULL;
+ if (node) md = node->md;
+ if (md) {
+ tor_assert(md->body);
+ *answer = tor_strndup(md->body, md->bodylen);
+ }
+ } else if (!strcmpstart(question, "md/name/")) {
+ /* XXX023 Setting 'warn_if_unnamed' here is a bit silly -- the
+ * warning goes to the user, not to the controller. */
+ const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 1);
+ /* XXXX duplicated code */
+ const microdesc_t *md = NULL;
+ if (node) md = node->md;
+ if (md) {
+ tor_assert(md->body);
+ *answer = tor_strndup(md->body, md->bodylen);
+ }
} else if (!strcmpstart(question, "desc-annotations/id/")) {
- routerinfo_t *ri = router_get_by_hexdigest(question+
- strlen("desc-annotations/id/"));
+ ri = router_get_by_hexdigest(question+
+ strlen("desc-annotations/id/"));
if (ri) {
const char *annotations =
signed_descriptor_get_annotations(&ri->cache_info);
@@ -1733,7 +1825,7 @@ getinfo_helper_events(control_connection_t *control_conn,
char buf[256];
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
const char *state;
- edge_connection_t *conn;
+ entry_connection_t *conn;
char *s;
size_t slen;
circuit_t *circ;
@@ -1743,8 +1835,8 @@ getinfo_helper_events(control_connection_t *control_conn,
base_conn->state == AP_CONN_STATE_SOCKS_WAIT ||
base_conn->state == AP_CONN_STATE_NATD_WAIT)
continue;
- conn = TO_EDGE_CONN(base_conn);
- switch (conn->_base.state)
+ conn = TO_ENTRY_CONN(base_conn);
+ switch (base_conn->state)
{
case AP_CONN_STATE_CONTROLLER_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
@@ -1763,17 +1855,17 @@ getinfo_helper_events(control_connection_t *control_conn,
state = "SUCCEEDED"; break;
default:
log_warn(LD_BUG, "Asked for stream in unknown state %d",
- conn->_base.state);
+ base_conn->state);
continue;
}
- circ = circuit_get_by_edge_conn(conn);
+ circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
write_stream_target_to_buf(conn, buf, sizeof(buf));
slen = strlen(buf)+strlen(state)+32;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %lu %s",
- (unsigned long) conn->_base.global_identifier,state,
+ (unsigned long) base_conn->global_identifier,state,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf);
@@ -1886,7 +1978,7 @@ getinfo_helper_events(control_connection_t *control_conn,
} else if (!strcmp(question, "status/version/num-versioning") ||
!strcmp(question, "status/version/num-concurring")) {
char s[33];
- tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
+ tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_DIRINFO));
*answer = tor_strdup(s);
log_warn(LD_GENERAL, "%s is deprecated; it no longer gives useful "
"information", question);
@@ -1934,6 +2026,7 @@ typedef struct getinfo_item_t {
static const getinfo_item_t getinfo_items[] = {
ITEM("version", misc, "The current version of Tor."),
ITEM("config-file", misc, "Current location of the \"torrc\" file."),
+ ITEM("config-defaults-file", misc, "Current location of the defaults file."),
ITEM("config-text", misc,
"Return the string that would be written by a saveconf command."),
ITEM("accounting/bytes", accounting,
@@ -1965,6 +2058,8 @@ static const getinfo_item_t getinfo_items[] = {
ITEM("desc/all-recent", dir,
"All non-expired, non-superseded router descriptors."),
ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */
+ PREFIX("md/id/", dir, "Microdescriptors by ID"),
+ PREFIX("md/name/", dir, "Microdescriptors by name"),
PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."),
PREFIX("net/listeners/", listeners, "Bound addresses by type"),
ITEM("ns/all", networkstatus,
@@ -2004,6 +2099,14 @@ static const getinfo_item_t getinfo_items[] = {
"Number of versioning authorities agreeing on the status of the "
"current version"),
ITEM("address", misc, "IP address of this Tor host, if we can guess it."),
+ ITEM("traffic/read", misc,"Bytes read since the process was started."),
+ ITEM("traffic/written", misc,
+ "Bytes written since the process was started."),
+ ITEM("process/pid", misc, "Process id belonging to the main tor process."),
+ ITEM("process/uid", misc, "User id running the tor process."),
+ ITEM("process/user", misc,
+ "Username under which the tor process is running."),
+ ITEM("process/descriptor-limit", misc, "File descriptor limit."),
ITEM("dir-usage", misc, "Breakdown of bytes transferred over DirPort."),
PREFIX("desc-annotations/id/", dir, "Router annotations by hexdigest."),
PREFIX("dir/server/", dir,"Router descriptors as retrieved from a DirPort."),
@@ -2213,7 +2316,7 @@ static int
handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
const char *body)
{
- smartlist_t *router_nicknames=NULL, *routers=NULL;
+ smartlist_t *router_nicknames=NULL, *nodes=NULL;
origin_circuit_t *circ = NULL;
int zero_circ;
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
@@ -2244,8 +2347,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if ((smartlist_len(args) == 1) ||
(smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
// "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
- circ = circuit_launch_by_router(intended_purpose, NULL,
- CIRCLAUNCH_NEED_CAPACITY);
+ circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
if (!circ) {
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
} else {
@@ -2273,17 +2375,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
- routers = smartlist_create();
+ nodes = smartlist_create();
SMARTLIST_FOREACH(router_nicknames, const char *, n,
{
- routerinfo_t *r = router_get_by_nickname(n, 1);
- if (!r) {
+ const node_t *node = node_get_by_nickname(n, 1);
+ if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
}
- smartlist_add(routers, r);
+ if (!node_has_descriptor(node)) {
+ connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n);
+ goto done;
+ }
+ smartlist_add(nodes, (void*)node);
});
- if (!smartlist_len(routers)) {
+ if (!smartlist_len(nodes)) {
connection_write_str_to_buf("512 No router names provided\r\n", conn);
goto done;
}
@@ -2294,9 +2400,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
}
/* now circ refers to something that is ready to be extended */
- SMARTLIST_FOREACH(routers, routerinfo_t *, r,
+ SMARTLIST_FOREACH(nodes, const node_t *, node,
{
- extend_info_t *info = extend_info_from_router(r);
+ extend_info_t *info = extend_info_from_node(node);
+ tor_assert(info); /* True, since node_has_descriptor(node) == true */
circuit_append_new_exit(circ, info);
extend_info_free(info);
});
@@ -2330,7 +2437,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
done:
SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
smartlist_free(router_nicknames);
- smartlist_free(routers);
+ smartlist_free(nodes);
return 0;
}
@@ -2381,7 +2488,7 @@ static int
handle_control_attachstream(control_connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn = NULL;
+ entry_connection_t *ap_conn = NULL;
origin_circuit_t *circ = NULL;
int zero_circ;
smartlist_t *args;
@@ -2417,9 +2524,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
if (!ap_conn || (!zero_circ && !circ) || !hop_line_ok)
return 0;
- if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT &&
- ap_conn->_base.state != AP_CONN_STATE_CONNECT_WAIT &&
- ap_conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
+ if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT &&
+ ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONNECT_WAIT &&
+ ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_RESOLVE_WAIT) {
connection_write_str_to_buf(
"555 Connection is not managed by controller.\r\n",
conn);
@@ -2427,15 +2534,16 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Do we need to detach it first? */
- if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT) {
- circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn);
- connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT);
+ if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT) {
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn);
+ connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT);
/* Un-mark it as ending, since we're going to reuse it. */
- ap_conn->edge_has_sent_end = 0;
- ap_conn->end_reason = 0;
+ edge_conn->edge_has_sent_end = 0;
+ edge_conn->end_reason = 0;
if (tmpcirc)
- circuit_detach_stream(tmpcirc,ap_conn);
- ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
+ circuit_detach_stream(tmpcirc, edge_conn);
+ TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
}
if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) {
@@ -2446,16 +2554,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Is this a single hop circuit? */
if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
- routerinfo_t *r = NULL;
- char* exit_digest;
+ const node_t *node = NULL;
+ char *exit_digest;
if (circ->build_state &&
circ->build_state->chosen_exit &&
!tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
exit_digest = circ->build_state->chosen_exit->identity_digest;
- r = router_get_by_digest(exit_digest);
+ node = node_get_by_id(exit_digest);
}
/* Do both the client and relay allow one-hop exit circuits? */
- if (!r || !r->allow_single_hop_exits ||
+ if (!node ||
+ !node_allows_single_hop_exits(node) ||
!get_options()->AllowSingleHopCircuits) {
connection_write_str_to_buf(
"551 Can't attach stream to this one-hop circuit.\r\n", conn);
@@ -2556,7 +2665,7 @@ static int
handle_control_redirectstream(control_connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn = NULL;
+ entry_connection_t *ap_conn = NULL;
char *new_addr = NULL;
uint16_t new_port = 0;
smartlist_t *args;
@@ -2604,7 +2713,7 @@ static int
handle_control_closestream(control_connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn=NULL;
+ entry_connection_t *ap_conn=NULL;
uint8_t reason=0;
smartlist_t *args;
int ok;
@@ -2749,7 +2858,7 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
connection_mark_for_close(TO_CONN(conn));
goto done;
} else {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int cookies = options->CookieAuthentication;
char *cfile = get_cookie_file();
char *esc_cfile = esc_for_log(cfile);
@@ -2827,8 +2936,6 @@ int
connection_control_finished_flushing(control_connection_t *conn)
{
tor_assert(conn);
-
- connection_stop_writing(TO_CONN(conn));
return 0;
}
@@ -2900,6 +3007,17 @@ is_valid_initial_command(control_connection_t *conn, const char *cmd)
* interfaces is broken. */
#define MAX_COMMAND_LINE_LENGTH (1024*1024)
+static int
+peek_connection_has_control0_command(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return peek_evbuffer_has_control0_command(input);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return peek_buf_has_control0_command(conn->inbuf);
+ }
+}
+
/** Called when data has arrived on a v1 control connection: Try to fetch
* commands from conn->inbuf, and execute them.
*/
@@ -2922,7 +3040,7 @@ connection_control_process_inbuf(control_connection_t *conn)
}
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH &&
- peek_buf_has_control0_command(conn->_base.inbuf)) {
+ peek_connection_has_control0_command(TO_CONN(conn))) {
/* Detect v0 commands and send a "no more v0" message. */
size_t body_len;
char buf[128];
@@ -2934,8 +3052,8 @@ connection_control_process_inbuf(control_connection_t *conn)
body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
set_uint16(buf+0, htons(body_len));
connection_write_to_buf(buf, 4+body_len, TO_CONN(conn));
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+
+ connection_mark_and_flush(TO_CONN(conn));
return 0;
}
@@ -2946,7 +3064,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* First, fetch a line. */
do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
- r = fetch_from_buf_line(conn->_base.inbuf,
+ r = connection_fetch_from_buf_line(TO_CONN(conn),
conn->incoming_cmd+conn->incoming_cmd_cur_len,
&data_len);
if (r == 0)
@@ -2956,8 +3074,7 @@ connection_control_process_inbuf(control_connection_t *conn)
if (data_len + conn->incoming_cmd_cur_len > MAX_COMMAND_LINE_LENGTH) {
connection_write_str_to_buf("500 Line too long.\r\n", conn);
connection_stop_reading(TO_CONN(conn));
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
conn->incoming_cmd_len *= 2;
@@ -3004,7 +3121,7 @@ connection_control_process_inbuf(control_connection_t *conn)
args = conn->incoming_cmd+cmd_len+1;
tor_assert(data_len>(size_t)cmd_len);
data_len -= (cmd_len+1); /* skip the command and NUL we added after it */
- while (*args == ' ' || *args == '\t') {
+ while (TOR_ISSPACE(*args)) {
++args;
--data_len;
}
@@ -3017,8 +3134,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* Otherwise, Quit is always valid. */
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
connection_write_str_to_buf("250 closing connection\r\n", conn);
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
return 0;
}
@@ -3177,7 +3293,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
* <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
* failure. */
static int
-write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
+write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
{
char buf2[256];
if (conn->chosen_exit_name)
@@ -3188,8 +3304,8 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
if (tor_snprintf(buf, len, "%s%s%s:%d",
conn->socks_request->address,
conn->chosen_exit_name ? buf2 : "",
- !conn->chosen_exit_name &&
- connection_edge_is_rendezvous_stream(conn) ? ".onion" : "",
+ !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
+ ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
conn->socks_request->port)<0)
return -1;
return 0;
@@ -3198,7 +3314,7 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
/** Something has happened to the stream associated with AP connection
* <b>conn</b>: tell any interested control connections. */
int
-control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
+control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
int reason_code)
{
char reason_buf[64];
@@ -3270,7 +3386,7 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW) {
tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
- TO_CONN(conn)->address, TO_CONN(conn)->port );
+ ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
} else {
addrport_buf[0] = '\0';
}
@@ -3278,12 +3394,12 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW_RESOLVE) {
purpose = " PURPOSE=DNS_REQUEST";
} else if (tp == STREAM_EVENT_NEW) {
- if (conn->is_dns_request ||
+ if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request ||
(conn->socks_request &&
SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)))
purpose = " PURPOSE=DNS_REQUEST";
else if (conn->use_begindir) {
- connection_t *linked = TO_CONN(conn)->linked_conn;
+ connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
int linked_dir_purpose = -1;
if (linked && linked->type == CONN_TYPE_DIR)
linked_dir_purpose = linked->purpose;
@@ -3295,12 +3411,13 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
purpose = " PURPOSE=USER";
}
- circ = circuit_get_by_edge_conn(conn);
+ circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control_event(EVENT_STREAM_STATUS, ALL_FORMATS,
"650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n",
- U64_PRINTF_ARG(conn->_base.global_identifier), status,
+ U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier),
+ status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf, reason_buf, addrport_buf, purpose);
@@ -3316,10 +3433,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
static void
orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
{
- routerinfo_t *ri = router_get_by_digest(conn->identity_digest);
- if (ri) {
+ const node_t *node = node_get_by_id(conn->identity_digest);
+ if (node) {
tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
- router_get_verbose_nickname(name, ri);
+ node_get_verbose_nickname(node, name);
} else if (! tor_digest_is_zero(conn->identity_digest)) {
name[0] = '$';
base16_encode(name+1, len-1, conn->identity_digest,
@@ -3636,7 +3753,7 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses,
smartlist_add(strs, tor_strdup("650+"));
smartlist_add(strs, tor_strdup(event_string));
smartlist_add(strs, tor_strdup("\r\n"));
- SMARTLIST_FOREACH(statuses, routerstatus_t *, rs,
+ SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
{
s = networkstatus_getinfo_helper_single(rs);
if (!s) continue;
@@ -3724,10 +3841,46 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
return 0;
}
+/** Called when a signal has been processed from signal_callback */
+int
+control_event_signal(uintptr_t signal)
+{
+ const char *signal_string = NULL;
+
+ if (!control_event_is_interesting(EVENT_SIGNAL))
+ return 0;
+
+ switch (signal) {
+ case SIGHUP:
+ signal_string = "RELOAD";
+ break;
+ case SIGUSR1:
+ signal_string = "DUMP";
+ break;
+ case SIGUSR2:
+ signal_string = "DEBUG";
+ break;
+ case SIGNEWNYM:
+ signal_string = "NEWNYM";
+ break;
+ case SIGCLEARDNSCACHE:
+ signal_string = "CLEARDNSCACHE";
+ break;
+ default:
+ log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
+ (unsigned long)signal);
+ return -1;
+ }
+
+ send_control_event(EVENT_SIGNAL, ALL_FORMATS, "650 SIGNAL %s\r\n",
+ signal_string);
+ return 0;
+}
+
/** Called when a single local_routerstatus_t has changed: Sends an NS event
* to any controller that cares. */
int
-control_event_networkstatus_changed_single(routerstatus_t *rs)
+control_event_networkstatus_changed_single(const routerstatus_t *rs)
{
smartlist_t *statuses;
int r;
@@ -3736,7 +3889,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs)
return 0;
statuses = smartlist_create();
- smartlist_add(statuses, rs);
+ smartlist_add(statuses, (void*)rs);
r = control_event_networkstatus_changed(statuses);
smartlist_free(statuses);
return r;
@@ -3861,9 +4014,9 @@ control_event_guard(const char *nickname, const char *digest,
{
char buf[MAX_VERBOSE_NICKNAME_LEN+1];
- routerinfo_t *ri = router_get_by_digest(digest);
- if (ri) {
- router_get_verbose_nickname(buf, ri);
+ const node_t *node = node_get_by_id(digest);
+ if (node) {
+ node_get_verbose_nickname(node, buf);
} else {
tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
}
@@ -3873,12 +4026,45 @@ control_event_guard(const char *nickname, const char *digest,
return 0;
}
+/** Called when a configuration option changes. This is generally triggered
+ * by SETCONF requests and RELOAD/SIGHUP signals. The <b>elements</b> is
+ * a smartlist_t containing (key, value, ...) pairs in sequence.
+ * <b>value</b> can be NULL. */
+int
+control_event_conf_changed(smartlist_t *elements)
+{
+ int i;
+ char *result;
+ smartlist_t *lines;
+ if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) ||
+ smartlist_len(elements) == 0) {
+ return 0;
+ }
+ lines = smartlist_create();
+ for (i = 0; i < smartlist_len(elements); i += 2) {
+ char *k = smartlist_get(elements, i);
+ char *v = smartlist_get(elements, i+1);
+ if (v == NULL) {
+ smartlist_asprintf_add(lines, "650-%s", k);
+ } else {
+ smartlist_asprintf_add(lines, "650-%s=%s", k, v);
+ }
+ }
+ result = smartlist_join_strings(lines, "\r\n", 0, NULL);
+ send_control_event(EVENT_CONF_CHANGED, 0,
+ "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", result);
+ tor_free(result);
+ SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
+ smartlist_free(lines);
+ return 0;
+}
+
/** Helper: Return a newly allocated string containing a path to the
* file where we store our authentication cookie. */
static char *
get_cookie_file(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->CookieAuthFile && strlen(options->CookieAuthFile)) {
return tor_strdup(options->CookieAuthFile);
} else {
@@ -4146,6 +4332,7 @@ control_event_bootstrap_problem(const char *warn, int reason)
const char *tag, *summary;
char buf[BOOTSTRAP_MSG_LEN];
const char *recommendation = "ignore";
+ int severity;
/* bootstrap_percent must not be in "undefined" state here. */
tor_assert(status >= 0);
@@ -4170,12 +4357,17 @@ control_event_bootstrap_problem(const char *warn, int reason)
status--; /* find a recognized status string based on current progress */
status = bootstrap_percent; /* set status back to the actual number */
- log_fn(!strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO,
+ severity = !strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO;
+
+ log_fn(severity,
LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; "
"count %d; recommendation %s)",
status, summary, warn,
orconn_end_reason_to_control_string(reason),
bootstrap_problems, recommendation);
+
+ connection_or_report_broken_states(severity, LD_HANDSHAKE);
+
tor_snprintf(buf, sizeof(buf),
"BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
"COUNT=%d RECOMMENDATION=%s",
diff --git a/src/or/control.h b/src/or/control.h
index ddea4cd548..0d9acd26ef 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -37,7 +37,7 @@ int control_event_is_interesting(int event);
int control_event_circuit_status(origin_circuit_t *circ,
circuit_status_event_t e, int reason);
-int control_event_stream_status(edge_connection_t *conn,
+int control_event_stream_status(entry_connection_t *conn,
stream_status_event_t e,
int reason);
int control_event_or_conn_status(or_connection_t *conn,
@@ -57,7 +57,7 @@ int control_event_my_descriptor_changed(void);
int control_event_networkstatus_changed(smartlist_t *statuses);
int control_event_newconsensus(const networkstatus_t *consensus);
-int control_event_networkstatus_changed_single(routerstatus_t *rs);
+int control_event_networkstatus_changed_single(const routerstatus_t *rs);
int control_event_general_status(int severity, const char *format, ...)
CHECK_PRINTF(2,3);
int control_event_client_status(int severity, const char *format, ...)
@@ -66,8 +66,10 @@ int control_event_server_status(int severity, const char *format, ...)
CHECK_PRINTF(2,3);
int control_event_guard(const char *nickname, const char *digest,
const char *status);
+int control_event_conf_changed(smartlist_t *elements);
int control_event_buildtimeout_set(const circuit_build_times_t *cbt,
buildtimeout_set_event_t type);
+int control_event_signal(uintptr_t signal);
int init_cookie_authentication(int enabled);
smartlist_t *decode_hashed_passwords(config_line_t *passwords);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index c5e4863f7f..914003790a 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -62,7 +62,6 @@ connection_cpu_finished_flushing(connection_t *conn)
{
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CPUWORKER);
- connection_stop_writing(conn);
return 0;
}
@@ -141,13 +140,13 @@ connection_cpu_process_inbuf(connection_t *conn)
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CPUWORKER);
- if (!buf_datalen(conn->inbuf))
+ if (!connection_get_inbuf_len(conn))
return 0;
if (conn->state == CPUWORKER_STATE_BUSY_ONION) {
- if (buf_datalen(conn->inbuf) < LEN_ONION_RESPONSE) /* answer available? */
+ if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE)
return 0; /* not yet */
- tor_assert(buf_datalen(conn->inbuf) == LEN_ONION_RESPONSE);
+ tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE);
connection_fetch_from_buf(&success,1,conn);
connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);
@@ -367,7 +366,7 @@ spawn_cpuworker(void)
static void
spawn_enough_cpuworkers(void)
{
- int num_cpuworkers_needed = get_options()->NumCPUs;
+ int num_cpuworkers_needed = get_num_cpus(get_options());
if (num_cpuworkers_needed < MIN_CPUWORKERS)
num_cpuworkers_needed = MIN_CPUWORKERS;
@@ -446,9 +445,19 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker,
{
char qbuf[1];
char tag[TAG_LEN];
+ time_t now = approx_time();
+ static time_t last_culled_cpuworkers = 0;
- cull_wedged_cpuworkers();
- spawn_enough_cpuworkers();
+ /* Checking for wedged cpuworkers requires a linear search over all
+ * connections, so let's do it only once a minute.
+ */
+#define CULL_CPUWORKERS_INTERVAL 60
+
+ if (last_culled_cpuworkers + CULL_CPUWORKERS_INTERVAL <= now) {
+ cull_wedged_cpuworkers();
+ spawn_enough_cpuworkers();
+ last_culled_cpuworkers = now;
+ }
if (1) {
if (num_cpuworkers_busy == num_cpuworkers) {
diff --git a/src/or/directory.c b/src/or/directory.c
index 52fec6b61a..776b7a25f9 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -15,7 +15,9 @@
#include "dirvote.h"
#include "geoip.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -78,6 +80,8 @@ static void dir_routerdesc_download_failed(smartlist_t *failed,
int router_purpose,
int was_extrainfo,
int was_descriptor_digests);
+static void dir_microdesc_download_failed(smartlist_t *failed,
+ int status_code);
static void note_client_request(int purpose, int compressed, size_t bytes);
static int client_likes_consensus(networkstatus_t *v, const char *want_url);
@@ -137,26 +141,28 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
+ dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ dir_purpose == DIR_PURPOSE_FETCH_MICRODESC)
return 0;
return 1;
}
-/** Return a newly allocated string describing <b>auth</b>. */
-char *
-authority_type_to_string(authority_type_t auth)
+/** Return a newly allocated string describing <b>auth</b>. Only describes
+ * authority features. */
+static char *
+authdir_type_to_string(dirinfo_type_t auth)
{
char *result;
smartlist_t *lst = smartlist_create();
- if (auth & V1_AUTHORITY)
+ if (auth & V1_DIRINFO)
smartlist_add(lst, (void*)"V1");
- if (auth & V2_AUTHORITY)
+ if (auth & V2_DIRINFO)
smartlist_add(lst, (void*)"V2");
- if (auth & V3_AUTHORITY)
+ if (auth & V3_DIRINFO)
smartlist_add(lst, (void*)"V3");
- if (auth & BRIDGE_AUTHORITY)
+ if (auth & BRIDGE_DIRINFO)
smartlist_add(lst, (void*)"Bridge");
- if (auth & HIDSERV_AUTHORITY)
+ if (auth & HIDSERV_DIRINFO)
smartlist_add(lst, (void*)"Hidden service");
if (smartlist_len(lst)) {
result = smartlist_join_strings(lst, ", ", 0, NULL);
@@ -201,6 +207,8 @@ dir_conn_purpose_to_string(int purpose)
return "hidden-service v2 descriptor fetch";
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
return "hidden-service v2 descriptor upload";
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ return "microdescriptor fetch";
}
log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
@@ -213,17 +221,19 @@ dir_conn_purpose_to_string(int purpose)
int
router_supports_extrainfo(const char *identity_digest, int is_authority)
{
- routerinfo_t *ri = router_get_by_digest(identity_digest);
+ const node_t *node = node_get_by_id(identity_digest);
- if (ri) {
- if (ri->caches_extra_info)
+ if (node && node->ri) {
+ if (node->ri->caches_extra_info)
return 1;
- if (is_authority && ri->platform &&
- tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
+ if (is_authority && node->ri->platform &&
+ tor_version_as_new_as(node->ri->platform,
+ "Tor 0.2.0.0-alpha-dev (r10070)"))
return 1;
}
if (is_authority) {
- routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
+ const routerstatus_t *rs =
+ router_get_consensus_status_by_id(identity_digest);
if (rs && rs->version_supports_extrainfo_upload)
return 1;
}
@@ -242,7 +252,7 @@ int
directories_have_accepted_server_descriptor(void)
{
smartlist_t *servers = router_get_trusted_dir_servers();
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
if ((d->type & options->_PublishServerDescriptor) &&
d->has_accepted_serverdesc) {
@@ -271,11 +281,11 @@ directories_have_accepted_server_descriptor(void)
*/
void
directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
- authority_type_t type,
+ dirinfo_type_t type,
const char *payload,
size_t payload_len, size_t extrainfo_len)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int post_via_tor;
smartlist_t *dirservers = router_get_trusted_dir_servers();
int found = 0;
@@ -296,8 +306,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
if (exclude_self && router_digest_is_me(ds->digest))
continue;
- if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, rs)) {
+ if (options->StrictNodes &&
+ routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
"it's in our ExcludedNodes list and StrictNodes is set. "
"Skipping.",
@@ -324,7 +334,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
NULL, payload, upload_len, 0);
} SMARTLIST_FOREACH_END(ds);
if (!found) {
- char *s = authority_type_to_string(type);
+ char *s = authdir_type_to_string(type);
log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
"of type '%s', but no authorities of that type listed!", s);
tor_free(s);
@@ -341,39 +351,44 @@ void
directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource, int pds_flags)
{
- routerstatus_t *rs = NULL;
- or_options_t *options = get_options();
+ const routerstatus_t *rs = NULL;
+ const or_options_t *options = get_options();
int prefer_authority = directory_fetches_from_authorities(options);
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
- authority_type_t type;
+ dirinfo_type_t type;
time_t if_modified_since = 0;
/* FFFF we could break this switch into its own function, and call
* it elsewhere in directory.c. -RD */
switch (dir_purpose) {
case DIR_PURPOSE_FETCH_EXTRAINFO:
- type = EXTRAINFO_CACHE |
- (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
- V3_AUTHORITY);
+ type = EXTRAINFO_DIRINFO |
+ (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
+ V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
- type = V2_AUTHORITY;
+ type = V2_DIRINFO;
prefer_authority = 1; /* Only v2 authorities have these anyway. */
break;
case DIR_PURPOSE_FETCH_SERVERDESC:
- type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
- V3_AUTHORITY);
+ type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
+ V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_RENDDESC:
- type = HIDSERV_AUTHORITY;
+ type = HIDSERV_DIRINFO;
break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
- type = V3_AUTHORITY;
+ case DIR_PURPOSE_FETCH_CERTIFICATE:
+ type = V3_DIRINFO;
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
- case DIR_PURPOSE_FETCH_CERTIFICATE:
- type = V3_AUTHORITY;
+ type = V3_DIRINFO;
+ if (resource && !strcmp(resource,"microdesc"))
+ type |= MICRODESC_DIRINFO;
+ break;
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ type = MICRODESC_DIRINFO;
break;
default:
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
@@ -381,25 +396,42 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
- networkstatus_t *v = networkstatus_get_latest_consensus();
- if (v)
- if_modified_since = v->valid_after + 180;
+ int flav = FLAV_NS;
+ networkstatus_t *v;
+ if (resource)
+ flav = networkstatus_parse_flavor_name(resource);
+
+ if (flav != -1) {
+ /* IF we have a parsed consensus of this type, we can do an
+ * if-modified-time based on it. */
+ v = networkstatus_get_latest_consensus_by_flavor(flav);
+ if (v)
+ if_modified_since = v->valid_after + 180;
+ } else {
+ /* Otherwise it might be a consensus we don't parse, but which we
+ * do cache. Look at the cached copy, perhaps. */
+ cached_dir_t *cd = dirserv_get_consensus(resource ? resource : "ns");
+ if (cd)
+ if_modified_since = cd->published + 180;
+ }
}
- if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
+ if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
return;
if (!get_via_tor) {
- if (options->UseBridges && type != BRIDGE_AUTHORITY) {
+ if (options->UseBridges && type != BRIDGE_DIRINFO) {
/* want to ask a running bridge for which we have a descriptor. */
/* XXX023 we assume that all of our bridges can answer any
* possible directory question. This won't be true forever. -RD */
/* It certainly is not true with conditional consensus downloading,
* so, for now, never assume the server supports that. */
- routerinfo_t *ri = choose_random_entry(NULL);
- if (ri) {
+ const node_t *node = choose_random_entry(NULL);
+ if (node && node->ri) {
+ /* every bridge has a routerinfo. */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
+ routerinfo_t *ri = node->ri;
+ node_get_addr(node, &addr);
directory_initiate_command(ri->address, &addr,
ri->or_port, 0,
0, /* don't use conditional consensus url */
@@ -412,10 +444,11 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
"nodes are available yet.");
return;
} else {
- if (prefer_authority || type == BRIDGE_AUTHORITY) {
+ if (prefer_authority || type == BRIDGE_DIRINFO) {
/* only ask authdirservers, and don't ask myself */
rs = router_pick_trusteddirserver(type, pds_flags);
- if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) {
+ if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH))) {
/* We don't want to fetch from any authorities that we're currently
* fetching server descriptors from, and we got no match. Did we
* get no match because all the authorities have connections
@@ -423,7 +456,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
* return,) or because all the authorities are down or on fire or
* unreachable or something (in which case we should go on with
* our fallback code)? */
- pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH;
+ pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH);
rs = router_pick_trusteddirserver(type, pds_flags);
if (rs) {
log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
@@ -432,7 +466,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
}
- if (!rs && type != BRIDGE_AUTHORITY) {
+ if (!rs && type != BRIDGE_DIRINFO) {
/* anybody with a non-zero dirport will do */
rs = router_pick_directory_server(type, pds_flags);
if (!rs) {
@@ -449,7 +483,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
/* only ask hidserv authorities, any of them will do */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
- rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
+ rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
} else {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
@@ -495,7 +529,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
routerstatus_t *rs;
if (router_digest_is_me(ds->digest))
continue;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
rs = &ds->fake_status;
directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
@@ -506,7 +540,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
/** Same as directory_initiate_command_routerstatus(), but accepts
* rendezvous data to fetch a hidden service descriptor. */
void
-directory_initiate_command_routerstatus_rend(routerstatus_t *status,
+directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -516,21 +550,22 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
time_t if_modified_since,
const rend_data_t *rend_query)
{
- or_options_t *options = get_options();
- routerinfo_t *router;
+ const or_options_t *options = get_options();
+ const node_t *node;
char address_buf[INET_NTOA_BUF_LEN+1];
struct in_addr in;
const char *address;
tor_addr_t addr;
- router = router_get_by_digest(status->identity_digest);
+ node = node_get_by_id(status->identity_digest);
- if (!router && anonymized_connection) {
- log_info(LD_DIR, "Not sending anonymized request to directory %s; we "
+ if (!node && anonymized_connection) {
+ log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
"don't have its router descriptor.",
routerstatus_describe(status));
return;
- } else if (router) {
- address = router->address;
+ } else if (node) {
+ node_get_address_string(node, address_buf, sizeof(address_buf));
+ address = address_buf;
} else {
in.s_addr = htonl(status->addr);
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
@@ -539,7 +574,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
tor_addr_from_ipv4h(&addr, status->addr);
if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
+ routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
"it's in our ExcludedNodes list and StrictNodes is set. "
"Skipping. This choice might make your Tor not work.",
@@ -574,7 +609,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
* want to fetch.
*/
void
-directory_initiate_command_routerstatus(routerstatus_t *status,
+directory_initiate_command_routerstatus(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -598,7 +633,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
{
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"authority")) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me &&
router_digest_is_me(conn->identity_digest) &&
tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
@@ -612,7 +647,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
* server due to a network error: Mark the router as down and try again if
* possible.
*/
-void
+static void
connection_dir_request_failed(dir_connection_t *conn)
{
if (directory_conn_is_self_reachability_test(conn)) {
@@ -626,15 +661,18 @@ connection_dir_request_failed(dir_connection_t *conn)
connection_dir_download_v2_networkstatus_failed(conn, -1);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
- log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
+ log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
+ "directory server at '%s'; retrying",
conn->_base.address);
if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
connection_dir_bridge_routerdesc_failed(conn);
connection_dir_download_routerdesc_failed(conn);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
- networkstatus_consensus_download_failed(0);
+ if (conn->requested_resource)
+ networkstatus_consensus_download_failed(0, conn->requested_resource);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
- log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
+ log_info(LD_DIR, "Giving up on certificate fetch from directory server "
+ "at '%s'; retrying",
conn->_base.address);
connection_dir_download_cert_failed(conn, 0);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
@@ -643,6 +681,10 @@ connection_dir_request_failed(dir_connection_t *conn)
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
log_info(LD_DIR, "Giving up downloading votes from '%s'",
conn->_base.address);
+ } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ log_info(LD_DIR, "Giving up on downloading microdescriptors from "
+ " directory server at '%s'; will retry", conn->_base.address);
+ connection_dir_download_routerdesc_failed(conn);
}
}
@@ -713,7 +755,8 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
/* No need to relaunch descriptor downloads here: we already do it
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
+ conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
(void) conn;
}
@@ -776,7 +819,7 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status)
* 3) Else yes.
*/
static int
-directory_command_should_use_begindir(or_options_t *options,
+directory_command_should_use_begindir(const or_options_t *options,
const tor_addr_t *addr,
int or_port, uint8_t router_purpose,
int anonymized_connection)
@@ -785,8 +828,7 @@ directory_command_should_use_begindir(or_options_t *options,
return 0; /* We don't know an ORPort -- no chance. */
if (!anonymized_connection)
if (!fascist_firewall_allows_address_or(addr, or_port) ||
- directory_fetches_from_authorities(options) ||
- (server_mode(options) && !options->Address))
+ directory_fetches_from_authorities(options))
return 0; /* We're firewalled or are acting like a relay -- also no. */
if (!options->TunnelDirConns &&
router_purpose != ROUTER_PURPOSE_BRIDGE)
@@ -817,6 +859,20 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
if_modified_since, NULL);
}
+/** Return non-zero iff a directory connection with purpose
+ * <b>dir_purpose</b> reveals sensitive information about a Tor
+ * instance's client activities. (Such connections must be performed
+ * through normal three-hop Tor circuits.) */
+static int
+is_sensitive_dir_purpose(uint8_t dir_purpose)
+{
+ return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
+ (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
+}
+
/** Same as directory_initiate_command(), but accepts rendezvous data to
* fetch a hidden service descriptor. */
static void
@@ -832,7 +888,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
const rend_data_t *rend_query)
{
dir_connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int socket_error = 0;
int use_begindir = supports_begindir &&
directory_command_should_use_begindir(options, _addr,
@@ -851,6 +907,9 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
+ tor_assert(!(is_sensitive_dir_purpose(dir_purpose) &&
+ !anonymized_connection));
+
/* ensure that we don't make direct connections when a SOCKS server is
* configured. */
if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
@@ -912,7 +971,11 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
error indicates broken link in windowsland. */
}
} else { /* we want to connect via a tor connection */
- edge_connection_t *linked_conn;
+ entry_connection_t *linked_conn;
+ /* Anonymized tunneled connections can never share a circuit.
+ * One-hop directory connections can share circuits with each other
+ * but nothing else. */
+ int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
/* If it's an anonymized connection, remember the fact that we
* wanted it for later: maybe we'll want it again soon. */
@@ -926,14 +989,16 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
* hook up both sides
*/
linked_conn =
- connection_ap_make_link(conn->_base.address, conn->_base.port,
- digest, use_begindir, conn->dirconn_direct);
+ connection_ap_make_link(TO_CONN(conn),
+ conn->_base.address, conn->_base.port,
+ digest,
+ SESSION_GROUP_DIRCONN, iso_flags,
+ use_begindir, conn->dirconn_direct);
if (!linked_conn) {
log_warn(LD_NET,"Making tunnel to dirserver failed.");
connection_mark_for_close(TO_CONN(conn));
return;
}
- connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
if (connection_add(TO_CONN(conn)) < 0) {
log_warn(LD_NET,"Unable to add connection for link to dirserver.");
@@ -946,8 +1011,13 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
payload, payload_len,
supports_conditional_consensus,
if_modified_since);
+
connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
- connection_start_reading(TO_CONN(linked_conn));
+ IF_HAS_BUFFEREVENT(ENTRY_TO_CONN(linked_conn), {
+ connection_watch_events(ENTRY_TO_CONN(linked_conn),
+ READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT
+ connection_start_reading(ENTRY_TO_CONN(linked_conn));
}
}
@@ -985,12 +1055,22 @@ _compare_strs(const void **a, const void **b)
* This url depends on whether or not the server we go to
* is sufficiently new to support conditional consensus downloading,
* i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
+ *
+ * If 'resource' is provided, it is the name of a consensus flavor to request.
*/
static char *
-directory_get_consensus_url(int supports_conditional_consensus)
+directory_get_consensus_url(int supports_conditional_consensus,
+ const char *resource)
{
- char *url;
- size_t len;
+ char *url = NULL;
+ const char *hyphen, *flavor;
+ if (resource==NULL || strcmp(resource, "ns")==0) {
+ flavor = ""; /* Request ns consensuses as "", so older servers will work*/
+ hyphen = "";
+ } else {
+ flavor = resource;
+ hyphen = "-";
+ }
if (supports_conditional_consensus) {
char *authority_id_list;
@@ -1000,7 +1080,7 @@ directory_get_consensus_url(int supports_conditional_consensus)
trusted_dir_server_t *, ds,
{
char *hex;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
@@ -1012,16 +1092,15 @@ directory_get_consensus_url(int supports_conditional_consensus)
authority_id_list = smartlist_join_strings(authority_digests,
"+", 0, NULL);
- len = strlen(authority_id_list)+64;
- url = tor_malloc(len);
- tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
- authority_id_list);
+ tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
+ hyphen, flavor, authority_id_list);
SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
smartlist_free(authority_digests);
tor_free(authority_id_list);
} else {
- url = tor_strdup("/tor/status-vote/current/consensus.z");
+ tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s.z",
+ hyphen, flavor);
}
return url;
}
@@ -1037,11 +1116,11 @@ directory_send_command(dir_connection_t *conn,
time_t if_modified_since)
{
char proxystring[256];
- char proxyauthstring[256];
char hoststring[128];
- char imsstring[RFC1123_TIME_LEN+32];
+ smartlist_t *headers = smartlist_create();
char *url;
char request[8192];
+ char *header;
const char *httpcommand = NULL;
size_t len;
@@ -1061,12 +1140,11 @@ directory_send_command(dir_connection_t *conn,
}
/* Format if-modified-since */
- if (!if_modified_since) {
- imsstring[0] = '\0';
- } else {
+ if (if_modified_since) {
char b[RFC1123_TIME_LEN+1];
format_rfc1123_time(b, if_modified_since);
- tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
+ tor_asprintf(&header, "If-Modified-Since: %s\r\n", b);
+ smartlist_add(headers, header);
}
/* come up with some proxy lines, if we're using one. */
@@ -1081,16 +1159,14 @@ directory_send_command(dir_connection_t *conn,
log_warn(LD_BUG, "Encoding http authenticator failed");
}
if (base64_authenticator) {
- tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
- "\r\nProxy-Authorization: Basic %s",
+ tor_asprintf(&header,
+ "Proxy-Authorization: Basic %s\r\n",
base64_authenticator);
tor_free(base64_authenticator);
- } else {
- proxyauthstring[0] = 0;
+ smartlist_add(headers, header);
}
} else {
proxystring[0] = 0;
- proxyauthstring[0] = 0;
}
switch (purpose) {
@@ -1102,10 +1178,11 @@ directory_send_command(dir_connection_t *conn,
tor_snprintf(url, len, "/tor/status/%s", resource);
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
- tor_assert(!resource);
+ /* resource is optional. If present, it's a flavor name */
tor_assert(!payload);
httpcommand = "GET";
- url = directory_get_consensus_url(supports_conditional_consensus);
+ url = directory_get_consensus_url(supports_conditional_consensus,
+ resource);
log_info(LD_DIR, "Downloading consensus from %s using %s",
hoststring, url);
break;
@@ -1145,12 +1222,23 @@ directory_send_command(dir_connection_t *conn,
url = tor_malloc(len);
tor_snprintf(url, len, "/tor/extra/%s", resource);
break;
- case DIR_PURPOSE_UPLOAD_DIR:
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ tor_assert(resource);
+ httpcommand = "GET";
+ tor_asprintf(&url, "/tor/micro/%s", resource);
+ break;
+ case DIR_PURPOSE_UPLOAD_DIR: {
+ const char *why = router_get_descriptor_gen_reason();
tor_assert(!resource);
tor_assert(payload);
httpcommand = "POST";
url = tor_strdup("/tor/");
+ if (why) {
+ tor_asprintf(&header, "X-Desc-Gen-Reason: %s\r\n", why);
+ smartlist_add(headers, header);
+ }
break;
+ }
case DIR_PURPOSE_UPLOAD_VOTE:
tor_assert(!resource);
tor_assert(payload);
@@ -1201,26 +1289,26 @@ directory_send_command(dir_connection_t *conn,
connection_write_to_buf(url, strlen(url), TO_CONN(conn));
tor_free(url);
- if (!strcmp(httpcommand, "GET") && !payload) {
- tor_snprintf(request, sizeof(request),
- " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
- hoststring,
- imsstring,
- proxyauthstring);
- } else {
- tor_snprintf(request, sizeof(request),
- " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
- payload ? (unsigned long)payload_len : 0,
- hoststring,
- imsstring,
- proxyauthstring);
+ if (!strcmp(httpcommand, "POST") || payload) {
+ tor_asprintf(&header, "Content-Length: %lu\r\n",
+ payload ? (unsigned long)payload_len : 0);
+ smartlist_add(headers, header);
}
+
+ header = smartlist_join_strings(headers, "", 0, NULL);
+ tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
+ hoststring, header);
+ tor_free(header);
+
connection_write_to_buf(request, strlen(request), TO_CONN(conn));
if (payload) {
/* then send the payload afterwards too */
connection_write_to_buf(payload, payload_len, TO_CONN(conn));
}
+
+ SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
+ smartlist_free(headers);
}
/** Parse an HTTP request string <b>headers</b> of the form
@@ -1420,6 +1508,9 @@ body_is_plausible(const char *body, size_t len, int purpose)
return 1; /* empty bodies don't need decompression */
if (len < 32)
return 0;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ return (!strcmpstart(body,"onion-key"));
+ }
if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
if (!strcmpstart(body,"router") ||
!strcmpstart(body,"signed-directory") ||
@@ -1496,11 +1587,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
int plausible;
int skewed=0;
int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
+ conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
int was_compressed=0;
time_t now = time(NULL);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_DL_SIZE,
allow_partial)) {
@@ -1575,13 +1667,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (status_code == 503) {
routerstatus_t *rs;
trusted_dir_server_t *ds;
+ const char *id_digest = conn->identity_digest;
log_info(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
- if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
+ if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
rs->last_dir_503_at = now;
- if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
+ if ((ds = router_get_trusteddirserver_by_digest(id_digest)))
ds->fake_status.last_dir_503_at = now;
tor_free(body); tor_free(headers); tor_free(reason);
@@ -1720,6 +1813,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
int r;
+ const char *flavname = conn->requested_resource;
if (status_code != 200) {
int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
log(severity, LD_DIR,
@@ -1728,22 +1822,24 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
- networkstatus_consensus_download_failed(status_code);
+ networkstatus_consensus_download_failed(status_code, flavname);
return -1;
}
log_info(LD_DIR,"Received consensus directory (size %d) from server "
"'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
- if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) {
+ if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) {
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
- "Unable to load consensus directory downloaded from "
+ "Unable to load %s consensus directory downloaded from "
"server '%s:%d'. I'll try again soon.",
- conn->_base.address, conn->_base.port);
+ flavname, conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
- networkstatus_consensus_download_failed(0);
+ networkstatus_consensus_download_failed(0, flavname);
return -1;
}
/* launches router downloads as needed */
routers_update_all_from_networkstatus(now, 3);
+ update_microdescs_from_networkstatus(now);
+ update_microdesc_downloads(now);
directory_info_has_arrived(now, 0);
log_info(LD_DIR, "Successfully loaded consensus.");
}
@@ -1893,6 +1989,43 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (directory_conn_is_self_reachability_test(conn))
router_dirport_found_reachable();
}
+ if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ smartlist_t *which = NULL;
+ log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
+ "size %d) from server '%s:%d'",
+ status_code, (int)body_len, conn->_base.address,
+ conn->_base.port);
+ tor_assert(conn->requested_resource &&
+ !strcmpstart(conn->requested_resource, "d/"));
+ which = smartlist_create();
+ dir_split_resource_into_fingerprints(conn->requested_resource+2,
+ which, NULL,
+ DSR_DIGEST256|DSR_BASE64);
+ if (status_code != 200) {
+ log_info(LD_DIR, "Received status code %d (%s) from server "
+ "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
+ "soon.",
+ status_code, escaped(reason), conn->_base.address,
+ (int)conn->_base.port, conn->requested_resource);
+ dir_microdesc_download_failed(which, status_code);
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ smartlist_free(which);
+ tor_free(body); tor_free(headers); tor_free(reason);
+ return 0;
+ } else {
+ smartlist_t *mds;
+ mds = microdescs_add_to_cache(get_microdesc_cache(),
+ body, body+body_len, SAVED_NOWHERE, 0,
+ now, which);
+ if (smartlist_len(which)) {
+ /* Mark remaining ones as failed. */
+ dir_microdesc_download_failed(which, status_code);
+ }
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ smartlist_free(which);
+ smartlist_free(mds);
+ }
+ }
if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
switch (status_code) {
@@ -2167,7 +2300,7 @@ connection_dir_process_inbuf(dir_connection_t *conn)
return 0;
}
- if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
+ if (connection_get_inbuf_len(TO_CONN(conn)) > MAX_DIRECTORY_OBJECT_SIZE) {
log_warn(LD_HTTP, "Too much data received from directory connection: "
"denial of service attempt, or you need to upgrade?");
connection_mark_for_close(TO_CONN(conn));
@@ -2179,6 +2312,28 @@ connection_dir_process_inbuf(dir_connection_t *conn)
return 0;
}
+/** Called when we're about to finally unlink and free a directory connection:
+ * perform necessary accounting and cleanup */
+void
+connection_dir_about_to_close(dir_connection_t *dir_conn)
+{
+ connection_t *conn = TO_CONN(dir_conn);
+
+ if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
+ /* It's a directory connection and connecting or fetching
+ * failed: forget about this router, and maybe try again. */
+ connection_dir_request_failed(dir_conn);
+ }
+ /* If we were trying to fetch a v2 rend desc and did not succeed,
+ * retry as needed. (If a fetch is successful, the connection state
+ * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
+ * refetching is unnecessary.) */
+ if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
+ dir_conn->rend_data &&
+ strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
+ rend_client_refetch_v2_renddesc(dir_conn->rend_data);
+}
+
/** Create an http response for the client <b>conn</b> out of
* <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
*/
@@ -2470,18 +2625,18 @@ client_likes_consensus(networkstatus_t *v, const char *want_url)
* Always return 0. */
static int
directory_handle_command_get(dir_connection_t *conn, const char *headers,
- const char *body, size_t body_len)
+ const char *req_body, size_t req_body_len)
{
size_t dlen;
char *url, *url_mem, *header;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
time_t if_modified_since = 0;
int compressed;
size_t url_len;
/* We ignore the body of a GET request. */
- (void)body;
- (void)body_len;
+ (void)req_body;
+ (void)req_body_len;
log_debug(LD_DIRSERV,"Received GET command.");
@@ -3190,7 +3345,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
const char *body, size_t body_len)
{
char *url = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
log_debug(LD_DIRSERV,"Received POST command.");
@@ -3334,7 +3489,7 @@ directory_handle_command(dir_connection_t *conn)
tor_assert(conn);
tor_assert(conn->_base.type == CONN_TYPE_DIR);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_UL_SIZE, 0)) {
case -1: /* overflow */
@@ -3387,14 +3542,27 @@ connection_dir_finished_flushing(dir_connection_t *conn)
DIRREQ_DIRECT,
DIRREQ_FLUSHING_DIR_CONN_FINISHED);
switch (conn->_base.state) {
+ case DIR_CONN_STATE_CONNECTING:
case DIR_CONN_STATE_CLIENT_SENDING:
log_debug(LD_DIR,"client finished sending command.");
conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
- connection_stop_writing(TO_CONN(conn));
return 0;
case DIR_CONN_STATE_SERVER_WRITING:
- log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
- connection_mark_for_close(TO_CONN(conn));
+ if (conn->dir_spool_src != DIR_SPOOL_NONE) {
+#ifdef USE_BUFFEREVENTS
+ /* This can happen with paired bufferevents, since a paired connection
+ * can flush immediately when you write to it, making the subsequent
+ * check in connection_handle_write_cb() decide that the connection
+ * is flushed. */
+ log_debug(LD_DIRSERV, "Emptied a dirserv buffer, but still spooling.");
+#else
+ log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
+ connection_mark_for_close(TO_CONN(conn));
+#endif
+ } else {
+ log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
return 0;
default:
log_warn(LD_BUG,"called in unexpected state %d.",
@@ -3620,6 +3788,36 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
}
+/* DOCDOC NM */
+static void
+dir_microdesc_download_failed(smartlist_t *failed,
+ int status_code)
+{
+ networkstatus_t *consensus
+ = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ routerstatus_t *rs;
+ download_status_t *dls;
+ time_t now = time(NULL);
+ int server = directory_fetches_from_authorities(get_options());
+
+ if (! consensus)
+ return;
+ SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
+ rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
+ if (!rs)
+ continue;
+ dls = &rs->dl_status;
+ if (dls->n_download_failures >= MAX_MICRODESC_DOWNLOAD_FAILURES)
+ continue;
+ {
+ char buf[BASE64_DIGEST256_LEN+1];
+ digest256_to_base64(buf, d);
+ download_status_increment_failure(dls, status_code, buf,
+ server, now);
+ }
+ } SMARTLIST_FOREACH_END(d);
+}
+
/** Helper. Compare two fp_pair_t objects, and return negative, 0, or
* positive as appropriate. */
static int
diff --git a/src/or/directory.h b/src/or/directory.h
index 94dfb17644..8c63bb5dfd 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -13,9 +13,8 @@
#define _TOR_DIRECTORY_H
int directories_have_accepted_server_descriptor(void);
-char *authority_type_to_string(authority_type_t auth);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
- authority_type_t type, const char *payload,
+ dirinfo_type_t type, const char *payload,
size_t payload_len, size_t extrainfo_len);
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource,
@@ -23,7 +22,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
void directory_get_from_all_authorities(uint8_t dir_purpose,
uint8_t router_purpose,
const char *resource);
-void directory_initiate_command_routerstatus(routerstatus_t *status,
+void directory_initiate_command_routerstatus(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -31,7 +30,7 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
const char *payload,
size_t payload_len,
time_t if_modified_since);
-void directory_initiate_command_routerstatus_rend(routerstatus_t *status,
+void directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -49,7 +48,7 @@ int connection_dir_reached_eof(dir_connection_t *conn);
int connection_dir_process_inbuf(dir_connection_t *conn);
int connection_dir_finished_flushing(dir_connection_t *conn);
int connection_dir_finished_connecting(dir_connection_t *conn);
-void connection_dir_request_failed(dir_connection_t *conn);
+void connection_dir_about_to_close(dir_connection_t *dir_conn);
void directory_initiate_command(const char *address, const tor_addr_t *addr,
uint16_t or_port, uint16_t dir_port,
int supports_conditional_consensus,
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 66079018ab..8fe1b18a35 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -16,6 +16,7 @@
#include "hibernate.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rephist.h"
#include "router.h"
@@ -67,8 +68,6 @@ static char *format_versions_list(config_line_t *ln);
struct authdir_config_t;
static int add_fingerprint_to_dir(const char *nickname, const char *fp,
struct authdir_config_t *list);
-static uint32_t dirserv_router_get_status(const routerinfo_t *router,
- const char **msg);
static uint32_t
dirserv_get_status_impl(const char *fp, const char *nickname,
const char *address,
@@ -76,7 +75,8 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
const char *platform, const char *contact,
const char **msg, int should_log);
static void clear_cached_dir(cached_dir_t *d);
-static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp,
+static const signed_descriptor_t *get_signed_descriptor_by_fp(
+ const char *fp,
int extrainfo,
time_t publish_cutoff);
static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
@@ -212,7 +212,7 @@ dirserv_load_fingerprint_file(void)
authdir_config_t *fingerprint_list_new;
int result;
config_line_t *front=NULL, *list;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
fname = get_datadir_fname("approved-routers");
log_info(LD_GENERAL,
@@ -232,7 +232,7 @@ dirserv_load_fingerprint_file(void)
}
tor_free(fname);
- result = config_get_lines(cf, &front);
+ result = config_get_lines(cf, &front, 0);
tor_free(cf);
if (result < 0) {
log_warn(LD_CONFIG, "Error reading from fingerprint file");
@@ -305,7 +305,7 @@ dirserv_load_fingerprint_file(void)
*
* If the status is 'FP_REJECT' and <b>msg</b> is provided, set
* *<b>msg</b> to an explanation of why. */
-static uint32_t
+uint32_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg)
{
char d[DIGEST_LEN];
@@ -327,7 +327,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
/** Return true if there is no point in downloading the router described by
* <b>rs</b> because this directory would reject it. */
int
-dirserv_would_reject_router(routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs)
{
uint32_t res;
@@ -362,7 +362,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
return 0;
}
-/** Helper: As dirserv_get_router_status, but takes the router fingerprint
+/** Helper: As dirserv_router_get_status, but takes the router fingerprint
* (hex, no spaces), nickname, address (used for logging only), IP address, OR
* port, platform (logging only) and contact info (logging only) as arguments.
*
@@ -377,7 +377,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
const char **msg, int should_log)
{
int reject_unlisted = get_options()->AuthDirRejectUnlisted;
- uint32_t result = 0;
+ uint32_t result;
router_status_t *status_by_digest;
if (!fingerprint_list)
@@ -542,7 +542,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
*/
int
authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain)
+ int complain, int *valid_out)
{
/* Okay. Now check whether the fingerprint is recognized. */
uint32_t status = dirserv_router_get_status(ri, msg);
@@ -586,15 +586,24 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
*msg = "Rejected: Address is not an IP, or IP is a private address.";
return -1;
}
- /* Okay, looks like we're willing to accept this one. */
- ri->is_named = (status & FP_NAMED) ? 1 : 0;
- ri->is_valid = (status & FP_INVALID) ? 0 : 1;
- ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
- ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
+
+ *valid_out = ! (status & FP_INVALID);
return 0;
}
+/** Update the relevant flags of <b>node</b> based on our opinion as a
+ * directory authority in <b>authstatus</b>, as returned by
+ * dirserv_router_get_status or equivalent. */
+void
+dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus)
+{
+ node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
+ node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
+ node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+}
+
/** True iff <b>a</b> is more severe than <b>b</b>. */
static int
WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
@@ -719,7 +728,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
* from this server. (We do this here and not in router_add_to_routerlist
* because we want to be able to accept the newest router descriptor that
* another authority has, so we all converge on the same one.) */
- ri_old = router_get_by_digest(ri->cache_info.identity_digest);
+ ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
&& router_differences_are_cosmetic(ri_old, ri)
&& !router_is_me(ri)) {
@@ -763,8 +772,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
routerlist_descriptors_added(changed, 0);
smartlist_free(changed);
if (!*msg) {
- *msg = ri->is_valid ? "Descriptor for valid server accepted" :
- "Descriptor for invalid server accepted";
+ *msg = "Descriptor accepted";
}
log_info(LD_DIRSERV,
"Added descriptor from '%s' (source: %s): %s.",
@@ -779,12 +787,12 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
static was_router_added_t
dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
{
- routerinfo_t *ri;
+ const routerinfo_t *ri;
int r;
tor_assert(msg);
*msg = NULL;
- ri = router_get_by_digest(ei->cache_info.identity_digest);
+ ri = router_get_by_id_digest(ei->cache_info.identity_digest);
if (!ri) {
*msg = "No corresponding router descriptor for extra-info descriptor";
extrainfo_free(ei);
@@ -819,56 +827,67 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
static void
directory_remove_invalid(void)
{
- int i;
int changed = 0;
routerlist_t *rl = router_get_routerlist();
+ smartlist_t *nodes = smartlist_create();
+ smartlist_add_all(nodes, nodelist_get_list());
- routerlist_assert_ok(rl);
-
- for (i = 0; i < smartlist_len(rl->routers); ++i) {
+ SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
const char *msg;
- routerinfo_t *ent = smartlist_get(rl->routers, i);
+ routerinfo_t *ent = node->ri;
char description[NODE_DESC_BUF_LEN];
- uint32_t r = dirserv_router_get_status(ent, &msg);
+ uint32_t r;
+ if (!ent)
+ continue;
+ r = dirserv_router_get_status(ent, &msg);
router_get_description(description, ent);
if (r & FP_REJECT) {
log_info(LD_DIRSERV, "Router %s is now rejected: %s",
description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
- i--;
changed = 1;
continue;
}
- if (bool_neq((r & FP_NAMED), ent->is_named)) {
+#if 0
+ if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
log_info(LD_DIRSERV,
"Router %s is now %snamed.", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NAMED)?1:0;
changed = 1;
}
- if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
+ if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
+ log_info(LD_DIRSERV,
+ "Router '%s' is now %snamed. (FP_UNNAMED)", description,
+ (r&FP_NAMED)?"":"un");
+ ent->is_named = (r&FP_NUNAMED)?0:1;
+ changed = 1;
+ }
+#endif
+ if (bool_neq((r & FP_INVALID), !node->is_valid)) {
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
(r&FP_INVALID) ? "in" : "");
- ent->is_valid = (r&FP_INVALID)?0:1;
+ node->is_valid = (r&FP_INVALID)?0:1;
changed = 1;
}
- if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
+ if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description,
(r & FP_BADDIR) ? "bad" : "good");
- ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
+ node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
changed = 1;
}
- if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
+ if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
(r & FP_BADEXIT) ? "bad" : "good");
- ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+ node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
changed = 1;
}
- }
+ } SMARTLIST_FOREACH_END(node);
if (changed)
directory_set_dirty();
routerlist_assert_ok(rl);
+ smartlist_free(nodes);
}
/** Mark the directory as <b>dirty</b> -- when we're next asked for a
@@ -907,10 +926,11 @@ directory_set_dirty(void)
* as running iff <b>is_live</b> is true.
*/
static char *
-list_single_server_status(routerinfo_t *desc, int is_live)
+list_single_server_status(const routerinfo_t *desc, int is_live)
{
char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
char *cp;
+ const node_t *node;
tor_assert(desc);
@@ -918,7 +938,8 @@ list_single_server_status(routerinfo_t *desc, int is_live)
if (!is_live) {
*cp++ = '!';
}
- if (desc->is_valid) {
+ node = node_get_by_id(desc->cache_info.identity_digest);
+ if (node && node->is_valid) {
strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
cp += strlen(cp);
*cp++ = '=';
@@ -957,6 +978,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
unreachable.
*/
int answer;
+ node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
+ tor_assert(node);
if (router_is_me(router)) {
/* We always know if we are down ourselves. */
@@ -991,7 +1014,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
rep_hist_note_router_unreachable(router->cache_info.identity_digest, when);
}
- router->is_running = answer;
+ node->is_running = answer;
}
/** Based on the routerinfo_ts in <b>routers</b>, allocate the
@@ -1009,7 +1032,7 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
smartlist_t *rs_entries;
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* We include v2 dir auths here too, because they need to answer
* controllers. Eventually we'll deprecate this whole function;
* see also networkstatus_getinfo_by_purpose(). */
@@ -1019,6 +1042,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
rs_entries = smartlist_create();
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
if (authdir) {
/* Update router status in routerinfo_t. */
dirserv_set_router_is_running(ri, now);
@@ -1026,12 +1051,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
if (for_controller) {
char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
char *cp = name_buf;
- if (!ri->is_running)
+ if (!node->is_running)
*cp++ = '!';
router_get_verbose_nickname(cp, ri);
smartlist_add(rs_entries, tor_strdup(name_buf));
} else if (ri->cache_info.published_on >= cutoff) {
- smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
+ smartlist_add(rs_entries, list_single_server_status(ri,
+ node->is_running));
}
} SMARTLIST_FOREACH_END(ri);
@@ -1069,12 +1095,12 @@ format_versions_list(config_line_t *ln)
* not hibernating, and not too old. Else return 0.
*/
static int
-router_is_active(routerinfo_t *ri, time_t now)
+router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
{
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
if (ri->cache_info.published_on < cutoff)
return 0;
- if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
+ if (!node->is_running || !node->is_valid || ri->is_hibernating)
return 0;
return 1;
}
@@ -1173,9 +1199,9 @@ dirserv_dump_directory_to_string(char **dir_out,
/** Return 1 if we fetch our directory material directly from the
* authorities, rather than from a mirror. */
int
-directory_fetches_from_authorities(or_options_t *options)
+directory_fetches_from_authorities(const or_options_t *options)
{
- routerinfo_t *me;
+ const routerinfo_t *me;
uint32_t addr;
int refuseunknown;
if (options->FetchDirInfoEarly)
@@ -1200,7 +1226,7 @@ directory_fetches_from_authorities(or_options_t *options)
* on the "mirror" schedule rather than the "client" schedule.
*/
int
-directory_fetches_dir_info_early(or_options_t *options)
+directory_fetches_dir_info_early(const or_options_t *options)
{
return directory_fetches_from_authorities(options);
}
@@ -1212,7 +1238,7 @@ directory_fetches_dir_info_early(or_options_t *options)
* client as a directory guard.
*/
int
-directory_fetches_dir_info_later(or_options_t *options)
+directory_fetches_dir_info_later(const or_options_t *options)
{
return options->UseBridges != 0;
}
@@ -1220,7 +1246,7 @@ directory_fetches_dir_info_later(or_options_t *options)
/** Return 1 if we want to cache v2 dir info (each status file).
*/
int
-directory_caches_v2_dir_info(or_options_t *options)
+directory_caches_v2_dir_info(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1229,7 +1255,7 @@ directory_caches_v2_dir_info(or_options_t *options)
* and we're willing to serve them to others. Else return 0.
*/
int
-directory_caches_dir_info(or_options_t *options)
+directory_caches_dir_info(const or_options_t *options)
{
if (options->BridgeRelay || options->DirPort)
return 1;
@@ -1245,7 +1271,7 @@ directory_caches_dir_info(or_options_t *options)
* requests via the "begin_dir" interface, which doesn't require
* having any separate port open. */
int
-directory_permits_begindir_requests(or_options_t *options)
+directory_permits_begindir_requests(const or_options_t *options)
{
return options->BridgeRelay != 0 || options->DirPort != 0;
}
@@ -1254,7 +1280,7 @@ directory_permits_begindir_requests(or_options_t *options)
* requests via the controller interface, which doesn't require
* having any separate port open. */
int
-directory_permits_controller_requests(or_options_t *options)
+directory_permits_controller_requests(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1264,7 +1290,8 @@ directory_permits_controller_requests(or_options_t *options)
* lately.
*/
int
-directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now)
+directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now)
{
return !directory_caches_dir_info(options) &&
!options->FetchUselessDescriptors &&
@@ -1287,7 +1314,8 @@ static cached_dir_t cached_runningrouters;
* cached_dir_t. */
static digestmap_t *cached_v2_networkstatus = NULL;
-/** Map from flavor name to the v3 consensuses that we're currently serving. */
+/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
+ * currently serving. */
static strmap_t *cached_consensuses = NULL;
/** Possibly replace the contents of <b>d</b> with the value of
@@ -1531,11 +1559,11 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
cached_dir_t *auth_src,
time_t dirty, cached_dir_t *(*regenerate)(void),
const char *name,
- authority_type_t auth_type)
+ dirinfo_type_t auth_type)
{
- or_options_t *options = get_options();
- int authority = (auth_type == V1_AUTHORITY && authdir_mode_v1(options)) ||
- (auth_type == V2_AUTHORITY && authdir_mode_v2(options));
+ const or_options_t *options = get_options();
+ int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
+ (auth_type == V2_DIRINFO && authdir_mode_v2(options));
if (!authority || authdir_mode_bridge(options)) {
return cache_src;
@@ -1564,7 +1592,7 @@ dirserv_get_directory(void)
return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
the_directory_is_dirty,
dirserv_regenerate_directory,
- "v1 server directory", V1_AUTHORITY);
+ "v1 server directory", V1_DIRINFO);
}
/** Only called by v1 auth dirservers.
@@ -1657,7 +1685,7 @@ dirserv_get_runningrouters(void)
&cached_runningrouters, &the_runningrouters,
runningrouters_is_dirty,
generate_runningrouters,
- "v1 network status list", V1_AUTHORITY);
+ "v1 network status list", V1_DIRINFO);
}
/** Return the latest downloaded consensus networkstatus in encoded, signed,
@@ -1692,12 +1720,6 @@ should_generate_v2_networkstatus(void)
/** If a router's MTBF is at least this value, then it is always stable.
* See above. (Corresponds to about 7 days for current decay rates.) */
#define MTBF_TO_GUARANTEE_STABLE (60*60*24*5)
-/** Similarly, we protect sufficiently fast nodes from being pushed
- * out of the set of Fast nodes. */
-#define BANDWIDTH_TO_GUARANTEE_FAST ROUTER_REQUIRED_MIN_BANDWIDTH
-/** Similarly, every node with sufficient bandwidth can be considered
- * for Guard status. */
-#define BANDWIDTH_TO_GUARANTEE_GUARD (250*1024)
/** Similarly, every node with at least this much weighted time known can be
* considered familiar enough to be a guard. Corresponds to about 20 days for
* current decay rates.
@@ -1740,7 +1762,7 @@ static uint64_t total_exit_bandwidth = 0;
/** Helper: estimate the uptime of a router given its stated uptime and the
* amount of time since it last stated its stated uptime. */
static INLINE long
-real_uptime(routerinfo_t *router, time_t now)
+real_uptime(const routerinfo_t *router, time_t now)
{
if (now < router->cache_info.published_on)
return router->uptime;
@@ -1794,7 +1816,8 @@ dirserv_thinks_router_is_unreliable(time_t now,
* been set.
*/
static int
-dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
+dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
+ const node_t *node, time_t now)
{
long uptime;
@@ -1822,7 +1845,7 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
* to fix the bug was 0.2.2.25-alpha. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime > get_options()->MinUptimeHidServDirectoryV2 &&
- router->is_running);
+ node->is_running);
}
/** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1841,6 +1864,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
long *tks;
double *mtbfs, *wfus;
time_t now = time(NULL);
+ const or_options_t *options = get_options();
/* initialize these all here, in case there are no routers */
stable_uptime = 0;
@@ -1870,19 +1894,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* Weighted fractional uptime for each active router. */
wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
+ nodelist_assert_ok();
+
/* Now, fill in the arrays. */
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
uint32_t bw;
- ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
- exit_policy_is_general_exit(ri->exit_policy));
+ node->is_exit = (!router_exit_policy_rejects_all(ri) &&
+ exit_policy_is_general_exit(ri->exit_policy));
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
mtbfs[n_active] = rep_hist_get_stability(id, now);
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
total_bandwidth += bw;
- if (ri->is_exit && !ri->is_bad_exit) {
+ if (node->is_exit && !node->is_bad_exit) {
total_exit_bandwidth += bw;
} else {
bandwidths_excluding_exits[n_active_nonexit] = bw;
@@ -1890,7 +1917,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
}
++n_active;
}
- });
+ } SMARTLIST_FOREACH_END(node);
/* Now, compute thresholds. */
if (n_active) {
@@ -1910,21 +1937,26 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR)
guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR;
- if (fast_bandwidth > BANDWIDTH_TO_GUARANTEE_FAST)
- fast_bandwidth = BANDWIDTH_TO_GUARANTEE_FAST;
+ /* Protect sufficiently fast nodes from being pushed out of the set
+ * of Fast nodes. */
+ if (options->AuthDirFastGuarantee &&
+ fast_bandwidth > options->AuthDirFastGuarantee)
+ fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee;
/* Now that we have a time-known that 7/8 routers are known longer than,
* fill wfus with the wfu of every such "familiar" router. */
n_familiar = 0;
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
long tk = rep_hist_get_weighted_time_known(id, now);
if (tk < guard_tk)
continue;
wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
}
- });
+ } SMARTLIST_FOREACH_END(node);
if (n_familiar)
guard_wfu = median_double(wfus, n_familiar);
if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
@@ -1995,24 +2027,20 @@ version_from_platform(const char *platform)
*/
int
routerstatus_format_entry(char *buf, size_t buf_len,
- routerstatus_t *rs, const char *version,
+ const routerstatus_t *rs, const char *version,
routerstatus_format_type_t format)
{
int r;
- struct in_addr in;
char *cp;
char *summary;
char published[ISO_TIME_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char identity64[BASE64_DIGEST_LEN+1];
char digest64[BASE64_DIGEST_LEN+1];
format_iso_time(published, rs->published_on);
digest_to_base64(identity64, rs->identity_digest);
digest_to_base64(digest64, rs->descriptor_digest);
- in.s_addr = htonl(rs->addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
r = tor_snprintf(buf, buf_len,
"r %s %s %s%s%s %s %d %d\n",
@@ -2021,7 +2049,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
(format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
(format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
published,
- ipaddr,
+ fmt_addr32(rs->addr),
(int)rs->or_port,
(int)rs->dir_port);
if (r<0) {
@@ -2049,7 +2077,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
rs->is_possible_guard?" Guard":"",
rs->is_hs_dir?" HSDir":"",
rs->is_named?" Named":"",
- rs->is_running?" Running":"",
+ rs->is_flagged_running?" Running":"",
rs->is_stable?" Stable":"",
rs->is_unnamed?" Unnamed":"",
rs->is_v2_dir?" V2Dir":"",
@@ -2071,7 +2099,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
}
if (format != NS_V2) {
- routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
+ const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
uint32_t bw;
if (format != NS_CONTROL_PORT) {
@@ -2167,6 +2195,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
int first_is_auth, second_is_auth;
uint32_t bw_first, bw_second;
+ const node_t *node_first, *node_second;
+ int first_is_running, second_is_running;
/* we return -1 if first should appear before second... that is,
* if first is a better router. */
@@ -2189,9 +2219,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
else if (!first_is_auth && second_is_auth)
return 1;
- else if (first->is_running && !second->is_running)
+ node_first = node_get_by_id(first->cache_info.identity_digest);
+ node_second = node_get_by_id(second->cache_info.identity_digest);
+ first_is_running = node_first && node_first->is_running;
+ second_is_running = node_second && node_second->is_running;
+
+ if (first_is_running && !second_is_running)
return -1;
- else if (!first->is_running && second->is_running)
+ else if (!first_is_running && second_is_running)
return 1;
bw_first = router_get_advertised_bandwidth(first);
@@ -2215,7 +2250,7 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
static digestmap_t *
get_possible_sybil_list(const smartlist_t *routers)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *omit_as_sybil;
smartlist_t *routers_by_ip = smartlist_create();
uint32_t last_addr;
@@ -2251,6 +2286,75 @@ get_possible_sybil_list(const smartlist_t *routers)
return omit_as_sybil;
}
+/** Return non-zero iff a relay running the Tor version specified in
+ * <b>platform</b> is suitable for use as a potential entry guard. */
+static int
+is_router_version_good_for_possible_guard(const char *platform)
+{
+ static int parsed_versions_initialized = 0;
+ static tor_version_t first_good_0_2_1_guard_version;
+ static tor_version_t first_good_0_2_2_guard_version;
+ static tor_version_t first_good_later_guard_version;
+
+ tor_version_t router_version;
+
+ /* XXX023 This block should be extracted into its own function. */
+ /* XXXX Begin code copied from tor_version_as_new_as (in routerparse.c) */
+ {
+ char *s, *s2, *start;
+ char tmp[128];
+
+ tor_assert(platform);
+
+ /* nonstandard Tor; be safe and say yes */
+ if (strcmpstart(platform,"Tor "))
+ return 1;
+
+ start = (char *)eat_whitespace(platform+3);
+ if (!*start) return 0;
+ s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
+ s2 = (char*)eat_whitespace(s);
+ if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
+ s = (char*)find_whitespace(s2);
+
+ if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
+ return 0;
+ strlcpy(tmp, start, s-start+1);
+
+ if (tor_version_parse(tmp, &router_version)<0) {
+ log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
+ return 1; /* be safe and say yes */
+ }
+ }
+ /* XXXX End code copied from tor_version_as_new_as (in routerparse.c) */
+
+ if (!parsed_versions_initialized) {
+ /* CVE-2011-2769 was fixed on the relay side in Tor versions
+ * 0.2.1.31, 0.2.2.34, and 0.2.3.6-alpha. */
+ tor_assert(tor_version_parse("0.2.1.31",
+ &first_good_0_2_1_guard_version)>=0);
+ tor_assert(tor_version_parse("0.2.2.34",
+ &first_good_0_2_2_guard_version)>=0);
+ tor_assert(tor_version_parse("0.2.3.6-alpha",
+ &first_good_later_guard_version)>=0);
+
+ /* Don't parse these constant version strings once for every relay
+ * for every vote. */
+ parsed_versions_initialized = 1;
+ }
+
+ return ((tor_version_same_series(&first_good_0_2_1_guard_version,
+ &router_version) &&
+ tor_version_compare(&first_good_0_2_1_guard_version,
+ &router_version) <= 0) ||
+ (tor_version_same_series(&first_good_0_2_2_guard_version,
+ &router_version) &&
+ tor_version_compare(&first_good_0_2_2_guard_version,
+ &router_version) <= 0) ||
+ (tor_version_compare(&first_good_later_guard_version,
+ &router_version) <= 0));
+}
+
/** Extract status information from <b>ri</b> and from other authority
* functions and store it in <b>rs</b>>. If <b>naming</b>, consider setting
* the named flag in <b>rs</b>.
@@ -2260,60 +2364,68 @@ get_possible_sybil_list(const smartlist_t *routers)
*/
void
set_routerstatus_from_routerinfo(routerstatus_t *rs,
- routerinfo_t *ri, time_t now,
+ node_t *node,
+ routerinfo_t *ri,
+ time_t now,
int naming, int listbadexits,
int listbaddirs, int vote_on_hsdirs)
{
+ const or_options_t *options = get_options();
int unstable_version =
!tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs");
+ uint32_t routerbw = router_get_advertised_bandwidth(ri);
+
memset(rs, 0, sizeof(routerstatus_t));
rs->is_authority =
router_digest_is_trusted_dir(ri->cache_info.identity_digest);
/* Already set by compute_performance_thresholds. */
- rs->is_exit = ri->is_exit;
- rs->is_stable = ri->is_stable =
- router_is_active(ri, now) &&
+ rs->is_exit = node->is_exit;
+ rs->is_stable = node->is_stable =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
!unstable_version;
- rs->is_fast = ri->is_fast =
- router_is_active(ri, now) &&
+ rs->is_fast = node->is_fast =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
- rs->is_running = ri->is_running; /* computed above */
+ rs->is_flagged_running = node->is_running; /* computed above */
if (naming) {
uint32_t name_status = dirserv_get_name_status(
- ri->cache_info.identity_digest, ri->nickname);
+ node->identity, ri->nickname);
rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
}
- rs->is_valid = ri->is_valid;
+ rs->is_valid = node->is_valid;
- if (rs->is_fast &&
- (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
- router_get_advertised_bandwidth(ri) >=
- MIN(guard_bandwidth_including_exits,
- guard_bandwidth_excluding_exits))) {
+ if (node->is_fast &&
+ ((options->AuthDirGuardBWGuarantee &&
+ routerbw >= options->AuthDirGuardBWGuarantee) ||
+ routerbw >= MIN(guard_bandwidth_including_exits,
+ guard_bandwidth_excluding_exits)) &&
+ (options->GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays ||
+ is_router_version_good_for_possible_guard(ri->platform))) {
long tk = rep_hist_get_weighted_time_known(
- ri->cache_info.identity_digest, now);
+ node->identity, now);
double wfu = rep_hist_get_weighted_fractional_uptime(
- ri->cache_info.identity_digest, now);
+ node->identity, now);
rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
} else {
rs->is_possible_guard = 0;
}
- rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
- rs->is_bad_exit = listbadexits && ri->is_bad_exit;
- ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
- rs->is_hs_dir = vote_on_hsdirs && ri->is_hs_dir;
+
+ rs->is_bad_directory = listbaddirs && node->is_bad_directory;
+ rs->is_bad_exit = listbadexits && node->is_bad_exit;
+ node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
+ rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir;
rs->is_v2_dir = ri->dir_port != 0;
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
rs->is_named = rs->is_unnamed = 0;
rs->published_on = ri->cache_info.published_on;
- memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
+ memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
DIGEST_LEN);
rs->addr = ri->addr;
@@ -2330,7 +2442,7 @@ static void
clear_status_flags_on_sybil(routerstatus_t *rs)
{
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
- rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
+ rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
rs->is_bad_directory = 0;
/* FFFF we might want some mechanism to check later on if we
@@ -2338,18 +2450,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
* forget to add it to this clause. */
}
-/** Clear all the status flags in routerinfo <b>router</b>. We put this
- * function here because it's eerily similar to
- * clear_status_flags_on_sybil() above. One day we should merge them. */
-void
-router_clear_status_flags(routerinfo_t *router)
-{
- router->is_valid = router->is_running = router->is_hs_dir =
- router->is_fast = router->is_stable =
- router->is_possible_guard = router->is_exit =
- router->is_bad_exit = router->is_bad_directory = 0;
-}
-
/**
* Helper function to parse out a line in the measured bandwidth file
* into a measured_bw_line_t output structure. Returns -1 on failure
@@ -2467,7 +2567,7 @@ dirserv_read_measured_bandwidths(const char *from_file,
smartlist_t *routerstatuses)
{
char line[256];
- FILE *fp = fopen(from_file, "r");
+ FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
time_t file_time;
int ok;
@@ -2527,7 +2627,7 @@ networkstatus_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
authority_cert_t *cert)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *v3_out = NULL;
uint32_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -2598,10 +2698,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
routerstatus_t *rs;
vote_routerstatus_t *vrs;
microdesc_t *md;
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
- set_routerstatus_from_routerinfo(rs, ri, now,
+ set_routerstatus_from_routerinfo(rs, node, ri, now,
naming, listbadexits, listbaddirs,
vote_on_hsdirs);
@@ -2609,7 +2712,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
clear_status_flags_on_sybil(rs);
if (!vote_on_reachability)
- rs->is_running = 0;
+ rs->is_flagged_running = 0;
vrs->version = version_from_platform(ri->platform);
md = dirvote_create_microdescriptor(ri);
@@ -2743,12 +2846,10 @@ generate_v2_networkstatus_opinion(void)
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
char *outp, *endp;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char fingerprint[FINGERPRINT_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
- struct in_addr in;
uint32_t addr;
crypto_pk_env_t *private_key;
routerlist_t *rl = router_get_routerlist();
@@ -2770,8 +2871,6 @@ generate_v2_networkstatus_opinion(void)
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
format_iso_time(published, now);
@@ -2789,7 +2888,7 @@ generate_v2_networkstatus_opinion(void)
goto done;
}
- contact = get_options()->ContactInfo;
+ contact = options->ContactInfo;
if (!contact)
contact = "(none)";
@@ -2817,7 +2916,7 @@ generate_v2_networkstatus_opinion(void)
"dir-options%s%s%s%s\n"
"%s" /* client version line, server version line. */
"dir-signing-key\n%s",
- hostname, ipaddr,
+ hostname, fmt_addr32(addr),
(int)router_get_advertised_dir_port(options, 0),
fingerprint,
contact,
@@ -2849,8 +2948,12 @@ generate_v2_networkstatus_opinion(void)
if (ri->cache_info.published_on >= cutoff) {
routerstatus_t rs;
char *version = version_from_platform(ri->platform);
-
- set_routerstatus_from_routerinfo(&rs, ri, now,
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node) {
+ tor_free(version);
+ continue;
+ }
+ set_routerstatus_from_routerinfo(&rs, node, ri, now,
naming, listbadexits, listbaddirs,
vote_on_hsdirs);
@@ -2868,7 +2971,7 @@ generate_v2_networkstatus_opinion(void)
});
if (tor_snprintf(outp, endp-outp, "directory-signature %s\n",
- get_options()->Nickname)<0) {
+ options->Nickname)<0) {
log_warn(LD_BUG, "Unable to write signature line.");
goto done;
}
@@ -2934,7 +3037,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
if (!strcmp(key,"authority")) {
if (authdir_mode_v2(get_options())) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me)
smartlist_add(result,
tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
@@ -2953,7 +3056,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
} else {
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if (ds->type & V2_AUTHORITY)
+ if (ds->type & V2_DIRINFO)
smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN)));
}
smartlist_sort_digests(result);
@@ -3022,7 +3125,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
/* Treat "all" requests as if they were unencrypted */
for_unencrypted_conn = 1;
} else if (!strcmp(key, "authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
smartlist_add(fps_out,
tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
@@ -3042,8 +3145,8 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
if (for_unencrypted_conn) {
/* Remove anything that insists it not be sent unencrypted. */
- SMARTLIST_FOREACH(fps_out, char *, cp, {
- signed_descriptor_t *sd;
+ SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) {
+ const signed_descriptor_t *sd;
if (by_id)
sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0);
else if (is_extrainfo)
@@ -3054,7 +3157,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
tor_free(cp);
SMARTLIST_DEL_CURRENT(fps_out, cp);
}
- });
+ } SMARTLIST_FOREACH_END(cp);
}
if (!smartlist_len(fps_out)) {
@@ -3093,9 +3196,9 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
smartlist_add(descs_out, &(r->cache_info)));
} else if (!strcmp(key, "/tor/server/authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
} else if (!strcmpstart(key, "/tor/server/d/")) {
smartlist_t *digests = smartlist_create();
key += strlen("/tor/server/d/");
@@ -3119,17 +3222,17 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
{
if (router_digest_is_me(d)) {
/* make sure desc_routerinfo exists */
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
} else {
- routerinfo_t *ri = router_get_by_digest(d);
+ const routerinfo_t *ri = router_get_by_id_digest(d);
/* Don't actually serve a descriptor that everyone will think is
* expired. This is an (ugly) workaround to keep buggy 0.1.1.10
* Tors from downloading descriptors that they will throw away.
*/
if (ri && ri->cache_info.published_on > cutoff)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
}
});
SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
@@ -3178,7 +3281,7 @@ dirserv_orconn_tls_done(const char *address,
log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
router_describe(ri),
address, ri->or_port);
- if (tor_addr_from_str(&addr, ri->address) != -1)
+ if (tor_addr_parse(&addr, ri->address) != -1)
addrp = &addr;
else
log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address);
@@ -3196,7 +3299,8 @@ dirserv_orconn_tls_done(const char *address,
* an upload or a download. Used to decide whether to relaunch reachability
* testing for the server. */
int
-dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old)
+dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old)
{
if (!authdir_mode_handles_descs(get_options(), ri->purpose))
return 0;
@@ -3320,7 +3424,7 @@ dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff)
* its extra-info document if <b>extrainfo</b> is true. Return
* NULL if not found or if the descriptor is older than
* <b>publish_cutoff</b>. */
-static signed_descriptor_t *
+static const signed_descriptor_t *
get_signed_descriptor_by_fp(const char *fp, int extrainfo,
time_t publish_cutoff)
{
@@ -3330,7 +3434,7 @@ get_signed_descriptor_by_fp(const char *fp, int extrainfo,
else
return &(router_get_my_routerinfo()->cache_info);
} else {
- routerinfo_t *ri = router_get_by_digest(fp);
+ const routerinfo_t *ri = router_get_by_id_digest(fp);
if (ri &&
ri->cache_info.published_on > publish_cutoff) {
if (extrainfo)
@@ -3398,7 +3502,7 @@ dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
tor_assert(fps);
if (is_serverdescs) {
int n = smartlist_len(fps);
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
result = (me?me->cache_info.signed_descriptor_len:2048) * n;
if (compressed)
result /= 2; /* observed compressibility is between 35 and 55%. */
@@ -3452,20 +3556,19 @@ connection_dirserv_finish_spooling(dir_connection_t *conn)
static int
connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
{
-#ifdef TRACK_SERVED_TIME
- time_t now = time(NULL);
-#endif
int by_fp = (conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP ||
conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP);
int extra = (conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP ||
conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST);
time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
+ const or_options_t *options = get_options();
+
while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
const char *body;
char *fp = smartlist_pop_last(conn->fingerprint_stack);
- signed_descriptor_t *sd = NULL;
+ const signed_descriptor_t *sd = NULL;
if (by_fp) {
sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff);
} else {
@@ -3482,9 +3585,17 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
* unknown bridge descriptor has shown up between then and now. */
continue;
}
-#ifdef TRACK_SERVED_TIME
- sd->last_served_at = now;
-#endif
+
+ /** If we are the bridge authority and the descriptor is a bridge
+ * descriptor, remember that we served this descriptor for desc stats. */
+ if (options->BridgeAuthoritativeDir && by_fp) {
+ const routerinfo_t *router =
+ router_get_by_id_digest(sd->identity_digest);
+ /* router can be NULL here when the bridge auth is asked for its own
+ * descriptor. */
+ if (router && router->purpose == ROUTER_PURPOSE_BRIDGE)
+ rep_hist_note_desc_served(sd->identity_digest);
+ }
body = signed_descriptor_get_body(sd);
if (conn->zlib_state) {
/* XXXX022 This 'last' business should actually happen on the last
@@ -3523,7 +3634,7 @@ connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn)
{
microdesc_cache_t *cache = get_microdesc_cache();
while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
char *fp256 = smartlist_pop_last(conn->fingerprint_stack);
microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256);
tor_free(fp256);
@@ -3562,7 +3673,7 @@ connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
ssize_t bytes;
int64_t remaining;
- bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
+ bytes = DIRSERV_BUFFER_MIN - connection_get_outbuf_len(TO_CONN(conn));
tor_assert(bytes > 0);
tor_assert(conn->cached_dir);
if (bytes < 8192)
@@ -3601,7 +3712,7 @@ static int
connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
{
- while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
if (conn->cached_dir) {
int uncompressing = (conn->zlib_state != NULL);
int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
@@ -3647,7 +3758,7 @@ connection_dirserv_flushed_some(dir_connection_t *conn)
{
tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
- if (buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
+ if (connection_get_outbuf_len(TO_CONN(conn)) >= DIRSERV_BUFFER_MIN)
return 0;
switch (conn->dir_spool_src) {
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index 569abfca2e..d3fd90ceb5 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -52,8 +52,6 @@
MAX_V_LINE_LEN \
)
-#define UNNAMED_ROUTER_NICKNAME "Unnamed"
-
int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
@@ -73,15 +71,16 @@ int list_server_status_v1(smartlist_t *routers, char **router_status_out,
int dirserv_dump_directory_to_string(char **dir_out,
crypto_pk_env_t *private_key);
-int directory_fetches_from_authorities(or_options_t *options);
-int directory_fetches_dir_info_early(or_options_t *options);
-int directory_fetches_dir_info_later(or_options_t *options);
-int directory_caches_v2_dir_info(or_options_t *options);
+int directory_fetches_from_authorities(const or_options_t *options);
+int directory_fetches_dir_info_early(const or_options_t *options);
+int directory_fetches_dir_info_later(const or_options_t *options);
+int directory_caches_v2_dir_info(const or_options_t *options);
#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o)
-int directory_caches_dir_info(or_options_t *options);
-int directory_permits_begindir_requests(or_options_t *options);
-int directory_permits_controller_requests(or_options_t *options);
-int directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now);
+int directory_caches_dir_info(const or_options_t *options);
+int directory_permits_begindir_requests(const or_options_t *options);
+int directory_permits_controller_requests(const or_options_t *options);
+int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now);
void directory_set_dirty(void);
cached_dir_t *dirserv_get_directory(void);
@@ -111,13 +110,19 @@ void dirserv_orconn_tls_done(const char *address,
uint16_t or_port,
const char *digest_rcvd,
int as_advertised);
-int dirserv_should_launch_reachability_test(routerinfo_t *ri,
- routerinfo_t *ri_old);
+int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old);
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
void dirserv_test_reachability(time_t now);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain);
-int dirserv_would_reject_router(routerstatus_t *rs);
+ int complain,
+ int *valid_out);
+uint32_t dirserv_router_get_status(const routerinfo_t *router,
+ const char **msg);
+void dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus);
+
+int dirserv_would_reject_router(const routerstatus_t *rs);
int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);
int dirserv_have_any_microdesc(const smartlist_t *fps);
@@ -126,7 +131,7 @@ size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
size_t dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed);
int routerstatus_format_entry(char *buf, size_t buf_len,
- routerstatus_t *rs, const char *platform,
+ const routerstatus_t *rs, const char *platform,
routerstatus_format_type_t format);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index c6ce9f6776..01e2358c44 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -50,7 +50,7 @@ static int dirvote_publish_consensus(void);
static char *make_consensus_method_list(int low, int high, const char *sep);
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 11
+#define MAX_SUPPORTED_CONSENSUS_METHOD 12
/** Lowest consensus method that contains a 'directory-footer' marker */
#define MIN_METHOD_FOR_FOOTER 9
@@ -64,6 +64,10 @@ static char *make_consensus_method_list(int low, int high, const char *sep);
/** Lowest consensus method that generates microdescriptors */
#define MIN_METHOD_FOR_MICRODESC 8
+/** Lowest consensus method that ensures a majority of authorities voted
+ * for a param. */
+#define MIN_METHOD_FOR_MAJORITY_PARAMS 12
+
/* =====
* Voting
* =====*/
@@ -83,9 +87,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
const char *client_versions = NULL, *server_versions = NULL;
char *outp, *endp;
char fingerprint[FINGERPRINT_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char digest[DIGEST_LEN];
- struct in_addr in;
uint32_t addr;
routerlist_t *rl = router_get_routerlist();
char *version_lines = NULL;
@@ -98,8 +100,6 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
voter = smartlist_get(v3_ns->voters, 0);
addr = voter->addr;
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
base16_encode(fingerprint, sizeof(fingerprint),
v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
@@ -186,7 +186,8 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
flags,
params,
voter->nickname, fingerprint, voter->address,
- ipaddr, voter->dir_port, voter->or_port, voter->contact);
+ fmt_addr32(addr), voter->dir_port, voter->or_port,
+ voter->contact);
if (r < 0) {
log_err(LD_BUG, "Insufficient memory for network status line");
@@ -611,11 +612,16 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
return result;
}
+/** Minimum number of directory authorities voting for a parameter to
+ * include it in the consensus, if consensus method 12 or later is to be
+ * used. See proposal 178 for details. */
+#define MIN_VOTES_FOR_PARAM 3
+
/** Helper: given a list of valid networkstatus_t, return a new string
* containing the contents of the consensus network parameter set.
*/
/* private */ char *
-dirvote_compute_params(smartlist_t *votes)
+dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
{
int i;
int32_t *vals;
@@ -672,11 +678,17 @@ dirvote_compute_params(smartlist_t *votes)
next_param = smartlist_get(param_list, param_sl_idx+1);
if (!next_param || strncmp(next_param, param, cur_param_len)) {
/* We've reached the end of a series. */
- int32_t median = median_int32(vals, i);
- char *out_string = tor_malloc(64+cur_param_len);
- memcpy(out_string, param, cur_param_len);
- tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median);
- smartlist_add(output, out_string);
+ /* Make sure enough authorities voted on this param, unless the
+ * the consensus method we use is too old for that. */
+ if (method < MIN_METHOD_FOR_MAJORITY_PARAMS ||
+ i > total_authorities/2 ||
+ i >= MIN_VOTES_FOR_PARAM) {
+ int32_t median = median_int32(vals, i);
+ char *out_string = tor_malloc(64+cur_param_len);
+ memcpy(out_string, param, cur_param_len);
+ tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median);
+ smartlist_add(output, out_string);
+ }
i = 0;
if (next_param) {
@@ -1499,7 +1511,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
if (consensus_method >= MIN_METHOD_FOR_PARAMS) {
- params = dirvote_compute_params(votes);
+ params = dirvote_compute_params(votes, consensus_method,
+ total_authorities);
if (params) {
smartlist_add(chunks, tor_strdup("params "));
smartlist_add(chunks, params);
@@ -1530,8 +1543,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id);
SMARTLIST_FOREACH_BEGIN(dir_sources, const dir_src_ent_t *, e) {
- struct in_addr in;
- char ip[INET_NTOA_BUF_LEN];
char fingerprint[HEX_DIGEST_LEN+1];
char votedigest[HEX_DIGEST_LEN+1];
networkstatus_t *v = e->v;
@@ -1541,8 +1552,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
if (e->is_legacy)
tor_assert(consensus_method >= 2);
- in.s_addr = htonl(voter->addr);
- tor_inet_ntoa(&in, ip, sizeof(ip));
base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
DIGEST_LEN);
@@ -1550,7 +1559,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
tor_asprintf(&buf,
"dir-source %s%s %s %s %s %d %d\n",
voter->nickname, e->is_legacy ? "-legacy" : "",
- fingerprint, voter->address, ip,
+ fingerprint, voter->address, fmt_addr32(voter->addr),
voter->dir_port,
voter->or_port);
smartlist_add(chunks, buf);
@@ -2511,7 +2520,7 @@ authority_cert_dup(authority_cert_t *cert)
void
dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(timing_out);
@@ -2585,7 +2594,7 @@ static struct {
/** Set voting_schedule to hold the timing for the next vote we should be
* doing. */
void
-dirvote_recalculate_timing(or_options_t *options, time_t now)
+dirvote_recalculate_timing(const or_options_t *options, time_t now)
{
int interval, vote_delay, dist_delay;
time_t start;
@@ -2636,7 +2645,7 @@ dirvote_recalculate_timing(or_options_t *options, time_t now)
/** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
void
-dirvote_act(or_options_t *options, time_t now)
+dirvote_act(const or_options_t *options, time_t now)
{
if (!authdir_mode_v3(options))
return;
@@ -2751,7 +2760,7 @@ dirvote_perform_vote(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_vote->vote_body->dir,
pending_vote->vote_body->dir_len, 0);
log_notice(LD_DIR, "Vote posted.");
@@ -2770,7 +2779,7 @@ dirvote_fetch_missing_votes(void)
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
if (!dirvote_get_vote(ds->v3_identity_digest,
DGV_BY_ID|DGV_INCLUDE_PENDING)) {
@@ -2883,7 +2892,7 @@ list_v3_auth_ids(void)
char *keys;
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!tor_digest_is_zero(ds->v3_identity_digest))
smartlist_add(known_v3_keys,
tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
@@ -3078,7 +3087,7 @@ dirvote_compute_consensuses(void)
if (!pending_vote_list)
pending_vote_list = smartlist_create();
- n_voters = get_n_authorities(V3_AUTHORITY);
+ n_voters = get_n_authorities(V3_DIRINFO);
n_votes = smartlist_len(pending_vote_list);
if (n_votes <= n_voters/2) {
log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
@@ -3217,7 +3226,7 @@ dirvote_compute_consensuses(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_consensus_signatures,
strlen(pending_consensus_signatures), 0);
log_notice(LD_DIR, "Signature(s) posted.");
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index de11fcf997..1f4dc362b5 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -41,8 +41,8 @@ authority_cert_t *authority_cert_dup(authority_cert_t *cert);
/* vote scheduling */
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
time_t dirvote_get_start_of_next_interval(time_t now, int interval);
-void dirvote_recalculate_timing(or_options_t *options, time_t now);
-void dirvote_act(or_options_t *options, time_t now);
+void dirvote_recalculate_timing(const or_options_t *options, time_t now);
+void dirvote_act(const or_options_t *options, time_t now);
/* invoked on timers and by outside triggers. */
struct pending_vote_t * dirvote_add_vote(const char *vote_body,
@@ -60,6 +60,7 @@ const char *dirvote_get_pending_detached_signatures(void);
#define DGV_INCLUDE_PREVIOUS 4
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+ node_t *node,
routerinfo_t *ri, time_t now,
int naming, int listbadexits,
int listbaddirs, int vote_on_hsdirs);
@@ -83,7 +84,8 @@ document_signature_t *voter_get_sig_by_algorithm(
#ifdef DIRVOTE_PRIVATE
char *format_networkstatus_vote(crypto_pk_env_t *private_key,
networkstatus_t *v3_ns);
-char *dirvote_compute_params(smartlist_t *votes);
+char *dirvote_compute_params(smartlist_t *votes, int method,
+ int total_authorities);
#endif
#endif
diff --git a/src/or/dns.c b/src/or/dns.c
index 9b6b98afaf..beb110acb2 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -276,7 +276,7 @@ dns_init(void)
int
dns_reset(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (! server_mode(options)) {
if (!the_evdns_base) {
@@ -675,7 +675,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
cached_resolve_t *resolve;
cached_resolve_t search;
pending_connection_t *pending_connection;
- routerinfo_t *me;
+ const routerinfo_t *me;
tor_addr_t addr;
time_t now = time(NULL);
uint8_t is_reverse = 0;
@@ -687,7 +687,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
/* first check if exitconn->_base.address is an IP. If so, we already
* know the answer. */
- if (tor_addr_from_str(&addr, exitconn->_base.address) >= 0) {
+ if (tor_addr_parse(&addr, exitconn->_base.address) >= 0) {
if (tor_addr_family(&addr) == AF_INET) {
tor_addr_copy(&exitconn->_base.addr, &addr);
exitconn->address_ttl = DEFAULT_DNS_TTL;
@@ -721,7 +721,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
* .in-addr.arpa address but this isn't a resolve request, kill the
* connection.
*/
- if ((r = tor_addr_parse_reverse_lookup_name(&addr, exitconn->_base.address,
+ if ((r = tor_addr_parse_PTR_name(&addr, exitconn->_base.address,
AF_UNSPEC, 0)) != 0) {
if (r == 1) {
is_reverse = 1;
@@ -1026,7 +1026,7 @@ add_answer_to_cache(const char *address, uint8_t is_reverse, uint32_t addr,
static INLINE int
is_test_address(const char *address)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return options->ServerDNSTestAddresses &&
smartlist_string_isin_case(options->ServerDNSTestAddresses, address);
}
@@ -1177,7 +1177,7 @@ evdns_err_is_transient(int err)
static int
configure_nameservers(int force)
{
- or_options_t *options;
+ const or_options_t *options;
const char *conf_fname;
struct stat st;
int r;
@@ -1198,7 +1198,7 @@ configure_nameservers(int force)
#ifdef HAVE_EVDNS_SET_DEFAULT_OUTGOING_BIND_ADDRESS
if (options->OutboundBindAddress) {
tor_addr_t addr;
- if (tor_addr_from_str(&addr, options->OutboundBindAddress) < 0) {
+ if (tor_addr_parse(&addr, options->OutboundBindAddress) < 0) {
log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.",
options->OutboundBindAddress);
} else {
@@ -1395,6 +1395,10 @@ launch_resolve(edge_connection_t *exitconn)
int r;
int options = get_options()->ServerDNSSearchDomains ? 0
: DNS_QUERY_NO_SEARCH;
+
+ if (get_options()->DisableNetwork)
+ return -1;
+
/* What? Nameservers not configured? Sounds like a bug. */
if (!nameservers_configured) {
log_warn(LD_EXIT, "(Harmless.) Nameservers not configured, but resolve "
@@ -1404,7 +1408,7 @@ launch_resolve(edge_connection_t *exitconn)
}
}
- r = tor_addr_parse_reverse_lookup_name(
+ r = tor_addr_parse_PTR_name(
&a, exitconn->_base.address, AF_UNSPEC, 0);
tor_assert(the_evdns_base);
@@ -1595,12 +1599,15 @@ launch_wildcard_check(int min_len, int max_len, const char *suffix)
static void
launch_test_addresses(int fd, short event, void *args)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
struct evdns_request *req;
(void)fd;
(void)event;
(void)args;
+ if (options->DisableNetwork)
+ return;
+
log_info(LD_EXIT, "Launching checks to see whether our nameservers like to "
"hijack *everything*.");
/* This situation is worse than the failure-hijacking situation. When this
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index f2c473dfc5..7f519398fa 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -29,8 +29,10 @@
* DNSPort. We need to eventually answer the request <b>req</b>.
*/
static void
-evdns_server_callback(struct evdns_server_request *req, void *_data)
+evdns_server_callback(struct evdns_server_request *req, void *data_)
{
+ const listener_connection_t *listener = data_;
+ entry_connection_t *entry_conn;
edge_connection_t *conn;
int i = 0;
struct evdns_server_question *q = NULL;
@@ -43,7 +45,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
char *q_name;
tor_assert(req);
- tor_assert(_data == NULL);
+
log_info(LD_APP, "Got a new DNS request!");
req->flags |= 0x80; /* set RA */
@@ -114,8 +116,9 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
}
/* Make a new dummy AP connection, and attach the request to it. */
- conn = edge_connection_new(CONN_TYPE_AP, AF_INET);
- conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
+ entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT;
conn->is_dns_request = 1;
tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr);
@@ -123,23 +126,27 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
TO_CONN(conn)->address = tor_dup_addr(&tor_addr);
if (q->type == EVDNS_TYPE_A)
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
else
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
- strlcpy(conn->socks_request->address, q->name,
- sizeof(conn->socks_request->address));
+ strlcpy(entry_conn->socks_request->address, q->name,
+ sizeof(entry_conn->socks_request->address));
- conn->dns_server_request = req;
+ entry_conn->socks_request->listener_type = listener->_base.type;
+ entry_conn->dns_server_request = req;
+ entry_conn->isolation_flags = listener->isolation_flags;
+ entry_conn->session_group = listener->session_group;
+ entry_conn->nym_epoch = get_signewnym_epoch();
- if (connection_add(TO_CONN(conn)) < 0) {
+ if (connection_add(ENTRY_TO_CONN(entry_conn)) < 0) {
log_warn(LD_APP, "Couldn't register dummy connection for DNS request");
evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
- connection_free(TO_CONN(conn));
+ connection_free(ENTRY_TO_CONN(entry_conn));
return;
}
- control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+ control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0);
/* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will
@@ -148,7 +155,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
escaped_safe_str_client(q->name));
q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */
- connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+ connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
/* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
@@ -164,22 +171,30 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
int
dnsserv_launch_request(const char *name, int reverse)
{
+ entry_connection_t *entry_conn;
edge_connection_t *conn;
char *q_name;
/* Make a new dummy AP connection, and attach the request to it. */
- conn = edge_connection_new(CONN_TYPE_AP, AF_INET);
+ entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
if (reverse)
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
else
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
conn->is_dns_request = 1;
- strlcpy(conn->socks_request->address, name,
- sizeof(conn->socks_request->address));
+ strlcpy(entry_conn->socks_request->address, name,
+ sizeof(entry_conn->socks_request->address));
+
+ entry_conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER;
+ entry_conn->original_dest_address = tor_strdup(name);
+ entry_conn->session_group = SESSION_GROUP_CONTROL_RESOLVE;
+ entry_conn->nym_epoch = get_signewnym_epoch();
+ entry_conn->isolation_flags = ISO_DEFAULT;
if (connection_add(TO_CONN(conn))<0) {
log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request");
@@ -194,7 +209,7 @@ dnsserv_launch_request(const char *name, int reverse)
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
escaped_safe_str_client(name));
q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */
- connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+ connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
/* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
@@ -206,7 +221,7 @@ dnsserv_launch_request(const char *name, int reverse)
/** If there is a pending request on <b>conn</b> that's waiting for an answer,
* send back an error and free the request. */
void
-dnsserv_reject_request(edge_connection_t *conn)
+dnsserv_reject_request(entry_connection_t *conn)
{
if (conn->dns_server_request) {
evdns_server_request_respond(conn->dns_server_request,
@@ -252,7 +267,7 @@ evdns_get_orig_address(const struct evdns_server_request *req,
* <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do
* any caching; that's handled elsewhere. */
void
-dnsserv_resolved(edge_connection_t *conn,
+dnsserv_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
@@ -305,12 +320,15 @@ dnsserv_resolved(edge_connection_t *conn,
void
dnsserv_configure_listener(connection_t *conn)
{
+ listener_connection_t *listener_conn;
tor_assert(conn);
tor_assert(SOCKET_OK(conn->s));
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
- conn->dns_server_port =
- tor_evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL);
+ listener_conn = TO_LISTENER_CONN(conn);
+ listener_conn->dns_server_port =
+ tor_evdns_add_server_port(conn->s, 0, evdns_server_callback,
+ listener_conn);
}
/** Free the evdns server port for <b>conn</b>, which must be an
@@ -318,12 +336,15 @@ dnsserv_configure_listener(connection_t *conn)
void
dnsserv_close_listener(connection_t *conn)
{
+ listener_connection_t *listener_conn;
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
- if (conn->dns_server_port) {
- evdns_close_server_port(conn->dns_server_port);
- conn->dns_server_port = NULL;
+ listener_conn = TO_LISTENER_CONN(conn);
+
+ if (listener_conn->dns_server_port) {
+ evdns_close_server_port(listener_conn->dns_server_port);
+ listener_conn->dns_server_port = NULL;
}
}
diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h
index fcca868885..73ec365647 100644
--- a/src/or/dnsserv.h
+++ b/src/or/dnsserv.h
@@ -14,12 +14,12 @@
void dnsserv_configure_listener(connection_t *conn);
void dnsserv_close_listener(connection_t *conn);
-void dnsserv_resolved(edge_connection_t *conn,
+void dnsserv_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
int ttl);
-void dnsserv_reject_request(edge_connection_t *conn);
+void dnsserv_reject_request(entry_connection_t *conn);
int dnsserv_launch_request(const char *name, int is_reverse);
#endif
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index 42e16aec7a..7cd5d80afb 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -1,12 +1,18 @@
-/* The original version of this module was written by Adam Langley; for
- * a history of modifications, check out the subversion logs.
+/* READ THIS COMMENT BEFORE HACKING THIS FILE.
*
- * When editing this module, try to keep it re-mergeable by Adam. Don't
- * reformat the whitespace, add Tor dependencies, or so on.
+ * This eventdns.c copy has diverged a bit from Libevent's version, and it's
+ * no longer easy to resynchronize them. Once Tor requires Libevent 2.0, we
+ * will just dump this file and use Libevent's evdns code.
*
- * TODO:
- * - Replace all externally visible magic numbers with #defined constants.
- * - Write documentation for APIs of all external functions.
+ * Therefore, you probably shouldn't make any change here without making it to
+ * Libevent as well: it's not good for the implementation to diverge even
+ * more. Also, we can't shouldn't wantonly the API here (since Libevent APIs
+ * can't change in ways that break user behavior). Also, we shouldn't bother
+ * with cosmetic changes: the whole module is slated for demolition, so
+ * there's no point dusting the linebreaks or re-painting the parser.
+ *
+ * (We can't just drop the Libevent 2.0 evdns implementation in here instead,
+ * since it depends pretty heavily on parts of Libevent 2.0.)
*/
/* Async DNS Library
@@ -75,7 +81,6 @@
#include <stdint.h>
#endif
#include <stdlib.h>
-#include <string.h>
#include <errno.h>
#include <assert.h>
#ifdef HAVE_UNISTD_H
@@ -1831,8 +1836,8 @@ evdns_server_request_respond(struct evdns_server_request *_req, int err)
r = sendto(port->socket, req->response, req->response_len, 0,
(struct sockaddr*) &req->addr, req->addrlen);
if (r<0) {
- int err = last_error(port->socket);
- if (! error_is_eagain(err))
+ int error = last_error(port->socket);
+ if (! error_is_eagain(error))
return -1;
if (port->pending_replies) {
@@ -2291,7 +2296,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- ns->socket = socket(address->sa_family, SOCK_DGRAM, 0);
+ ns->socket = tor_open_socket(address->sa_family, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
#ifdef WIN32
{
@@ -3040,7 +3045,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) {
log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
- fd = open(filename, O_RDONLY);
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
if (fd < 0) {
evdns_resolv_set_defaults(flags);
return 1;
@@ -3460,7 +3465,7 @@ main(int c, char **v) {
if (servertest) {
int sock;
struct sockaddr_in my_addr;
- sock = socket(PF_INET, SOCK_DGRAM, 0);
+ sock = tor_open_socket(PF_INET, SOCK_DGRAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(10053);
diff --git a/src/or/geoip.c b/src/or/geoip.c
index c51142c82e..73194ae9c6 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -44,6 +44,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL;
/** A list of all known geoip_entry_t, sorted by ip_low. */
static smartlist_t *geoip_entries = NULL;
+/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */
+static char geoip_digest[DIGEST_LEN];
+
/** Return the index of the <b>country</b>'s entry in the GeoIP DB
* if it is a valid 2-letter country code, otherwise return -1.
*/
@@ -113,10 +116,10 @@ geoip_parse_entry(const char *line)
++line;
if (*line == '#')
return 0;
- if (sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
+ if (tor_sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
geoip_add_entry(low, high, b);
return 0;
- } else if (sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
+ } else if (tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
geoip_add_entry(low, high, b);
return 0;
} else {
@@ -159,7 +162,7 @@ _geoip_compare_key_to_entry(const void *_key, const void **_member)
/** Return 1 if we should collect geoip stats on bridge users, and
* include them in our extrainfo descriptor. Else return 0. */
int
-should_record_bridge_info(or_options_t *options)
+should_record_bridge_info(const or_options_t *options)
{
return options->BridgeRelay && options->BridgeRecordUsageByCountry;
}
@@ -196,13 +199,14 @@ init_geoip_countries(void)
* with '#' (comments).
*/
int
-geoip_load_file(const char *filename, or_options_t *options)
+geoip_load_file(const char *filename, const or_options_t *options)
{
FILE *f;
const char *msg = "";
int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
+ crypto_digest_env_t *geoip_digest_env = NULL;
clear_geoip_db();
- if (!(f = fopen(filename, "r"))) {
+ if (!(f = tor_fopen_cloexec(filename, "r"))) {
log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s",
filename, msg);
return -1;
@@ -214,11 +218,13 @@ geoip_load_file(const char *filename, or_options_t *options)
smartlist_free(geoip_entries);
}
geoip_entries = smartlist_create();
+ geoip_digest_env = crypto_new_digest_env();
log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename);
while (!feof(f)) {
char buf[512];
if (fgets(buf, (int)sizeof(buf), f) == NULL)
break;
+ crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf));
/* FFFF track full country name. */
geoip_parse_entry(buf);
}
@@ -231,6 +237,11 @@ geoip_load_file(const char *filename, or_options_t *options)
* country. */
refresh_all_country_info();
+ /* Remember file digest so that we can include it in our extra-info
+ * descriptors. */
+ crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
+ crypto_free_digest_env(geoip_digest_env);
+
return 0;
}
@@ -278,6 +289,15 @@ geoip_is_loaded(void)
return geoip_countries != NULL && geoip_entries != NULL;
}
+/** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The
+ * result does not need to be deallocated, but will be overwritten by the
+ * next call of hex_str(). */
+const char *
+geoip_db_digest(void)
+{
+ return hex_str(geoip_digest, DIGEST_LEN);
+}
+
/** Entry in a map from IP address to the last time we've seen an incoming
* connection from that IP address. Used by bridges only, to track which
* countries have them blocked. */
@@ -404,7 +424,7 @@ void
geoip_note_client_seen(geoip_client_action_t action,
uint32_t addr, time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
clientmap_entry_t lookup, *ent;
if (action == GEOIP_CLIENT_CONNECT) {
/* Only remember statistics as entry guard or as bridge. */
@@ -910,10 +930,9 @@ geoip_dirreq_stats_init(time_t now)
start_of_dirreq_stats_interval = now;
}
-/** Stop collecting directory request stats in a way that we can re-start
- * doing so in geoip_dirreq_stats_init(). */
+/** Reset counters for dirreq stats. */
void
-geoip_dirreq_stats_term(void)
+geoip_reset_dirreq_stats(time_t now)
{
SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
c->n_v2_ns_requests = c->n_v3_ns_requests = 0;
@@ -945,59 +964,44 @@ geoip_dirreq_stats_term(void)
tor_free(this);
}
}
- start_of_dirreq_stats_interval = 0;
+ start_of_dirreq_stats_interval = now;
}
-/** Write dirreq statistics to $DATADIR/stats/dirreq-stats and return when
- * we would next want to write. */
-time_t
-geoip_dirreq_stats_write(time_t now)
+/** Stop collecting directory request stats in a way that we can re-start
+ * doing so in geoip_dirreq_stats_init(). */
+void
+geoip_dirreq_stats_term(void)
{
- char *statsdir = NULL, *filename = NULL;
- char *data_v2 = NULL, *data_v3 = NULL;
- char written[ISO_TIME_LEN+1];
- open_file_t *open_file = NULL;
+ geoip_reset_dirreq_stats(0);
+}
+
+/** Return a newly allocated string containing the dirreq statistics
+ * until <b>now</b>, or NULL if we're not collecting dirreq stats. Caller
+ * must ensure start_of_dirreq_stats_interval is in the past. */
+char *
+geoip_format_dirreq_stats(time_t now)
+{
+ char t[ISO_TIME_LEN+1];
double v2_share = 0.0, v3_share = 0.0;
- FILE *out;
int i;
+ char *v3_ips_string, *v2_ips_string, *v3_reqs_string, *v2_reqs_string,
+ *v2_share_string = NULL, *v3_share_string = NULL,
+ *v3_direct_dl_string, *v2_direct_dl_string,
+ *v3_tunneled_dl_string, *v2_tunneled_dl_string;
+ char *result;
if (!start_of_dirreq_stats_interval)
- return 0; /* Not initialized. */
- if (start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL > now)
- goto done; /* Not ready to write. */
+ return NULL; /* Not initialized. */
- /* Discard all items in the client history that are too old. */
- geoip_remove_old_clients(start_of_dirreq_stats_interval);
+ tor_assert(now >= start_of_dirreq_stats_interval);
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
- goto done;
- filename = get_datadir_fname2("stats", "dirreq-stats");
- data_v2 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
- data_v3 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS);
- format_iso_time(written, now);
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT,
- 0600, &open_file);
- if (!out)
- goto done;
- if (fprintf(out, "dirreq-stats-end %s (%d s)\ndirreq-v3-ips %s\n"
- "dirreq-v2-ips %s\n", written,
- (unsigned) (now - start_of_dirreq_stats_interval),
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
- tor_free(data_v2);
- tor_free(data_v3);
+ format_iso_time(t, now);
+ v2_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
+ v3_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS);
+ v2_reqs_string = geoip_get_request_history(
+ GEOIP_CLIENT_NETWORKSTATUS_V2);
+ v3_reqs_string = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS);
- data_v2 = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
- data_v3 = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS);
- if (fprintf(out, "dirreq-v3-reqs %s\ndirreq-v2-reqs %s\n",
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
- tor_free(data_v2);
- tor_free(data_v3);
- SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
- c->n_v2_ns_requests = c->n_v3_ns_requests = 0;
- });
#define RESPONSE_GRANULARITY 8
for (i = 0; i < GEOIP_NS_RESPONSE_NUM; i++) {
ns_v2_responses[i] = round_uint32_to_next_multiple_of(
@@ -1006,61 +1010,117 @@ geoip_dirreq_stats_write(time_t now)
ns_v3_responses[i], RESPONSE_GRANULARITY);
}
#undef RESPONSE_GRANULARITY
- if (fprintf(out, "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u,"
- "not-found=%u,not-modified=%u,busy=%u\n",
- ns_v3_responses[GEOIP_SUCCESS],
- ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS],
- ns_v3_responses[GEOIP_REJECT_UNAVAILABLE],
- ns_v3_responses[GEOIP_REJECT_NOT_FOUND],
- ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED],
- ns_v3_responses[GEOIP_REJECT_BUSY]) < 0)
- goto done;
- if (fprintf(out, "dirreq-v2-resp ok=%u,unavailable=%u,"
- "not-found=%u,not-modified=%u,busy=%u\n",
- ns_v2_responses[GEOIP_SUCCESS],
- ns_v2_responses[GEOIP_REJECT_UNAVAILABLE],
- ns_v2_responses[GEOIP_REJECT_NOT_FOUND],
- ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED],
- ns_v2_responses[GEOIP_REJECT_BUSY]) < 0)
- goto done;
- memset(ns_v2_responses, 0, sizeof(ns_v2_responses));
- memset(ns_v3_responses, 0, sizeof(ns_v3_responses));
+
if (!geoip_get_mean_shares(now, &v2_share, &v3_share)) {
- if (fprintf(out, "dirreq-v2-share %0.2lf%%\n", v2_share*100) < 0)
- goto done;
- if (fprintf(out, "dirreq-v3-share %0.2lf%%\n", v3_share*100) < 0)
- goto done;
+ tor_asprintf(&v2_share_string, "dirreq-v2-share %0.2lf%%\n",
+ v2_share*100);
+ tor_asprintf(&v3_share_string, "dirreq-v3-share %0.2lf%%\n",
+ v3_share*100);
}
- data_v2 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS_V2,
- DIRREQ_DIRECT);
- data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS,
- DIRREQ_DIRECT);
- if (fprintf(out, "dirreq-v3-direct-dl %s\ndirreq-v2-direct-dl %s\n",
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
- tor_free(data_v2);
- tor_free(data_v3);
- data_v2 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS_V2,
- DIRREQ_TUNNELED);
- data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS,
- DIRREQ_TUNNELED);
- if (fprintf(out, "dirreq-v3-tunneled-dl %s\ndirreq-v2-tunneled-dl %s\n",
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
+ v2_direct_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_DIRECT);
+ v3_direct_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_DIRECT);
+
+ v2_tunneled_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_TUNNELED);
+ v3_tunneled_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_TUNNELED);
+
+ /* Put everything together into a single string. */
+ tor_asprintf(&result, "dirreq-stats-end %s (%d s)\n"
+ "dirreq-v3-ips %s\n"
+ "dirreq-v2-ips %s\n"
+ "dirreq-v3-reqs %s\n"
+ "dirreq-v2-reqs %s\n"
+ "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u,"
+ "not-found=%u,not-modified=%u,busy=%u\n"
+ "dirreq-v2-resp ok=%u,unavailable=%u,"
+ "not-found=%u,not-modified=%u,busy=%u\n"
+ "%s"
+ "%s"
+ "dirreq-v3-direct-dl %s\n"
+ "dirreq-v2-direct-dl %s\n"
+ "dirreq-v3-tunneled-dl %s\n"
+ "dirreq-v2-tunneled-dl %s\n",
+ t,
+ (unsigned) (now - start_of_dirreq_stats_interval),
+ v3_ips_string ? v3_ips_string : "",
+ v2_ips_string ? v2_ips_string : "",
+ v3_reqs_string ? v3_reqs_string : "",
+ v2_reqs_string ? v2_reqs_string : "",
+ ns_v3_responses[GEOIP_SUCCESS],
+ ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS],
+ ns_v3_responses[GEOIP_REJECT_UNAVAILABLE],
+ ns_v3_responses[GEOIP_REJECT_NOT_FOUND],
+ ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED],
+ ns_v3_responses[GEOIP_REJECT_BUSY],
+ ns_v2_responses[GEOIP_SUCCESS],
+ ns_v2_responses[GEOIP_REJECT_UNAVAILABLE],
+ ns_v2_responses[GEOIP_REJECT_NOT_FOUND],
+ ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED],
+ ns_v2_responses[GEOIP_REJECT_BUSY],
+ v2_share_string ? v2_share_string : "",
+ v3_share_string ? v3_share_string : "",
+ v3_direct_dl_string ? v3_direct_dl_string : "",
+ v2_direct_dl_string ? v2_direct_dl_string : "",
+ v3_tunneled_dl_string ? v3_tunneled_dl_string : "",
+ v2_tunneled_dl_string ? v2_tunneled_dl_string : "");
+
+ /* Free partial strings. */
+ tor_free(v3_ips_string);
+ tor_free(v2_ips_string);
+ tor_free(v3_reqs_string);
+ tor_free(v2_reqs_string);
+ tor_free(v2_share_string);
+ tor_free(v3_share_string);
+ tor_free(v3_direct_dl_string);
+ tor_free(v2_direct_dl_string);
+ tor_free(v3_tunneled_dl_string);
+ tor_free(v2_tunneled_dl_string);
- finish_writing_to_file(open_file);
- open_file = NULL;
+ return result;
+}
- start_of_dirreq_stats_interval = now;
+/** If 24 hours have passed since the beginning of the current dirreq
+ * stats period, write dirreq stats to $DATADIR/stats/dirreq-stats
+ * (possibly overwriting an existing file) and reset counters. Return
+ * when we would next want to write dirreq stats or 0 if we never want to
+ * write. */
+time_t
+geoip_dirreq_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_dirreq_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write. */
+
+ /* Discard all items in the client history that are too old. */
+ geoip_remove_old_clients(start_of_dirreq_stats_interval);
+
+ /* Generate history string .*/
+ str = geoip_format_dirreq_stats(now);
+
+ /* Write dirreq-stats string to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
+ goto done;
+ }
+ filename = get_datadir_fname2("stats", "dirreq-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write dirreq statistics to disk!");
+
+ /* Reset measurement interval start. */
+ geoip_reset_dirreq_stats(now);
done:
- if (open_file)
- abort_writing_to_file(open_file);
- tor_free(filename);
tor_free(statsdir);
- tor_free(data_v2);
- tor_free(data_v3);
+ tor_free(filename);
+ tor_free(str);
return start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL;
}
@@ -1140,8 +1200,8 @@ static char *bridge_stats_extrainfo = NULL;
/** Return a newly allocated string holding our bridge usage stats by country
* in a format suitable for inclusion in an extrainfo document. Return NULL on
* failure. */
-static char *
-format_bridge_stats_extrainfo(time_t now)
+char *
+geoip_format_bridge_stats(time_t now)
{
char *out = NULL, *data = NULL;
long duration = now - start_of_bridge_stats_interval;
@@ -1149,6 +1209,8 @@ format_bridge_stats_extrainfo(time_t now)
if (duration < 0)
return NULL;
+ if (!start_of_bridge_stats_interval)
+ return NULL; /* Not initialized. */
format_iso_time(written, now);
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
@@ -1198,7 +1260,7 @@ geoip_bridge_stats_write(time_t now)
geoip_remove_old_clients(start_of_bridge_stats_interval);
/* Generate formatted string */
- val = format_bridge_stats_extrainfo(now);
+ val = geoip_format_bridge_stats(now);
if (val == NULL)
goto done;
@@ -1275,25 +1337,54 @@ geoip_entry_stats_init(time_t now)
start_of_entry_stats_interval = now;
}
+/** Reset counters for entry stats. */
+void
+geoip_reset_entry_stats(time_t now)
+{
+ client_history_clear();
+ start_of_entry_stats_interval = now;
+}
+
/** Stop collecting entry stats in a way that we can re-start doing so in
* geoip_entry_stats_init(). */
void
geoip_entry_stats_term(void)
{
- client_history_clear();
- start_of_entry_stats_interval = 0;
+ geoip_reset_entry_stats(0);
}
-/** Write entry statistics to $DATADIR/stats/entry-stats and return time
- * when we would next want to write. */
+/** Return a newly allocated string containing the entry statistics
+ * until <b>now</b>, or NULL if we're not collecting entry stats. Caller
+ * must ensure start_of_entry_stats_interval lies in the past. */
+char *
+geoip_format_entry_stats(time_t now)
+{
+ char t[ISO_TIME_LEN+1];
+ char *data = NULL;
+ char *result;
+
+ if (!start_of_entry_stats_interval)
+ return NULL; /* Not initialized. */
+
+ tor_assert(now >= start_of_entry_stats_interval);
+
+ data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
+ format_iso_time(t, now);
+ tor_asprintf(&result, "entry-stats-end %s (%u s)\nentry-ips %s\n",
+ t, (unsigned) (now - start_of_entry_stats_interval),
+ data ? data : "");
+ tor_free(data);
+ return result;
+}
+
+/** If 24 hours have passed since the beginning of the current entry stats
+ * period, write entry stats to $DATADIR/stats/entry-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write entry stats or 0 if we never want to write. */
time_t
geoip_entry_stats_write(time_t now)
{
- char *statsdir = NULL, *filename = NULL;
- char *data = NULL;
- char written[ISO_TIME_LEN+1];
- open_file_t *open_file = NULL;
- FILE *out;
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
if (!start_of_entry_stats_interval)
return 0; /* Not initialized. */
@@ -1303,31 +1394,26 @@ geoip_entry_stats_write(time_t now)
/* Discard all items in the client history that are too old. */
geoip_remove_old_clients(start_of_entry_stats_interval);
+ /* Generate history string .*/
+ str = geoip_format_entry_stats(now);
+
+ /* Write entry-stats string to disk. */
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
goto done;
+ }
filename = get_datadir_fname2("stats", "entry-stats");
- data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
- format_iso_time(written, now);
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT,
- 0600, &open_file);
- if (!out)
- goto done;
- if (fprintf(out, "entry-stats-end %s (%u s)\nentry-ips %s\n",
- written, (unsigned) (now - start_of_entry_stats_interval),
- data ? data : "") < 0)
- goto done;
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write entry statistics to disk!");
- start_of_entry_stats_interval = now;
+ /* Reset measurement interval start. */
+ geoip_reset_entry_stats(now);
- finish_writing_to_file(open_file);
- open_file = NULL;
done:
- if (open_file)
- abort_writing_to_file(open_file);
- tor_free(filename);
tor_free(statsdir);
- tor_free(data);
+ tor_free(filename);
+ tor_free(str);
return start_of_entry_stats_interval + WRITE_STATS_INTERVAL;
}
diff --git a/src/or/geoip.h b/src/or/geoip.h
index 24f7c5b931..ce3841967f 100644
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@ -15,12 +15,13 @@
#ifdef GEOIP_PRIVATE
int geoip_parse_entry(const char *line);
#endif
-int should_record_bridge_info(or_options_t *options);
-int geoip_load_file(const char *filename, or_options_t *options);
+int should_record_bridge_info(const or_options_t *options);
+int geoip_load_file(const char *filename, const or_options_t *options);
int geoip_get_country_by_ip(uint32_t ipaddr);
int geoip_get_n_countries(void);
const char *geoip_get_country_name(country_t num);
int geoip_is_loaded(void);
+const char *geoip_db_digest(void);
country_t geoip_get_country(const char *countrycode);
void geoip_note_client_seen(geoip_client_action_t action,
@@ -42,12 +43,17 @@ void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type,
dirreq_state_t new_state);
void geoip_dirreq_stats_init(time_t now);
+void geoip_reset_dirreq_stats(time_t now);
+char *geoip_format_dirreq_stats(time_t now);
time_t geoip_dirreq_stats_write(time_t now);
void geoip_dirreq_stats_term(void);
void geoip_entry_stats_init(time_t now);
time_t geoip_entry_stats_write(time_t now);
void geoip_entry_stats_term(void);
+void geoip_reset_entry_stats(time_t now);
+char *geoip_format_entry_stats(time_t now);
void geoip_bridge_stats_init(time_t now);
+char *geoip_format_bridge_stats(time_t now);
time_t geoip_bridge_stats_write(time_t now);
void geoip_bridge_stats_term(void);
const char *geoip_get_bridge_stats_extrainfo(time_t);
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index aebce4cc88..ce64581d1c 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -21,6 +21,7 @@ hibernating, phase 2:
- close all OR/AP/exit conns)
*/
+#define HIBERNATE_PRIVATE
#include "or.h"
#include "config.h"
#include "connection.h"
@@ -29,26 +30,11 @@ hibernating, phase 2:
#include "main.h"
#include "router.h"
-/** Possible values of hibernate_state */
-typedef enum {
- /** We are running normally. */
- HIBERNATE_STATE_LIVE=1,
- /** We're trying to shut down cleanly, and we'll kill all active connections
- * at shutdown_time. */
- HIBERNATE_STATE_EXITING=2,
- /** We're running low on allocated bandwidth for this period, so we won't
- * accept any new connections. */
- HIBERNATE_STATE_LOWBANDWIDTH=3,
- /** We are hibernating, and we won't wake up till there's more bandwidth to
- * use. */
- HIBERNATE_STATE_DORMANT=4
-} hibernate_state_t;
-
extern long stats_n_seconds_working; /* published uptime */
/** Are we currently awake, asleep, running out of bandwidth, or shutting
* down? */
-static hibernate_state_t hibernate_state = HIBERNATE_STATE_LIVE;
+static hibernate_state_t hibernate_state = HIBERNATE_STATE_INITIAL;
/** If are hibernating, when do we plan to wake up? Set to 0 if we
* aren't hibernating. */
static time_t hibernate_end_time = 0;
@@ -134,7 +120,7 @@ static void accounting_set_wakeup_time(void);
* options->AccountingStart. Return 0 on success, -1 on failure. If
* <b>validate_only</b> is true, do not change the current settings. */
int
-accounting_parse_options(or_options_t *options, int validate_only)
+accounting_parse_options(const or_options_t *options, int validate_only)
{
time_unit_t unit;
int ok, idx;
@@ -249,7 +235,7 @@ accounting_parse_options(or_options_t *options, int validate_only)
* hibernate, return 1, else return 0.
*/
int
-accounting_is_enabled(or_options_t *options)
+accounting_is_enabled(const or_options_t *options)
{
if (options->AccountingMax)
return 1;
@@ -411,7 +397,7 @@ static void
update_expected_bandwidth(void)
{
uint64_t expected;
- or_options_t *options= get_options();
+ const or_options_t *options= get_options();
uint64_t max_configured = (options->RelayBandwidthRate > 0 ?
options->RelayBandwidthRate :
options->BandwidthRate) * 60;
@@ -749,8 +735,7 @@ hibernate_soft_limit_reached(void)
static void
hibernate_begin(hibernate_state_t new_state, time_t now)
{
- connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (new_state == HIBERNATE_STATE_EXITING &&
hibernate_state != HIBERNATE_STATE_LIVE) {
@@ -770,15 +755,7 @@ hibernate_begin(hibernate_state_t new_state, time_t now)
}
/* close listeners. leave control listener(s). */
- while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) ||
- (conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) ||
- (conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) ||
- (conn = connection_get_by_type(CONN_TYPE_AP_DNS_LISTENER)) ||
- (conn = connection_get_by_type(CONN_TYPE_AP_NATD_LISTENER)) ||
- (conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) {
- log_info(LD_NET,"Closing listener type %d", conn->type);
- connection_mark_for_close(conn);
- }
+ connection_mark_all_noncontrol_listeners();
/* XXX kill intro point circs */
/* XXX upload rendezvous service descriptors with no intro points */
@@ -804,10 +781,12 @@ static void
hibernate_end(hibernate_state_t new_state)
{
tor_assert(hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH ||
- hibernate_state == HIBERNATE_STATE_DORMANT);
+ hibernate_state == HIBERNATE_STATE_DORMANT ||
+ hibernate_state == HIBERNATE_STATE_INITIAL);
/* listeners will be relaunched in run_scheduled_events() in main.c */
- log_notice(LD_ACCT,"Hibernation period ended. Resuming normal activity.");
+ if (hibernate_state != HIBERNATE_STATE_INITIAL)
+ log_notice(LD_ACCT,"Hibernation period ended. Resuming normal activity.");
hibernate_state = new_state;
hibernate_end_time = 0; /* no longer hibernating */
@@ -856,7 +835,7 @@ hibernate_go_dormant(time_t now)
connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING);
log_info(LD_NET,"Closing conn type %d", conn->type);
if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */
- connection_mark_unattached_ap(TO_EDGE_CONN(conn),
+ connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
END_STREAM_REASON_HIBERNATING);
else
connection_mark_for_close(conn);
@@ -939,11 +918,12 @@ consider_hibernation(time_t now)
/* Else, we aren't hibernating. See if it's time to start hibernating, or to
* go dormant. */
- if (hibernate_state == HIBERNATE_STATE_LIVE) {
+ if (hibernate_state == HIBERNATE_STATE_LIVE ||
+ hibernate_state == HIBERNATE_STATE_INITIAL) {
if (hibernate_soft_limit_reached()) {
log_notice(LD_ACCT,
"Bandwidth soft limit reached; commencing hibernation. "
- "No new conncetions will be accepted");
+ "No new connections will be accepted");
hibernate_begin(HIBERNATE_STATE_LOWBANDWIDTH, now);
} else if (accounting_enabled && now < interval_wakeup_time) {
format_local_iso_time(buf,interval_wakeup_time);
@@ -951,6 +931,8 @@ consider_hibernation(time_t now)
"Commencing hibernation. We will wake up at %s local time.",
buf);
hibernate_go_dormant(now);
+ } else if (hibernate_state == HIBERNATE_STATE_INITIAL) {
+ hibernate_end(HIBERNATE_STATE_LIVE);
}
}
@@ -1017,3 +999,13 @@ getinfo_helper_accounting(control_connection_t *conn,
return 0;
}
+/**
+ * Manually change the hibernation state. Private; used only by the unit
+ * tests.
+ */
+void
+hibernate_set_state_for_testing_(hibernate_state_t newstate)
+{
+ hibernate_state = newstate;
+}
+
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index 2aea0fab0c..78e7bb75e9 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -12,8 +12,8 @@
#ifndef _TOR_HIBERNATE_H
#define _TOR_HIBERNATE_H
-int accounting_parse_options(or_options_t *options, int validate_only);
-int accounting_is_enabled(or_options_t *options);
+int accounting_parse_options(const or_options_t *options, int validate_only);
+int accounting_is_enabled(const or_options_t *options);
void configure_accounting(time_t now);
void accounting_run_housekeeping(time_t now);
void accounting_add_bytes(size_t n_read, size_t n_written, int seconds);
@@ -25,5 +25,27 @@ int getinfo_helper_accounting(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
+#ifdef HIBERNATE_PRIVATE
+/** Possible values of hibernate_state */
+typedef enum {
+ /** We are running normally. */
+ HIBERNATE_STATE_LIVE=1,
+ /** We're trying to shut down cleanly, and we'll kill all active connections
+ * at shutdown_time. */
+ HIBERNATE_STATE_EXITING=2,
+ /** We're running low on allocated bandwidth for this period, so we won't
+ * accept any new connections. */
+ HIBERNATE_STATE_LOWBANDWIDTH=3,
+ /** We are hibernating, and we won't wake up till there's more bandwidth to
+ * use. */
+ HIBERNATE_STATE_DORMANT=4,
+ /** We start out in state default, which means we havent decided which state
+ * we're in. */
+ HIBERNATE_STATE_INITIAL=5
+} hibernate_state_t;
+
+void hibernate_set_state_for_testing_(hibernate_state_t newstate);
+#endif
+
#endif
diff --git a/src/or/main.c b/src/or/main.c
index 289d805503..da45f5a681 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -33,9 +33,11 @@
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "ntmain.h"
#include "onion.h"
#include "policies.h"
+#include "transports.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -44,6 +46,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#include "status.h"
#ifdef USE_DMALLOC
#include <dmalloc.h>
#include <openssl/crypto.h>
@@ -56,6 +59,10 @@
#include <event.h>
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
+
void evdns_shutdown(int);
/********* PROTOTYPES **********/
@@ -71,6 +78,7 @@ static int connection_should_read_from_linked_conn(connection_t *conn);
/********* START VARIABLES **********/
+#ifndef USE_BUFFEREVENTS
int global_read_bucket; /**< Max number of bytes I can read this second. */
int global_write_bucket; /**< Max number of bytes I can write this second. */
@@ -78,13 +86,17 @@ int global_write_bucket; /**< Max number of bytes I can write this second. */
int global_relayed_read_bucket;
/** Max number of relayed (bandwidth class 1) bytes I can write this second. */
int global_relayed_write_bucket;
-
/** What was the read bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've read). */
static int stats_prev_global_read_bucket;
/** What was the write bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've written). */
static int stats_prev_global_write_bucket;
+#endif
+
+static uint64_t stats_prev_n_read = 0;
+static uint64_t stats_prev_n_written = 0;
+
/* XXX we might want to keep stats about global_relayed_*_bucket too. Or not.*/
/** How many bytes have we read since we started the process? */
static uint64_t stats_n_bytes_read = 0;
@@ -103,6 +115,8 @@ static time_t time_to_check_for_correct_dns = 0;
static time_t time_of_last_signewnym = 0;
/** Is there a signewnym request we're currently waiting to handle? */
static int signewnym_is_pending = 0;
+/** How many times have we called newnym? */
+static unsigned newnym_epoch = 0;
/** Smartlist of all open connections. */
static smartlist_t *connection_array = NULL;
@@ -141,6 +155,12 @@ int can_complete_circuit=0;
* they are obsolete? */
#define TLS_HANDSHAKE_TIMEOUT (60)
+/** Decides our behavior when no logs are configured/before any
+ * logs have been configured. For 0, we log notice to stdout as normal.
+ * For 1, we log warnings only. For 2, we log nothing.
+ */
+int quiet_level = 0;
+
/********* END VARIABLES ************/
/****************************************************************************
@@ -150,12 +170,58 @@ int can_complete_circuit=0;
*
****************************************************************************/
+#if 0 && defined(USE_BUFFEREVENTS)
+static void
+free_old_inbuf(connection_t *conn)
+{
+ if (! conn->inbuf)
+ return;
+
+ tor_assert(conn->outbuf);
+ tor_assert(buf_datalen(conn->inbuf) == 0);
+ tor_assert(buf_datalen(conn->outbuf) == 0);
+ buf_free(conn->inbuf);
+ buf_free(conn->outbuf);
+ conn->inbuf = conn->outbuf = NULL;
+
+ if (conn->read_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->read_event);
+ }
+ if (conn->write_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->write_event);
+ }
+ conn->read_event = conn->write_event = NULL;
+}
+#endif
+
+#ifdef MS_WINDOWS
+/** Remove the kernel-space send and receive buffers for <b>s</b>. For use
+ * with IOCP only. */
+static int
+set_buffer_lengths_to_zero(tor_socket_t s)
+{
+ int zero = 0;
+ int r = 0;
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&zero, sizeof(zero))) {
+ log_warn(LD_NET, "Unable to clear SO_SNDBUF");
+ r = -1;
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&zero, sizeof(zero))) {
+ log_warn(LD_NET, "Unable to clear SO_RCVBUF");
+ r = -1;
+ }
+ return r;
+}
+#endif
+
/** Add <b>conn</b> to the array of connections that we can poll on. The
* connection's socket must be set; the connection starts out
* non-reading and non-writing.
*/
int
-connection_add(connection_t *conn)
+connection_add_impl(connection_t *conn, int is_connecting)
{
tor_assert(conn);
tor_assert(SOCKET_OK(conn->s) ||
@@ -167,11 +233,71 @@ connection_add(connection_t *conn)
conn->conn_array_index = smartlist_len(connection_array);
smartlist_add(connection_array, conn);
- if (SOCKET_OK(conn->s) || conn->linked) {
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(conn)) {
+ if (SOCKET_OK(conn->s) && !conn->linked) {
+
+#ifdef MS_WINDOWS
+ if (tor_libevent_using_iocp_bufferevents() &&
+ get_options()->UserspaceIOCPBuffers) {
+ set_buffer_lengths_to_zero(conn->s);
+ }
+#endif
+
+ conn->bufev = bufferevent_socket_new(
+ tor_libevent_get_base(),
+ conn->s,
+ BEV_OPT_DEFER_CALLBACKS);
+ if (!conn->bufev) {
+ log_warn(LD_BUG, "Unable to create socket bufferevent");
+ smartlist_del(connection_array, conn->conn_array_index);
+ conn->conn_array_index = -1;
+ return -1;
+ }
+ if (is_connecting) {
+ /* Put the bufferevent into a "connecting" state so that we'll get
+ * a "connected" event callback on successful write. */
+ bufferevent_socket_connect(conn->bufev, NULL, 0);
+ }
+ connection_configure_bufferevent_callbacks(conn);
+ } else if (conn->linked && conn->linked_conn &&
+ connection_type_uses_bufferevent(conn->linked_conn)) {
+ tor_assert(!(SOCKET_OK(conn->s)));
+ if (!conn->bufev) {
+ struct bufferevent *pair[2] = { NULL, NULL };
+ if (bufferevent_pair_new(tor_libevent_get_base(),
+ BEV_OPT_DEFER_CALLBACKS,
+ pair) < 0) {
+ log_warn(LD_BUG, "Unable to create bufferevent pair");
+ smartlist_del(connection_array, conn->conn_array_index);
+ conn->conn_array_index = -1;
+ return -1;
+ }
+ tor_assert(pair[0]);
+ conn->bufev = pair[0];
+ conn->linked_conn->bufev = pair[1];
+ } /* else the other side already was added, and got a bufferevent_pair */
+ connection_configure_bufferevent_callbacks(conn);
+ } else {
+ tor_assert(!conn->linked);
+ }
+
+ if (conn->bufev)
+ tor_assert(conn->inbuf == NULL);
+
+ if (conn->linked_conn && conn->linked_conn->bufev)
+ tor_assert(conn->linked_conn->inbuf == NULL);
+ }
+#else
+ (void) is_connecting;
+#endif
+
+ if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) {
conn->read_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
conn->write_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
+ /* XXXX CHECK FOR NULL RETURN! */
}
log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
@@ -195,7 +321,13 @@ connection_unregister_events(connection_t *conn)
log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s);
tor_free(conn->write_event);
}
- if (conn->dns_server_port) {
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ bufferevent_free(conn->bufev);
+ conn->bufev = NULL;
+ }
+#endif
+ if (conn->type == CONN_TYPE_AP_DNS_LISTENER) {
dnsserv_close_listener(conn);
}
}
@@ -303,12 +435,37 @@ get_connection_array(void)
return connection_array;
}
+/** Provides the traffic read and written over the life of the process. */
+
+uint64_t
+get_bytes_read(void)
+{
+ return stats_n_bytes_read;
+}
+
+uint64_t
+get_bytes_written(void)
+{
+ return stats_n_bytes_written;
+}
+
/** Set the event mask on <b>conn</b> to <b>events</b>. (The event
* mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)
*/
void
connection_watch_events(connection_t *conn, watchable_events_t events)
{
+ IF_HAS_BUFFEREVENT(conn, {
+ short ev = ((short)events) & (EV_READ|EV_WRITE);
+ short old_ev = bufferevent_get_enabled(conn->bufev);
+ if ((ev & ~old_ev) != 0) {
+ bufferevent_enable(conn->bufev, ev);
+ }
+ if ((old_ev & ~ev) != 0) {
+ bufferevent_disable(conn->bufev, old_ev & ~ev);
+ }
+ return;
+ });
if (events & READ_EVENT)
connection_start_reading(conn);
else
@@ -326,6 +483,9 @@ connection_is_reading(connection_t *conn)
{
tor_assert(conn);
+ IF_HAS_BUFFEREVENT(conn,
+ return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
+ );
return conn->reading_from_linked_conn ||
(conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
}
@@ -335,6 +495,12 @@ void
connection_stop_reading(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_disable(conn->bufev, EV_READ);
+ return;
+ });
+
tor_assert(conn->read_event);
if (conn->linked) {
@@ -354,6 +520,12 @@ void
connection_start_reading(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_enable(conn->bufev, EV_READ);
+ return;
+ });
+
tor_assert(conn->read_event);
if (conn->linked) {
@@ -375,6 +547,10 @@ connection_is_writing(connection_t *conn)
{
tor_assert(conn);
+ IF_HAS_BUFFEREVENT(conn,
+ return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
+ );
+
return conn->writing_to_linked_conn ||
(conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
}
@@ -384,6 +560,12 @@ void
connection_stop_writing(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_disable(conn->bufev, EV_WRITE);
+ return;
+ });
+
tor_assert(conn->write_event);
if (conn->linked) {
@@ -404,6 +586,12 @@ void
connection_start_writing(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_enable(conn->bufev, EV_WRITE);
+ return;
+ });
+
tor_assert(conn->write_event);
if (conn->linked) {
@@ -590,9 +778,32 @@ conn_close_if_marked(int i)
assert_connection_ok(conn, now);
/* assert_all_pending_dns_resolves_ok(); */
- log_debug(LD_NET,"Cleaning up connection (fd %d).",(int)conn->s);
- if ((SOCKET_OK(conn->s) || conn->linked_conn)
- && connection_wants_to_flush(conn)) {
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ if (conn->hold_open_until_flushed &&
+ evbuffer_get_length(bufferevent_get_output(conn->bufev))) {
+ /* don't close yet. */
+ return 0;
+ }
+ if (conn->linked_conn && ! conn->linked_conn->marked_for_close) {
+ /* We need to do this explicitly so that the linked connection
+ * notices that there was an EOF. */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
+#endif
+
+ log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
+
+ /* If the connection we are about to close was trying to connect to
+ a proxy server and failed, the client won't be able to use that
+ proxy. We should warn the user about this. */
+ if (conn->proxy_state == PROXY_INFANT)
+ log_failed_proxy_connection(conn);
+
+ IF_HAS_BUFFEREVENT(conn, goto unlink);
+ if ((SOCKET_OK(conn->s) || conn->linked_conn) &&
+ connection_wants_to_flush(conn)) {
/* s == -1 means it's an incomplete edge connection, or that the socket
* has already been closed as unflushable. */
ssize_t sz = connection_bucket_write_limit(conn, now);
@@ -614,8 +825,8 @@ conn_close_if_marked(int i)
}
log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; "
"%d left; flushlen %d; wants-to-flush==%d", retval,
- (int)buf_datalen(conn->outbuf),
- (int)conn->outbuf_flushlen,
+ (int)connection_get_outbuf_len(conn),
+ (int)conn->outbuf_flushlen,
connection_wants_to_flush(conn));
} else if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) {
@@ -652,13 +863,17 @@ conn_close_if_marked(int i)
"something is wrong with your network connection, or "
"something is wrong with theirs. "
"(fd %d, type %s, state %d, marked at %s:%d).",
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
escaped_safe_str_client(conn->address),
(int)conn->s, conn_type_to_string(conn->type), conn->state,
conn->marked_for_close_file,
conn->marked_for_close);
}
}
+
+#ifdef USE_BUFFEREVENTS
+ unlink:
+#endif
connection_unlink(conn); /* unlink, remove, free */
return 1;
}
@@ -679,13 +894,13 @@ directory_all_unreachable(time_t now)
while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT))) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
log_notice(LD_NET,
"Is your network connection down? "
"Failing connection to '%s:%d'.",
- safe_str_client(edge_conn->socks_request->address),
- edge_conn->socks_request->port);
- connection_mark_unattached_ap(edge_conn,
+ safe_str_client(entry_conn->socks_request->address),
+ entry_conn->socks_request->port);
+ connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_NET_UNREACHABLE);
}
control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE");
@@ -696,18 +911,19 @@ directory_all_unreachable(time_t now)
void
directory_info_has_arrived(time_t now, int from_cache)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!router_have_minimum_dir_info()) {
int quiet = directory_too_idle_to_fetch_descriptors(options, now);
log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"I learned some more directory information, but not enough to "
"build a circuit: %s", get_dir_info_status_string());
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
return;
} else {
- if (directory_fetches_from_authorities(options))
- update_router_descriptor_downloads(now);
+ if (directory_fetches_from_authorities(options)) {
+ update_all_descriptor_downloads(now);
+ }
/* if we have enough dir info, then update our guard status with
* whatever we just learned. */
@@ -718,7 +934,7 @@ directory_info_has_arrived(time_t now, int from_cache)
update_extrainfo_downloads(now);
}
- if (server_mode(options) && !we_are_hibernating() && !from_cache &&
+ if (server_mode(options) && !net_is_disabled() && !from_cache &&
(can_complete_circuit || !any_predicted_circuits(now)))
consider_testing_reachability(1, 1);
}
@@ -740,12 +956,13 @@ run_connection_housekeeping(int i, time_t now)
{
cell_t cell;
connection_t *conn = smartlist_get(connection_array, i);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
or_connection_t *or_conn;
int past_keepalive =
now >= conn->timestamp_lastwritten + options->KeepalivePeriod;
- if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR)
+ if (conn->outbuf && !connection_get_outbuf_len(conn) &&
+ conn->type == CONN_TYPE_OR)
TO_OR_CONN(conn)->timestamp_lastempty = now;
if (conn->marked_for_close) {
@@ -765,7 +982,7 @@ run_connection_housekeeping(int i, time_t now)
/* This check is temporary; it's to let us know whether we should consider
* parsing partial serverdesc responses. */
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
- buf_datalen(conn->inbuf)>=1024) {
+ connection_get_inbuf_len(conn) >= 1024) {
log_info(LD_DIR,"Trying to extract information from wedged server desc "
"download.");
connection_dir_reached_eof(TO_DIR_CONN(conn));
@@ -782,7 +999,11 @@ run_connection_housekeeping(int i, time_t now)
the connection or send a keepalive, depending. */
or_conn = TO_OR_CONN(conn);
+#ifdef USE_BUFFEREVENTS
+ tor_assert(conn->bufev);
+#else
tor_assert(conn->outbuf);
+#endif
if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) {
/* It's bad for new circuits, and has no unmarked circuits on it:
@@ -794,8 +1015,7 @@ run_connection_housekeeping(int i, time_t now)
connection_or_connect_failed(TO_OR_CONN(conn),
END_OR_CONN_REASON_TIMEOUT,
"Tor gave up on the connection");
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ connection_mark_and_flush(conn);
} else if (!connection_state_is_open(conn)) {
if (past_keepalive) {
/* We never managed to actually get this connection open and happy. */
@@ -804,13 +1024,12 @@ run_connection_housekeeping(int i, time_t now)
connection_mark_for_close(conn);
}
} else if (we_are_hibernating() && !or_conn->n_circuits &&
- !buf_datalen(conn->outbuf)) {
+ !connection_get_outbuf_len(conn)) {
/* We're hibernating, there's no circuits, and nothing to flush.*/
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
(int)conn->s,conn->address, conn->port);
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ connection_mark_and_flush(conn);
} else if (!or_conn->n_circuits &&
now >= or_conn->timestamp_last_added_nonpadding +
IDLE_OR_CONN_TIMEOUT) {
@@ -818,7 +1037,6 @@ run_connection_housekeeping(int i, time_t now)
"[idle %d].", (int)conn->s,conn->address, conn->port,
(int)(now - or_conn->timestamp_last_added_nonpadding));
connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
} else if (
now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
@@ -826,10 +1044,10 @@ run_connection_housekeeping(int i, time_t now)
"Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
"flush; %d seconds since last write)",
(int)conn->s, conn->address, conn->port,
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
(int)(now-conn->timestamp_lastwritten));
connection_mark_for_close(conn);
- } else if (past_keepalive && !buf_datalen(conn->outbuf)) {
+ } else if (past_keepalive && !connection_get_outbuf_len(conn)) {
/* send a padding cell */
log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)",
conn->address, conn->port);
@@ -844,7 +1062,7 @@ run_connection_housekeeping(int i, time_t now)
static void
signewnym_impl(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!proxy_mode(options)) {
log_info(LD_CONTROL, "Ignoring SIGNAL NEWNYM because client functionality "
"is disabled.");
@@ -856,6 +1074,17 @@ signewnym_impl(time_t now)
rend_client_purge_state();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
+
+ ++newnym_epoch;
+
+ control_event_signal(SIGNEWNYM);
+}
+
+/** Return the number of times that signewnym has been called. */
+unsigned
+get_signewnym_epoch(void)
+{
+ return newnym_epoch;
}
/** Perform regular maintenance tasks. This function gets run once per
@@ -881,10 +1110,14 @@ run_scheduled_events(time_t now)
static time_t time_to_check_for_expired_networkstatus = 0;
static time_t time_to_write_stats_files = 0;
static time_t time_to_write_bridge_stats = 0;
+ static time_t time_to_check_port_forwarding = 0;
static time_t time_to_launch_reachability_tests = 0;
static int should_init_bridge_stats = 1;
static time_t time_to_retry_dns_init = 0;
- or_options_t *options = get_options();
+ static time_t time_to_next_heartbeat = 0;
+ static int has_validated_pt = 0;
+ const or_options_t *options = get_options();
+
int is_server = server_mode(options);
int i;
int have_dir_info;
@@ -895,6 +1128,16 @@ run_scheduled_events(time_t now)
*/
consider_hibernation(now);
+#if 0
+ {
+ static time_t nl_check_time = 0;
+ if (nl_check_time <= now) {
+ nodelist_assert_ok();
+ nl_check_time = now + 30;
+ }
+ }
+#endif
+
/* 0b. If we've deferred a signewnym, make sure it gets handled
* eventually. */
if (signewnym_is_pending &&
@@ -918,12 +1161,12 @@ run_scheduled_events(time_t now)
if (router_rebuild_descriptor(1)<0) {
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
}
- if (advertised_server_mode())
+ if (advertised_server_mode() & !options->DisableNetwork)
router_upload_dir_desc_to_dirservers(0);
}
- if (time_to_try_getting_descriptors < now) {
- update_router_descriptor_downloads(now);
+ if (!options->DisableNetwork && time_to_try_getting_descriptors < now) {
+ update_all_descriptor_downloads(now);
update_extrainfo_downloads(now);
if (router_have_minimum_dir_info())
time_to_try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL;
@@ -946,10 +1189,7 @@ run_scheduled_events(time_t now)
last_rotated_x509_certificate = now;
if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) {
log_info(LD_GENERAL,"Rotating tls context.");
- if (tor_tls_context_init(public_server_mode(options),
- get_tlsclient_identity_key(),
- is_server ? get_server_identity_key() : NULL,
- MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
+ if (router_initialize_tls_context() < 0) {
log_warn(LD_BUG, "Error reinitializing TLS context");
/* XXX is it a bug here, that we just keep going? -RD */
}
@@ -976,7 +1216,7 @@ run_scheduled_events(time_t now)
if (time_to_launch_reachability_tests < now &&
(authdir_mode_tests_reachability(options)) &&
- !we_are_hibernating()) {
+ !net_is_disabled()) {
time_to_launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL;
/* try to determine reachability of the other Tor relays */
dirserv_test_reachability(now);
@@ -1048,6 +1288,16 @@ run_scheduled_events(time_t now)
if (next_write && next_write < next_time_to_write_stats_files)
next_time_to_write_stats_files = next_write;
}
+ if (options->ConnDirectionStatistics) {
+ time_t next_write = rep_hist_conn_stats_write(time_to_write_stats_files);
+ if (next_write && next_write < next_time_to_write_stats_files)
+ next_time_to_write_stats_files = next_write;
+ }
+ if (options->BridgeAuthoritativeDir) {
+ time_t next_write = rep_hist_desc_stats_write(time_to_write_stats_files);
+ if (next_write && next_write < next_time_to_write_stats_files)
+ next_time_to_write_stats_files = next_write;
+ }
time_to_write_stats_files = next_time_to_write_stats_files;
}
@@ -1076,10 +1326,9 @@ run_scheduled_events(time_t now)
/* Remove old information from rephist and the rend cache. */
if (time_to_clean_caches < now) {
rep_history_clean(now - options->RephistTrackTime);
- rend_cache_clean();
- rend_cache_clean_v2_descs_as_dir();
- if (authdir_mode_v3(options))
- microdesc_cache_rebuild(NULL, 0);
+ rend_cache_clean(now);
+ rend_cache_clean_v2_descs_as_dir(now);
+ microdesc_cache_rebuild(NULL, 0);
#define CLEAN_CACHES_INTERVAL (30*60)
time_to_clean_caches = now + CLEAN_CACHES_INTERVAL;
}
@@ -1088,7 +1337,7 @@ run_scheduled_events(time_t now)
/* If we're a server and initializing dns failed, retry periodically. */
if (time_to_retry_dns_init < now) {
time_to_retry_dns_init = now + RETRY_DNS_INTERVAL;
- if (server_mode(options) && has_dns_init_failed())
+ if (is_server && has_dns_init_failed())
dns_init();
}
@@ -1103,7 +1352,7 @@ run_scheduled_events(time_t now)
/* 2b. Once per minute, regenerate and upload the descriptor if the old
* one is inaccurate. */
- if (time_to_check_descriptor < now) {
+ if (time_to_check_descriptor < now && !options->DisableNetwork) {
static int dirport_reachability_count = 0;
time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
check_descriptor_bandwidth_changed(now);
@@ -1111,15 +1360,11 @@ run_scheduled_events(time_t now)
time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL;
check_descriptor_ipaddress_changed(now);
}
-/** If our router descriptor ever goes this long without being regenerated
- * because something changed, we force an immediate regenerate-and-upload. */
-#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
- mark_my_descriptor_dirty_if_older_than(
- now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL);
+ mark_my_descriptor_dirty_if_too_old(now);
consider_publishable_server(0);
/* also, check religiously for reachability, if it's within the first
* 20 minutes of our uptime. */
- if (server_mode(options) &&
+ if (is_server &&
(can_complete_circuit || !any_predicted_circuits(now)) &&
!we_are_hibernating()) {
if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
@@ -1130,7 +1375,7 @@ run_scheduled_events(time_t now)
/* If we haven't checked for 12 hours and our bandwidth estimate is
* low, do another bandwidth test. This is especially important for
* bridges, since they might go long periods without much use. */
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (time_to_recheck_bandwidth && me &&
me->bandwidthcapacity < me->bandwidthrate &&
me->bandwidthcapacity < 51200) {
@@ -1182,7 +1427,7 @@ run_scheduled_events(time_t now)
connection_expire_held_open();
/** 3d. And every 60 seconds, we relaunch listeners if any died. */
- if (!we_are_hibernating() && time_to_check_listeners < now) {
+ if (!net_is_disabled() && time_to_check_listeners < now) {
retry_all_listeners(NULL, NULL);
time_to_check_listeners = now+60;
}
@@ -1193,7 +1438,7 @@ run_scheduled_events(time_t now)
* and we make a new circ if there are no clean circuits.
*/
have_dir_info = router_have_minimum_dir_info();
- if (have_dir_info && !we_are_hibernating())
+ if (have_dir_info && !net_is_disabled())
circuit_build_needed_circs(now);
/* every 10 seconds, but not at the same second as other such events */
@@ -1224,7 +1469,7 @@ run_scheduled_events(time_t now)
circuit_close_all_marked();
/** 7. And upload service descriptors if necessary. */
- if (can_complete_circuit && !we_are_hibernating()) {
+ if (can_complete_circuit && !net_is_disabled()) {
rend_consider_services_upload(now);
rend_consider_descriptor_republication();
}
@@ -1241,7 +1486,8 @@ run_scheduled_events(time_t now)
/** 9. and if we're a server, check whether our DNS is telling stories to
* us. */
- if (is_server && time_to_check_for_correct_dns < now) {
+ if (!net_is_disabled() &&
+ public_server_mode(options) && time_to_check_for_correct_dns < now) {
if (!time_to_check_for_correct_dns) {
time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120);
} else {
@@ -1251,13 +1497,45 @@ run_scheduled_events(time_t now)
}
}
- /** 10b. write bridge networkstatus file to disk */
+ /** 10. write bridge networkstatus file to disk */
if (options->BridgeAuthoritativeDir &&
time_to_write_bridge_status_file < now) {
networkstatus_dump_bridge_status_to_file(now);
#define BRIDGE_STATUSFILE_INTERVAL (30*60)
time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL;
}
+
+ /** 11. check the port forwarding app */
+ if (!net_is_disabled() &&
+ time_to_check_port_forwarding < now &&
+ options->PortForwarding &&
+ is_server) {
+#define PORT_FORWARDING_CHECK_INTERVAL 5
+ tor_check_port_forwarding(options->PortForwardingHelper,
+ options->DirPort,
+ options->ORPort,
+ now);
+ time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
+ }
+
+ /** 11b. check pending unconfigured managed proxies */
+ if (!net_is_disabled() && pt_proxies_configuration_pending())
+ pt_configure_remaining_proxies();
+
+ /** 11c. validate pluggable transports configuration if we need to */
+ if (!has_validated_pt &&
+ (options->Bridges || options->ClientTransportPlugin)) {
+ if (validate_pluggable_transports_config() == 0) {
+ has_validated_pt = 1;
+ }
+ }
+
+ /** 12. write the heartbeat message */
+ if (options->HeartbeatPeriod &&
+ time_to_next_heartbeat < now) {
+ log_heartbeat(now);
+ time_to_next_heartbeat = now+options->HeartbeatPeriod;
+ }
}
/** Timer: used to invoke second_elapsed_callback() once per second. */
@@ -1277,7 +1555,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
size_t bytes_written;
size_t bytes_read;
int seconds_elapsed;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
(void)timer;
(void)arg;
@@ -1288,30 +1566,39 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
update_approx_time(now);
/* the second has rolled over. check more stuff. */
- bytes_written = stats_prev_global_write_bucket - global_write_bucket;
- bytes_read = stats_prev_global_read_bucket - global_read_bucket;
seconds_elapsed = current_second ? (int)(now - current_second) : 0;
- stats_n_bytes_read += bytes_read;
- stats_n_bytes_written += bytes_written;
- if (accounting_is_enabled(options) && seconds_elapsed >= 0)
- accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed);
+#ifdef USE_BUFFEREVENTS
+ {
+ uint64_t cur_read,cur_written;
+ connection_get_rate_limit_totals(&cur_read, &cur_written);
+ bytes_written = (size_t)(cur_written - stats_prev_n_written);
+ bytes_read = (size_t)(cur_read - stats_prev_n_read);
+ stats_n_bytes_read += bytes_read;
+ stats_n_bytes_written += bytes_written;
+ if (accounting_is_enabled(options) && seconds_elapsed >= 0)
+ accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed);
+ stats_prev_n_written = cur_written;
+ stats_prev_n_read = cur_read;
+ }
+#else
+ bytes_read = (size_t)(stats_n_bytes_read - stats_prev_n_read);
+ bytes_written = (size_t)(stats_n_bytes_written - stats_prev_n_written);
+ stats_prev_n_read = stats_n_bytes_read;
+ stats_prev_n_written = stats_n_bytes_written;
+#endif
+
control_event_bandwidth_used((uint32_t)bytes_read,(uint32_t)bytes_written);
control_event_stream_bandwidth_used();
- if (seconds_elapsed > 0)
- connection_bucket_refill(seconds_elapsed, now);
- stats_prev_global_read_bucket = global_read_bucket;
- stats_prev_global_write_bucket = global_write_bucket;
-
if (server_mode(options) &&
- !we_are_hibernating() &&
+ !net_is_disabled() &&
seconds_elapsed > 0 &&
can_complete_circuit &&
stats_n_seconds_working / TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT !=
(stats_n_seconds_working+seconds_elapsed) /
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
/* every 20 minutes, check and complain if necessary */
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me && !check_whether_orport_reachable()) {
log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
"its ORPort is reachable. Please check your firewalls, ports, "
@@ -1350,6 +1637,57 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
current_second = now; /* remember which second it is, for next time */
}
+#ifndef USE_BUFFEREVENTS
+/** Timer: used to invoke refill_callback(). */
+static periodic_timer_t *refill_timer = NULL;
+
+/** Libevent callback: invoked periodically to refill token buckets
+ * and count r/w bytes. It is only used when bufferevents are disabled. */
+static void
+refill_callback(periodic_timer_t *timer, void *arg)
+{
+ static struct timeval current_millisecond;
+ struct timeval now;
+
+ size_t bytes_written;
+ size_t bytes_read;
+ int milliseconds_elapsed = 0;
+ int seconds_rolled_over = 0;
+
+ const or_options_t *options = get_options();
+
+ (void)timer;
+ (void)arg;
+
+ tor_gettimeofday(&now);
+
+ /* If this is our first time, no time has passed. */
+ if (current_millisecond.tv_sec) {
+ long mdiff = tv_mdiff(&current_millisecond, &now);
+ if (mdiff > INT_MAX)
+ mdiff = INT_MAX;
+ milliseconds_elapsed = (int)mdiff;
+ seconds_rolled_over = (int)(now.tv_sec - current_millisecond.tv_sec);
+ }
+
+ bytes_written = stats_prev_global_write_bucket - global_write_bucket;
+ bytes_read = stats_prev_global_read_bucket - global_read_bucket;
+
+ stats_n_bytes_read += bytes_read;
+ stats_n_bytes_written += bytes_written;
+ if (accounting_is_enabled(options) && milliseconds_elapsed >= 0)
+ accounting_add_bytes(bytes_read, bytes_written, seconds_rolled_over);
+
+ if (milliseconds_elapsed > 0)
+ connection_bucket_refill(milliseconds_elapsed, now.tv_sec);
+
+ stats_prev_global_read_bucket = global_read_bucket;
+ stats_prev_global_write_bucket = global_write_bucket;
+
+ current_millisecond = now; /* remember what time it is, for next time */
+}
+#endif
+
#ifndef MS_WINDOWS
/** Called when a possibly ignorable libevent error occurs; ensures that we
* don't get into an infinite loop by ignoring too many errors from
@@ -1378,7 +1716,8 @@ ip_address_changed(int at_interface)
if (at_interface) {
if (! server) {
/* Okay, change our keys. */
- init_keys();
+ if (init_keys()<0)
+ log_warn(LD_GENERAL, "Unable to rotate keys after IP change!");
}
} else {
if (server) {
@@ -1409,7 +1748,7 @@ dns_servers_relaunch_checks(void)
static int
do_hup(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
#ifdef USE_DMALLOC
dmalloc_log_stats();
@@ -1453,7 +1792,8 @@ do_hup(void)
/* retry appropriate downloads */
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
- update_networkstatus_downloads(time(NULL));
+ if (!options->DisableNetwork)
+ update_networkstatus_downloads(time(NULL));
/* We'll retry routerstatus downloads in about 10 seconds; no need to
* force a retry there. */
@@ -1501,8 +1841,10 @@ do_main_loop(void)
/* Set up our buckets */
connection_bucket_init();
+#ifndef USE_BUFFEREVENTS
stats_prev_global_read_bucket = global_read_bucket;
stats_prev_global_write_bucket = global_write_bucket;
+#endif
/* initialize the bootstrap status events to know we're starting up */
control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
@@ -1545,6 +1887,22 @@ do_main_loop(void)
tor_assert(second_timer);
}
+#ifndef USE_BUFFEREVENTS
+ if (!refill_timer) {
+ struct timeval refill_interval;
+ int msecs = get_options()->TokenBucketRefillInterval;
+
+ refill_interval.tv_sec = msecs/1000;
+ refill_interval.tv_usec = (msecs%1000)*1000;
+
+ refill_timer = periodic_timer_new(tor_libevent_get_base(),
+ &refill_interval,
+ refill_callback,
+ NULL);
+ tor_assert(refill_timer);
+ }
+#endif
+
for (;;) {
if (nt_service_is_stopping())
return 0;
@@ -1633,11 +1991,13 @@ process_signal(uintptr_t sig)
case SIGUSR1:
/* prefer to log it at INFO, but make sure we always see it */
dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO);
+ control_event_signal(sig);
break;
case SIGUSR2:
switch_logs_debug();
log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. "
"Send HUP to change back.");
+ control_event_signal(sig);
break;
case SIGHUP:
if (do_hup() < 0) {
@@ -1645,6 +2005,7 @@ process_signal(uintptr_t sig)
tor_cleanup();
exit(1);
}
+ control_event_signal(sig);
break;
#ifdef SIGCHLD
case SIGCHLD:
@@ -1666,10 +2027,18 @@ process_signal(uintptr_t sig)
}
case SIGCLEARDNSCACHE:
addressmap_clear_transient();
+ control_event_signal(sig);
break;
}
}
+/** Returns Tor's uptime. */
+long
+get_uptime(void)
+{
+ return stats_n_seconds_working;
+}
+
extern uint64_t rephist_total_alloc;
extern uint32_t rephist_total_num;
@@ -1716,13 +2085,13 @@ dumpstats(int severity)
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
i,
- (int)buf_datalen(conn->inbuf),
+ (int)connection_get_inbuf_len(conn),
(int)buf_allocation(conn->inbuf),
(int)(now - conn->timestamp_lastread));
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on outbuf "
"(len %d, last written %d secs ago)",i,
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
(int)buf_allocation(conn->outbuf),
(int)(now - conn->timestamp_lastwritten));
if (conn->type == CONN_TYPE_OR) {
@@ -1894,10 +2263,26 @@ tor_init(int argc, char *argv[])
default:
add_temp_log(LOG_NOTICE);
}
+ quiet_level = quiet;
+
+ {
+ const char *version = get_version();
+ log_notice(LD_GENERAL, "Tor v%s%s running on %s.", version,
+#ifdef USE_BUFFEREVENTS
+ " (with bufferevents)",
+#else
+ "",
+#endif
+ get_uname());
- log(LOG_NOTICE, LD_GENERAL, "Tor v%s. This is experimental software. "
- "Do not rely on it for strong anonymity. (Running on %s)",get_version(),
- get_uname());
+ log_notice(LD_GENERAL, "WARNING: Tor can't help you if you use it wrong. "
+ "Learn how to be safe at "
+ "https://www.torproject.org/download/download#warning");
+
+ if (strstr(version, "alpha") || strstr(version, "beta"))
+ log_notice(LD_GENERAL, "This version is not a stable Tor release. "
+ "Expect more bugs than usual.");
+ }
if (network_init()<0) {
log_err(LD_BUG,"Error initializing network; exiting.");
@@ -1937,7 +2322,7 @@ static tor_lockfile_t *lockfile = NULL;
* return -1 if we can't get the lockfile. Return 0 on success.
*/
int
-try_locking(or_options_t *options, int err_if_locked)
+try_locking(const or_options_t *options, int err_if_locked)
{
if (lockfile)
return 0;
@@ -2016,9 +2401,11 @@ tor_free_all(int postfork)
clear_pending_onions();
circuit_free_all();
entry_guards_free_all();
+ pt_free_all();
connection_free_all();
buf_shrink_freelists(1);
memarea_clear_freelist();
+ nodelist_free_all();
microdesc_free_all();
if (!postfork) {
config_free_all();
@@ -2050,7 +2437,7 @@ tor_free_all(int postfork)
void
tor_cleanup(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->command == CMD_RUN_TOR) {
time_t now = time(NULL);
/* Remove our pid file. We don't care if there was an error when we
diff --git a/src/or/main.h b/src/or/main.h
index 0551f7aaf9..c8903642de 100644
--- a/src/or/main.h
+++ b/src/or/main.h
@@ -14,7 +14,9 @@
extern int can_complete_circuit;
-int connection_add(connection_t *conn);
+int connection_add_impl(connection_t *conn, int is_connecting);
+#define connection_add(conn) connection_add_impl((conn), 0)
+#define connection_add_connecting(conn) connection_add_impl((conn), 1)
int connection_remove(connection_t *conn);
void connection_unregister_events(connection_t *conn);
int connection_in_array(connection_t *conn);
@@ -22,10 +24,13 @@ void add_connection_to_closeable_list(connection_t *conn);
int connection_is_on_closeable_list(connection_t *conn);
smartlist_t *get_connection_array(void);
+uint64_t get_bytes_read(void);
+uint64_t get_bytes_written(void);
/** Bitmask for events that we can turn on and off with
* connection_watch_events. */
typedef enum watchable_events {
+ /* Yes, it is intentional that these match Libevent's EV_READ and EV_WRITE */
READ_EVENT=0x02, /**< We want to know when a connection is readable */
WRITE_EVENT=0x04 /**< We want to know when a connection is writable */
} watchable_events_t;
@@ -46,10 +51,13 @@ void directory_info_has_arrived(time_t now, int from_cache);
void ip_address_changed(int at_interface);
void dns_servers_relaunch_checks(void);
+long get_uptime(void);
+unsigned get_signewnym_epoch(void);
+
void handle_signals(int is_parent);
void process_signal(uintptr_t sig);
-int try_locking(or_options_t *options, int err_if_locked);
+int try_locking(const or_options_t *options, int err_if_locked);
int have_lockfile(void);
void release_lockfile(void);
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 7c67d51448..92f5c03585 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -3,7 +3,14 @@
#include "or.h"
#include "config.h"
+#include "directory.h"
+#include "dirserv.h"
#include "microdesc.h"
+#include "networkstatus.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
#include "routerparse.h"
/** A data structure to hold a bunch of cached microdescriptors. There are
@@ -121,15 +128,19 @@ get_microdesc_cache(void)
* ending at <b>eos</b>, and store them in <b>cache</b>. If <b>no-save</b>,
* mark them as non-writable to disk. If <b>where</b> is SAVED_IN_CACHE,
* leave their bodies as pointers to the mmap'd cache. If where is
- * <b>SAVED_NOWHERE</b>, do not allow annotations. Return a list of the added
- * microdescriptors. */
+ * <b>SAVED_NOWHERE</b>, do not allow annotations. If listed_at is positive,
+ * set the last_listed field of every microdesc to listed_at. If
+ * requested_digests is non-null, then it contains a list of digests we mean
+ * to allow, so we should reject any non-requested microdesc with a different
+ * digest, and alter the list to contain only the digests of those microdescs
+ * we didn't find.
+ * Return a newly allocated list of the added microdescriptors, or NULL */
smartlist_t *
microdescs_add_to_cache(microdesc_cache_t *cache,
const char *s, const char *eos, saved_location_t where,
- int no_save)
+ int no_save, time_t listed_at,
+ smartlist_t *requested_digests256)
{
- /*XXXX need an argument that sets last_listed as appropriate. */
-
smartlist_t *descriptors, *added;
const int allow_annotations = (where != SAVED_NOWHERE);
const int copy_body = (where != SAVED_IN_CACHE);
@@ -137,6 +148,33 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
descriptors = microdescs_parse_from_string(s, eos,
allow_annotations,
copy_body);
+ if (listed_at > 0) {
+ SMARTLIST_FOREACH(descriptors, microdesc_t *, md,
+ md->last_listed = listed_at);
+ }
+ if (requested_digests256) {
+ digestmap_t *requested; /* XXXX actuqlly we should just use a
+ digest256map */
+ requested = digestmap_new();
+ SMARTLIST_FOREACH(requested_digests256, const char *, cp,
+ digestmap_set(requested, cp, (void*)1));
+ SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) {
+ if (digestmap_get(requested, md->digest)) {
+ digestmap_set(requested, md->digest, (void*)2);
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microcdesc");
+ microdesc_free(md);
+ SMARTLIST_DEL_CURRENT(descriptors, md);
+ }
+ } SMARTLIST_FOREACH_END(md);
+ SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) {
+ if (digestmap_get(requested, cp) == (void*)2) {
+ tor_free(cp);
+ SMARTLIST_DEL_CURRENT(requested_digests256, cp);
+ }
+ } SMARTLIST_FOREACH_END(cp);
+ digestmap_free(requested, NULL);
+ }
added = microdescs_add_list_to_cache(cache, descriptors, where, no_save);
smartlist_free(descriptors);
@@ -144,7 +182,7 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
}
/* As microdescs_add_to_cache, but takes a list of micrdescriptors instead of
- * a string to encode. Frees any members of <b>descriptors</b> that it does
+ * a string to decode. Frees any members of <b>descriptors</b> that it does
* not add. */
smartlist_t *
microdescs_add_list_to_cache(microdesc_cache_t *cache,
@@ -200,6 +238,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
md->no_save = no_save;
HT_INSERT(microdesc_map, &cache->map, md);
+ md->held_in_map = 1;
smartlist_add(added, md);
++cache->n_seen;
cache->total_len_seen += md->bodylen;
@@ -208,6 +247,15 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
if (f)
finish_writing_to_file(open_file); /*XXX Check me.*/
+ {
+ networkstatus_t *ns = networkstatus_get_latest_consensus();
+ if (ns && ns->flavor == FLAV_MICRODESC)
+ SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md));
+ }
+
+ if (smartlist_len(added))
+ router_dir_info_changed();
+
return added;
}
@@ -219,6 +267,7 @@ microdesc_cache_clear(microdesc_cache_t *cache)
for (entry = HT_START(microdesc_map, &cache->map); entry; entry = next) {
microdesc_t *md = *entry;
next = HT_NEXT_RMV(microdesc_map, &cache->map, entry);
+ md->held_in_map = 0;
microdesc_free(md);
}
HT_CLEAR(microdesc_map, &cache->map);
@@ -247,7 +296,7 @@ microdesc_cache_reload(microdesc_cache_t *cache)
mm = cache->cache_content = tor_mmap_file(cache->cache_fname);
if (mm) {
added = microdescs_add_to_cache(cache, mm->data, mm->data+mm->size,
- SAVED_IN_CACHE, 0);
+ SAVED_IN_CACHE, 0, -1, NULL);
if (added) {
total += smartlist_len(added);
smartlist_free(added);
@@ -260,7 +309,7 @@ microdesc_cache_reload(microdesc_cache_t *cache)
cache->journal_len = (size_t) st.st_size;
added = microdescs_add_to_cache(cache, journal_content,
journal_content+st.st_size,
- SAVED_IN_JOURNAL, 0);
+ SAVED_IN_JOURNAL, 0, -1, NULL);
if (added) {
total += smartlist_len(added);
smartlist_free(added);
@@ -293,9 +342,11 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
size_t bytes_dropped = 0;
time_t now = time(NULL);
- (void) force;
- /* In 0.2.2, we let this proceed unconditionally: only authorities have
- * microdesc caches. */
+ /* If we don't know a live consensus, don't believe last_listed values: we
+ * might be starting up after being down for a while. */
+ if (! force &&
+ ! networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC))
+ return;
if (cutoff <= 0)
cutoff = now - TOLERATE_MICRODESC_AGE;
@@ -305,6 +356,7 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
++dropped;
victim = *mdp;
mdp = HT_NEXT_RMV(microdesc_map, &cache->map, mdp);
+ victim->held_in_map = 0;
bytes_dropped += victim->bodylen;
microdesc_free(victim);
} else {
@@ -390,6 +442,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
/* log? return -1? die? coredump the universe? */
continue;
}
+ tor_assert(((size_t)size) == annotation_len + md->bodylen);
md->off = off + annotation_len;
off += size;
if (md->saved_location != SAVED_IN_CACHE) {
@@ -415,7 +468,21 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) {
tor_assert(md->saved_location == SAVED_IN_CACHE);
md->body = (char*)cache->cache_content->data + md->off;
- tor_assert(fast_memeq(md->body, "onion-key", 9));
+ if (PREDICT_UNLIKELY(
+ md->bodylen < 9 || fast_memneq(md->body, "onion-key", 9) != 0)) {
+ /* XXXX023 once bug 2022 is solved, we can kill this block and turn it
+ * into just the tor_assert(!memcmp) */
+ off_t avail = cache->cache_content->size - md->off;
+ char *bad_str;
+ tor_assert(avail >= 0);
+ bad_str = tor_strndup(md->body, MIN(128, (size_t)avail));
+ log_err(LD_BUG, "After rebuilding microdesc cache, offsets seem wrong. "
+ " At offset %d, I expected to find a microdescriptor starting "
+ " with \"onion-key\". Instead I got %s.",
+ (int)md->off, escaped(bad_str));
+ tor_free(bad_str);
+ tor_assert(fast_memeq(md->body, "onion-key", 9));
+ }
} SMARTLIST_FOREACH_END(md);
smartlist_free(wrote);
@@ -432,6 +499,28 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
return 0;
}
+/** Make sure that the reference count of every microdescriptor in cache is
+ * accurate. */
+void
+microdesc_check_counts(void)
+{
+ microdesc_t **mdp;
+ if (!the_microdesc_cache)
+ return;
+
+ HT_FOREACH(mdp, microdesc_map, &the_microdesc_cache->map) {
+ microdesc_t *md = *mdp;
+ unsigned int found=0;
+ const smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node, {
+ if (node->md == md) {
+ ++found;
+ }
+ });
+ tor_assert(found == md->held_by_nodes);
+ }
+}
+
/** Deallocate a single microdescriptor. Note: the microdescriptor MUST have
* previously been removed from the cache if it had ever been inserted. */
void
@@ -439,7 +528,43 @@ microdesc_free(microdesc_t *md)
{
if (!md)
return;
- /* Must be removed from hash table! */
+
+ /* Make sure that the microdesc was really removed from the appropriate data
+ structures. */
+ if (md->held_in_map) {
+ microdesc_cache_t *cache = get_microdesc_cache();
+ microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md);
+ if (md2 == md) {
+ log_warn(LD_BUG, "microdesc_free() called, but md was still in "
+ "microdesc_map");
+ HT_REMOVE(microdesc_map, &cache->map, md);
+ } else {
+ log_warn(LD_BUG, "microdesc_free() called with held_in_map set, but "
+ "microdesc was not in the map.");
+ }
+ tor_fragile_assert();
+ }
+ if (md->held_by_nodes) {
+ int found=0;
+ const smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node, {
+ if (node->md == md) {
+ ++found;
+ node->md = NULL;
+ }
+ });
+ if (found) {
+ log_warn(LD_BUG, "microdesc_free() called, but md was still referenced "
+ "%d node(s); held_by_nodes == %u", found, md->held_by_nodes);
+ } else {
+ log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set to %u, "
+ "but md was not referenced by any nodes", md->held_by_nodes);
+ }
+ tor_fragile_assert();
+ }
+ //tor_assert(md->held_in_map == 0);
+ //tor_assert(md->held_by_nodes == 0);
+
if (md->onion_pkey)
crypto_free_pk_env(md->onion_pkey);
if (md->body && md->saved_location != SAVED_IN_CACHE)
@@ -449,7 +574,7 @@ microdesc_free(microdesc_t *md)
SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp));
smartlist_free(md->family);
}
- tor_free(md->exitsummary);
+ short_policy_free(md->exit_policy);
tor_free(md);
}
@@ -491,3 +616,147 @@ microdesc_average_size(microdesc_cache_t *cache)
return (size_t)(cache->total_len_seen / cache->n_seen);
}
+/** Return a smartlist of all the sha256 digest of the microdescriptors that
+ * are listed in <b>ns</b> but not present in <b>cache</b>. Returns pointers
+ * to internals of <b>ns</b>; you should not free the members of the resulting
+ * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */
+smartlist_t *
+microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache,
+ int downloadable_only, digestmap_t *skip)
+{
+ smartlist_t *result = smartlist_create();
+ time_t now = time(NULL);
+ tor_assert(ns->flavor == FLAV_MICRODESC);
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ if (microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest))
+ continue;
+ if (downloadable_only &&
+ !download_status_is_ready(&rs->dl_status, now,
+ MAX_MICRODESC_DOWNLOAD_FAILURES))
+ continue;
+ if (skip && digestmap_get(skip, rs->descriptor_digest))
+ continue;
+ if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN))
+ continue; /* This indicates a bug somewhere XXXX023*/
+ /* XXXX Also skip if we're a noncache and wouldn't use this router.
+ * XXXX NM Microdesc
+ */
+ smartlist_add(result, rs->descriptor_digest);
+ } SMARTLIST_FOREACH_END(rs);
+ return result;
+}
+
+/** Launch download requests for mircodescriptors as appropriate.
+ *
+ * Specifically, we should launch download requests if we are configured to
+ * download mirodescriptors, and there are some microdescriptors listed the
+ * current microdesc consensus that we don't have, and either we never asked
+ * for them, or we failed to download them but we're willing to retry.
+ */
+void
+update_microdesc_downloads(time_t now)
+{
+ const or_options_t *options = get_options();
+ networkstatus_t *consensus;
+ smartlist_t *missing;
+ digestmap_t *pending;
+
+ if (should_delay_dir_fetches(options))
+ return;
+ if (directory_too_idle_to_fetch_descriptors(options, now))
+ return;
+
+ consensus = networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
+ if (!consensus)
+ return;
+
+ if (!we_fetch_microdescriptors(options))
+ return;
+
+ pending = digestmap_new();
+ list_pending_microdesc_downloads(pending);
+
+ missing = microdesc_list_missing_digest256(consensus,
+ get_microdesc_cache(),
+ 1,
+ pending);
+ digestmap_free(pending, NULL);
+
+ launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC,
+ missing, NULL, now);
+
+ smartlist_free(missing);
+}
+
+/** For every microdescriptor listed in the current microdecriptor consensus,
+ * update its last_listed field to be at least as recent as the publication
+ * time of the current microdescriptor consensus.
+ */
+void
+update_microdescs_from_networkstatus(time_t now)
+{
+ microdesc_cache_t *cache = get_microdesc_cache();
+ microdesc_t *md;
+ networkstatus_t *ns =
+ networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
+
+ if (! ns)
+ return;
+
+ tor_assert(ns->flavor == FLAV_MICRODESC);
+
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ md = microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest);
+ if (md && ns->valid_after > md->last_listed)
+ md->last_listed = ns->valid_after;
+ } SMARTLIST_FOREACH_END(rs);
+}
+
+/** Return true iff we should prefer to use microdescriptors rather than
+ * routerdescs for building circuits. */
+int
+we_use_microdescriptors_for_circuits(const or_options_t *options)
+{
+ int ret = options->UseMicrodescriptors;
+ if (ret == -1) {
+ /* UseMicrodescriptors is "auto"; we need to decide: */
+ /* So we decide that we'll use microdescriptors iff we are not a server,
+ * and we're not autofetching everything. */
+ ret = !server_mode(options) && !options->FetchUselessDescriptors;
+ }
+ return ret;
+}
+
+/** Return true iff we should try to download microdescriptors at all. */
+int
+we_fetch_microdescriptors(const or_options_t *options)
+{
+ if (directory_caches_dir_info(options))
+ return 1;
+ if (options->FetchUselessDescriptors)
+ return 1;
+ return we_use_microdescriptors_for_circuits(options);
+}
+
+/** Return true iff we should try to download router descriptors at all. */
+int
+we_fetch_router_descriptors(const or_options_t *options)
+{
+ if (directory_caches_dir_info(options))
+ return 1;
+ if (options->FetchUselessDescriptors)
+ return 1;
+ return ! we_use_microdescriptors_for_circuits(options);
+}
+
+/** Return the consensus flavor we actually want to use to build circuits. */
+int
+usable_consensus_flavor(void)
+{
+ if (we_use_microdescriptors_for_circuits(get_options())) {
+ return FLAV_MICRODESC;
+ } else {
+ return FLAV_NS;
+ }
+}
+
diff --git a/src/or/microdesc.h b/src/or/microdesc.h
index 77ce8536bc..4564132810 100644
--- a/src/or/microdesc.h
+++ b/src/or/microdesc.h
@@ -14,9 +14,12 @@
microdesc_cache_t *get_microdesc_cache(void);
+void microdesc_check_counts(void);
+
smartlist_t *microdescs_add_to_cache(microdesc_cache_t *cache,
const char *s, const char *eos, saved_location_t where,
- int no_save);
+ int no_save, time_t listed_at,
+ smartlist_t *requested_digests256);
smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache,
smartlist_t *descriptors, saved_location_t where,
int no_save);
@@ -31,8 +34,21 @@ microdesc_t *microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache,
size_t microdesc_average_size(microdesc_cache_t *cache);
+smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns,
+ microdesc_cache_t *cache,
+ int downloadable_only,
+ digestmap_t *skip);
+
void microdesc_free(microdesc_t *md);
void microdesc_free_all(void);
+void update_microdesc_downloads(time_t now);
+void update_microdescs_from_networkstatus(time_t now);
+
+int usable_consensus_flavor(void);
+int we_fetch_microdescriptors(const or_options_t *options);
+int we_fetch_router_descriptors(const or_options_t *options);
+int we_use_microdescriptors_for_circuits(const or_options_t *options);
+
#endif
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index b0ef74b02e..7cd9d02c3f 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -20,7 +20,9 @@
#include "dirserv.h"
#include "dirvote.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "relay.h"
#include "router.h"
#include "routerlist.h"
@@ -44,8 +46,21 @@ static strmap_t *named_server_map = NULL;
* as unnamed for some server in the consensus. */
static strmap_t *unnamed_server_map = NULL;
-/** Most recently received and validated v3 consensus network status. */
-static networkstatus_t *current_consensus = NULL;
+/** Most recently received and validated v3 consensus network status,
+ * of whichever type we are using for our own circuits. This will be the same
+ * as one of current_ns_consensus or current_md_consensus.
+ */
+#define current_consensus \
+ (we_use_microdescriptors_for_circuits(get_options()) ? \
+ current_md_consensus : current_ns_consensus)
+
+/** Most recently received and validated v3 "ns"-flavored consensus network
+ * status. */
+static networkstatus_t *current_ns_consensus = NULL;
+
+/** Most recently received and validated v3 "microdec"-flavored consensus
+ * network status. */
+static networkstatus_t *current_md_consensus = NULL;
/** A v3 consensus networkstatus that we've received, but which we don't
* have enough certificates to be happy about. */
@@ -94,9 +109,8 @@ void
networkstatus_reset_warnings(void)
{
if (current_consensus) {
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
- rs->name_lookup_warned = 0);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ node->name_lookup_warned = 0);
}
have_warned_about_old_version = 0;
@@ -199,7 +213,7 @@ router_reload_consensus_networkstatus(void)
char *filename;
char *s;
struct stat st;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS;
int flav;
@@ -271,6 +285,7 @@ router_reload_consensus_networkstatus(void)
update_certificate_downloads(time(NULL));
routers_update_all_from_networkstatus(time(NULL), 3);
+ update_microdescs_from_networkstatus(time(NULL));
return 0;
}
@@ -469,7 +484,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
int n_bad = 0;
int n_unknown = 0;
int n_no_signature = 0;
- int n_v3_authorities = get_n_authorities(V3_AUTHORITY);
+ int n_v3_authorities = get_n_authorities(V3_DIRINFO);
int n_required = n_v3_authorities/2 + 1;
smartlist_t *need_certs_from = smartlist_create();
smartlist_t *unrecognized = smartlist_create();
@@ -540,7 +555,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest))
smartlist_add(missing_authorities, ds);
});
@@ -723,7 +738,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at,
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest)) ||
- !(trusted_dir->type & V2_AUTHORITY)) {
+ !(trusted_dir->type & V2_DIRINFO)) {
log_info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize.");
source_desc = fp;
@@ -927,10 +942,9 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member)
return tor_memcmp(key, rs->identity_digest, DIGEST_LEN);
}
-/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
- * NULL if none was found. */
+/** As networkstatus_v2_find_entry, but do not return a const pointer */
routerstatus_t *
-networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
+networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest)
{
return smartlist_bsearch(ns->entries, digest,
compare_digest_to_routerstatus_entry);
@@ -938,14 +952,29 @@ networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
* NULL if none was found. */
+const routerstatus_t *
+networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
+{
+ return networkstatus_v2_find_mutable_entry(ns, digest);
+}
+
+/** As networkstatus_find_entry, but do not return a const pointer */
routerstatus_t *
-networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
+networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest)
{
return smartlist_bsearch(ns->routerstatus_list, digest,
compare_digest_to_routerstatus_entry);
}
-/*XXXX make this static once functions are moved into this file. */
+/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
+ * NULL if none was found. */
+const routerstatus_t *
+networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
+{
+ return networkstatus_vote_find_mutable_entry(ns, digest);
+}
+
+/*XXXX MOVE make this static once functions are moved into this file. */
/** Search the routerstatuses in <b>ns</b> for one whose identity digest is
* <b>digest</b>. Return value and set *<b>found_out</b> as for
* smartlist_bsearch_idx(). */
@@ -967,22 +996,37 @@ networkstatus_get_v2_list(void)
return networkstatus_v2_list;
}
-/** Return the consensus view of the status of the router whose current
- * <i>descriptor</i> digest is <b>digest</b>, or NULL if no such router is
- * known. */
+/* As router_get_consensus_status_by_descriptor_digest, but does not return
+ * a const pointer */
routerstatus_t *
-router_get_consensus_status_by_descriptor_digest(const char *digest)
+router_get_mutable_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest)
{
- if (!current_consensus) return NULL;
- if (!current_consensus->desc_digest_map) {
- digestmap_t * m = current_consensus->desc_digest_map = digestmap_new();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
+ if (!consensus)
+ consensus = current_consensus;
+ if (!consensus)
+ return NULL;
+ if (!consensus->desc_digest_map) {
+ digestmap_t *m = consensus->desc_digest_map = digestmap_new();
+ SMARTLIST_FOREACH(consensus->routerstatus_list,
routerstatus_t *, rs,
{
digestmap_set(m, rs->descriptor_digest, rs);
});
}
- return digestmap_get(current_consensus->desc_digest_map, digest);
+ return digestmap_get(consensus->desc_digest_map, digest);
+}
+
+/** Return the consensus view of the status of the router whose current
+ * <i>descriptor</i> digest in <b>consensus</b> is <b>digest</b>, or NULL if
+ * no such router is known. */
+const routerstatus_t *
+router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
+ const char *digest)
+{
+ return router_get_mutable_consensus_status_by_descriptor_digest(
+ consensus, digest);
}
/** Given the digest of a router descriptor, return its current download
@@ -991,7 +1035,10 @@ download_status_t *
router_get_dl_status_by_descriptor_digest(const char *d)
{
routerstatus_t *rs;
- if ((rs = router_get_consensus_status_by_descriptor_digest(d)))
+ if (!current_ns_consensus)
+ return NULL;
+ if ((rs = router_get_mutable_consensus_status_by_descriptor_digest(
+ current_ns_consensus, d)))
return &rs->dl_status;
if (v2_download_status_map)
return digestmap_get(v2_download_status_map, d);
@@ -999,10 +1046,9 @@ router_get_dl_status_by_descriptor_digest(const char *d)
return NULL;
}
-/** Return the consensus view of the status of the router whose identity
- * digest is <b>digest</b>, or NULL if we don't know about any such router. */
+/** As router_get_consensus_status_by_id, but do not return a const pointer */
routerstatus_t *
-router_get_consensus_status_by_id(const char *digest)
+router_get_mutable_consensus_status_by_id(const char *digest)
{
if (!current_consensus)
return NULL;
@@ -1010,100 +1056,27 @@ router_get_consensus_status_by_id(const char *digest)
compare_digest_to_routerstatus_entry);
}
+/** Return the consensus view of the status of the router whose identity
+ * digest is <b>digest</b>, or NULL if we don't know about any such router. */
+const routerstatus_t *
+router_get_consensus_status_by_id(const char *digest)
+{
+ return router_get_mutable_consensus_status_by_id(digest);
+}
+
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
* the corresponding routerstatus_t, or NULL if none exists. Warn the
* user if <b>warn_if_unnamed</b> is set, and they have specified a router by
* nickname, but the Named flag isn't set for that router. */
-routerstatus_t *
+const routerstatus_t *
router_get_consensus_status_by_nickname(const char *nickname,
int warn_if_unnamed)
{
- char digest[DIGEST_LEN];
- routerstatus_t *best=NULL;
- smartlist_t *matches=NULL;
- const char *named_id=NULL;
-
- if (!current_consensus || !nickname)
- return NULL;
-
- /* Is this name really a hexadecimal identity digest? */
- if (nickname[0] == '$') {
- if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
- return NULL;
- return networkstatus_vote_find_entry(current_consensus, digest);
- } else if (strlen(nickname) == HEX_DIGEST_LEN &&
- (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
- return networkstatus_vote_find_entry(current_consensus, digest);
- }
-
- /* Is there a server that is Named with this name? */
- if (named_server_map)
- named_id = strmap_get_lc(named_server_map, nickname);
- if (named_id)
- return networkstatus_vote_find_entry(current_consensus, named_id);
-
- /* Okay; is this name listed as Unnamed? */
- if (unnamed_server_map &&
- strmap_get_lc(unnamed_server_map, nickname)) {
- log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
- "canonical name of any server we know.", escaped(nickname));
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->rs;
+ else
return NULL;
- }
-
- /* This name is not canonical for any server; go through the list and
- * see who it matches. */
- /*XXXX This is inefficient; optimize it if it matters. */
- matches = smartlist_create();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, lrs,
- {
- if (!strcasecmp(lrs->nickname, nickname)) {
- if (lrs->is_named) {
- tor_fragile_assert() /* This should never happen. */
- smartlist_free(matches);
- return lrs;
- } else {
- if (lrs->is_unnamed) {
- tor_fragile_assert(); /* nor should this. */
- smartlist_clear(matches);
- best=NULL;
- break;
- }
- smartlist_add(matches, lrs);
- best = lrs;
- }
- }
- });
-
- if (smartlist_len(matches)>1 && warn_if_unnamed) {
- int any_unwarned=0;
- SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
- {
- if (! lrs->name_lookup_warned) {
- lrs->name_lookup_warned=1;
- any_unwarned=1;
- }
- });
- if (any_unwarned) {
- log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
- " but none is listed as named by the directory authorities. "
- "Choosing one arbitrarily.", nickname);
- }
- } else if (warn_if_unnamed && best && !best->name_lookup_warned) {
- char fp[HEX_DIGEST_LEN+1];
- base16_encode(fp, sizeof(fp),
- best->identity_digest, DIGEST_LEN);
- log_warn(LD_CONFIG,
- "When looking up a status, you specified a server \"%s\" by name, "
- "but the directory authorities do not have any key registered for "
- "this nickname -- so it could be used by any server, "
- "not just the one you meant. "
- "To make sure you get the same server in the future, refer to "
- "it by key, as \"$%s\".", nickname, fp);
- best->name_lookup_warned = 1;
- }
- smartlist_free(matches);
- return best;
}
/** Return the identity digest that's mapped to officially by
@@ -1159,7 +1132,7 @@ update_v2_networkstatus_cache_downloads(time_t now)
{
char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
tor_addr_t addr;
- if (!(ds->type & V2_AUTHORITY))
+ if (!(ds->type & V2_DIRINFO))
continue;
if (router_digest_is_me(ds->digest))
continue;
@@ -1200,6 +1173,29 @@ update_v2_networkstatus_cache_downloads(time_t now)
}
}
+/** DOCDOC */
+static int
+we_want_to_fetch_flavor(const or_options_t *options, int flavor)
+{
+ if (flavor < 0 || flavor > N_CONSENSUS_FLAVORS) {
+ /* This flavor is crazy; we don't want it */
+ /*XXXX handle unrecognized flavors later */
+ return 0;
+ }
+ if (authdir_mode_v3(options) || directory_caches_dir_info(options)) {
+ /* We want to serve all flavors to others, regardless if we would use
+ * it ourselves. */
+ return 1;
+ }
+ if (options->FetchUselessDescriptors) {
+ /* In order to get all descriptors, we need to fetch all consensuses. */
+ return 1;
+ }
+ /* Otherwise, we want the flavor only if we want to use it to build
+ * circuits. */
+ return flavor == usable_consensus_flavor();
+}
+
/** How many times will we try to fetch a consensus before we give up? */
#define CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES 8
/** How long will we hang onto a possibly live consensus for which we're
@@ -1212,48 +1208,65 @@ static void
update_consensus_networkstatus_downloads(time_t now)
{
int i;
+ const or_options_t *options = get_options();
+
if (!networkstatus_get_live_consensus(now))
time_to_download_next_consensus = now; /* No live consensus? Get one now!*/
if (time_to_download_next_consensus > now)
return; /* Wait until the current consensus is older. */
- /* XXXXNM Microdescs: may need to download more types. */
- if (!download_status_is_ready(&consensus_dl_status[FLAV_NS], now,
- CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
- return; /* We failed downloading a consensus too recently. */
- if (connection_get_by_type_purpose(CONN_TYPE_DIR,
- DIR_PURPOSE_FETCH_CONSENSUS))
- return; /* There's an in-progress download.*/
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
- consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i];
+ /* XXXX need some way to download unknown flavors if we are caching. */
+ const char *resource;
+ consensus_waiting_for_certs_t *waiting;
+
+ if (! we_want_to_fetch_flavor(options, i))
+ continue;
+
+ resource = networkstatus_get_flavor_name(i);
+
+ if (!download_status_is_ready(&consensus_dl_status[i], now,
+ CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
+ continue; /* We failed downloading a consensus too recently. */
+ if (connection_dir_get_by_purpose_and_resource(
+ DIR_PURPOSE_FETCH_CONSENSUS, resource))
+ continue; /* There's an in-progress download.*/
+
+ waiting = &consensus_waiting_for_certs[i];
if (waiting->consensus) {
/* XXXX make sure this doesn't delay sane downloads. */
- if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now)
- return; /* We're still getting certs for this one. */
- else {
+ if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now) {
+ continue; /* We're still getting certs for this one. */
+ } else {
if (!waiting->dl_failed) {
- download_status_failed(&consensus_dl_status[FLAV_NS], 0);
+ download_status_failed(&consensus_dl_status[i], 0);
waiting->dl_failed=1;
}
}
}
- }
- log_info(LD_DIR, "Launching networkstatus consensus download.");
- directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
- ROUTER_PURPOSE_GENERAL, NULL,
- PDS_RETRY_IF_NO_SERVERS);
+ log_info(LD_DIR, "Launching %s networkstatus consensus download.",
+ networkstatus_get_flavor_name(i));
+
+ directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
+ ROUTER_PURPOSE_GENERAL, resource,
+ PDS_RETRY_IF_NO_SERVERS);
+ }
}
/** Called when an attempt to download a consensus fails: note that the
* failure occurred, and possibly retry. */
void
-networkstatus_consensus_download_failed(int status_code)
+networkstatus_consensus_download_failed(int status_code, const char *flavname)
{
- /* XXXXNM Microdescs: may need to handle more types. */
- download_status_failed(&consensus_dl_status[FLAV_NS], status_code);
- /* Retry immediately, if appropriate. */
- update_consensus_networkstatus_downloads(time(NULL));
+ int flav = networkstatus_parse_flavor_name(flavname);
+ if (flav >= 0) {
+ tor_assert(flav < N_CONSENSUS_FLAVORS);
+ /* XXXX handle unrecognized flavors */
+ download_status_failed(&consensus_dl_status[flav], status_code);
+ /* Retry immediately, if appropriate. */
+ update_consensus_networkstatus_downloads(time(NULL));
+ }
}
/** How long do we (as a cache) wait after a consensus becomes non-fresh
@@ -1265,7 +1278,7 @@ networkstatus_consensus_download_failed(int status_code)
void
update_consensus_networkstatus_fetch_time(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *c = networkstatus_get_live_consensus(now);
if (c) {
long dl_interval;
@@ -1339,7 +1352,7 @@ update_consensus_networkstatus_fetch_time(time_t now)
* fetches yet (e.g. we demand bridges and none are yet known).
* Else return 0. */
int
-should_delay_dir_fetches(or_options_t *options)
+should_delay_dir_fetches(const or_options_t *options)
{
if (options->UseBridges && !any_bridge_descriptors_known()) {
log_info(LD_DIR, "delaying dir fetches (no running bridges known)");
@@ -1353,7 +1366,7 @@ should_delay_dir_fetches(or_options_t *options)
void
update_networkstatus_downloads(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (should_delay_dir_fetches(options))
return;
if (authdir_mode_any_main(options) || options->FetchV2Networkstatus)
@@ -1374,7 +1387,10 @@ update_certificate_downloads(time_t now)
now);
}
- authority_certs_fetch_missing(current_consensus, now);
+ if (current_ns_consensus)
+ authority_certs_fetch_missing(current_ns_consensus, now);
+ if (current_md_consensus)
+ authority_certs_fetch_missing(current_md_consensus, now);
}
/** Return 1 if we have a consensus but we don't have enough certificates
@@ -1382,7 +1398,7 @@ update_certificate_downloads(time_t now)
int
consensus_is_waiting_for_certs(void)
{
- return consensus_waiting_for_certs[USABLE_CONSENSUS_FLAVOR].consensus
+ return consensus_waiting_for_certs[usable_consensus_flavor()].consensus
? 1 : 0;
}
@@ -1406,6 +1422,18 @@ networkstatus_get_latest_consensus(void)
return current_consensus;
}
+/** DOCDOC */
+networkstatus_t *
+networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
+{
+ if (f == FLAV_NS)
+ return current_ns_consensus;
+ else if (f == FLAV_MICRODESC)
+ return current_md_consensus;
+ else
+ tor_assert(0);
+}
+
/** Return the most recent consensus that we have downloaded, or NULL if it is
* no longer live. */
networkstatus_t *
@@ -1425,13 +1453,15 @@ networkstatus_get_live_consensus(time_t now)
/** As networkstatus_get_live_consensus(), but is way more tolerant of expired
* consensuses. */
networkstatus_t *
-networkstatus_get_reasonably_live_consensus(time_t now)
+networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
{
#define REASONABLY_LIVE_TIME (24*60*60)
- if (current_consensus &&
- current_consensus->valid_after <= now &&
- now <= current_consensus->valid_until+REASONABLY_LIVE_TIME)
- return current_consensus;
+ networkstatus_t *consensus =
+ networkstatus_get_latest_consensus_by_flavor(flavor);
+ if (consensus &&
+ consensus->valid_after <= now &&
+ now <= consensus->valid_until+REASONABLY_LIVE_TIME)
+ return consensus;
else
return NULL;
}
@@ -1452,7 +1482,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
a->is_exit != b->is_exit ||
a->is_stable != b->is_stable ||
a->is_fast != b->is_fast ||
- a->is_running != b->is_running ||
+ a->is_flagged_running != b->is_flagged_running ||
a->is_named != b->is_named ||
a->is_unnamed != b->is_unnamed ||
a->is_valid != b->is_valid ||
@@ -1493,13 +1523,14 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
}
changed = smartlist_create();
- SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
- new_c->routerstatus_list, routerstatus_t *, rs_new,
- tor_memcmp(rs_old->identity_digest,
- rs_new->identity_digest, DIGEST_LEN),
- smartlist_add(changed, rs_new)) {
+ SMARTLIST_FOREACH_JOIN(
+ old_c->routerstatus_list, const routerstatus_t *, rs_old,
+ new_c->routerstatus_list, const routerstatus_t *, rs_new,
+ tor_memcmp(rs_old->identity_digest,
+ rs_new->identity_digest, DIGEST_LEN),
+ smartlist_add(changed, (void*) rs_new)) {
if (routerstatus_has_changed(rs_old, rs_new))
- smartlist_add(changed, rs_new);
+ smartlist_add(changed, (void*)rs_new);
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
control_event_networkstatus_changed(changed);
@@ -1523,7 +1554,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->identity_digest, DIGEST_LEN),
STMT_NIL) {
/* Okay, so we're looking at the same identity. */
- rs_new->name_lookup_warned = rs_old->name_lookup_warned;
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
@@ -1559,7 +1589,7 @@ networkstatus_set_current_consensus(const char *consensus,
networkstatus_t *c=NULL;
int r, result = -1;
time_t now = time(NULL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *unverified_fname = NULL, *consensus_fname = NULL;
int flav = networkstatus_parse_flavor_name(flavor);
const unsigned from_cache = flags & NSSET_FROM_CACHE;
@@ -1597,7 +1627,7 @@ networkstatus_set_current_consensus(const char *consensus,
flavor = networkstatus_get_flavor_name(flav);
}
- if (flav != USABLE_CONSENSUS_FLAVOR &&
+ if (flav != usable_consensus_flavor() &&
!directory_caches_dir_info(options)) {
/* This consensus is totally boring to us: we won't use it, and we won't
* serve it. Drop it. */
@@ -1616,9 +1646,16 @@ networkstatus_set_current_consensus(const char *consensus,
if (!strcmp(flavor, "ns")) {
consensus_fname = get_datadir_fname("cached-consensus");
unverified_fname = get_datadir_fname("unverified-consensus");
- if (current_consensus) {
- current_digests = &current_consensus->digests;
- current_valid_after = current_consensus->valid_after;
+ if (current_ns_consensus) {
+ current_digests = &current_ns_consensus->digests;
+ current_valid_after = current_ns_consensus->valid_after;
+ }
+ } else if (!strcmp(flavor, "microdesc")) {
+ consensus_fname = get_datadir_fname("cached-microdesc-consensus");
+ unverified_fname = get_datadir_fname("unverified-microdesc-consensus");
+ if (current_md_consensus) {
+ current_digests = &current_md_consensus->digests;
+ current_valid_after = current_md_consensus->valid_after;
}
} else {
cached_dir_t *cur;
@@ -1695,24 +1732,36 @@ networkstatus_set_current_consensus(const char *consensus,
}
}
- if (!from_cache && flav == USABLE_CONSENSUS_FLAVOR)
+ if (!from_cache && flav == usable_consensus_flavor())
control_event_client_status(LOG_NOTICE, "CONSENSUS_ARRIVED");
/* Are we missing any certificates at all? */
if (r != 1 && dl_certs)
authority_certs_fetch_missing(c, now);
- if (flav == USABLE_CONSENSUS_FLAVOR) {
+ if (flav == usable_consensus_flavor()) {
notify_control_networkstatus_changed(current_consensus, c);
-
- if (current_consensus) {
- networkstatus_copy_old_consensus_info(c, current_consensus);
- networkstatus_vote_free(current_consensus);
+ }
+ if (flav == FLAV_NS) {
+ if (current_ns_consensus) {
+ networkstatus_copy_old_consensus_info(c, current_ns_consensus);
+ networkstatus_vote_free(current_ns_consensus);
/* Defensive programming : we should set current_consensus very soon,
* but we're about to call some stuff in the meantime, and leaving this
* dangling pointer around has proven to be trouble. */
- current_consensus = NULL;
+ current_ns_consensus = NULL;
+ }
+ current_ns_consensus = c;
+ free_consensus = 0; /* avoid free */
+ } else if (flav == FLAV_MICRODESC) {
+ if (current_md_consensus) {
+ networkstatus_copy_old_consensus_info(c, current_md_consensus);
+ networkstatus_vote_free(current_md_consensus);
+ /* more defensive programming */
+ current_md_consensus = NULL;
}
+ current_md_consensus = c;
+ free_consensus = 0; /* avoid free */
}
waiting = &consensus_waiting_for_certs[flav];
@@ -1737,12 +1786,12 @@ networkstatus_set_current_consensus(const char *consensus,
download_status_failed(&consensus_dl_status[flav], 0);
}
- if (flav == USABLE_CONSENSUS_FLAVOR) {
- current_consensus = c;
- free_consensus = 0; /* Prevent free. */
-
- /* XXXXNM Microdescs: needs a non-ns variant. */
+ if (flav == usable_consensus_flavor()) {
+ /* XXXXNM Microdescs: needs a non-ns variant. ???? NM*/
update_consensus_networkstatus_fetch_time(now);
+
+ nodelist_set_consensus(current_consensus);
+
dirvote_recalculate_timing(options, now);
routerstatus_list_update_named_server_map();
cell_ewma_set_scale_factor(options, current_consensus);
@@ -1769,11 +1818,11 @@ networkstatus_set_current_consensus(const char *consensus,
* valid-after time, declare that our clock is skewed. */
#define EARLY_CONSENSUS_NOTICE_SKEW 60
- if (now < current_consensus->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) {
+ if (now < c->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) {
char tbuf[ISO_TIME_LEN+1];
char dbuf[64];
- long delta = now - current_consensus->valid_after;
- format_iso_time(tbuf, current_consensus->valid_after);
+ long delta = now - c->valid_after;
+ format_iso_time(tbuf, c->valid_after);
format_time_interval(dbuf, sizeof(dbuf), delta);
log_warn(LD_GENERAL, "Our clock is %s behind the time published in the "
"consensus network status document (%s GMT). Tor needs an "
@@ -1824,7 +1873,8 @@ void
routers_update_all_from_networkstatus(time_t now, int dir_version)
{
routerlist_t *rl = router_get_routerlist();
- networkstatus_t *consensus = networkstatus_get_live_consensus(now);
+ networkstatus_t *consensus = networkstatus_get_reasonably_live_consensus(now,
+ FLAV_NS);
if (networkstatus_v2_list_has_changed)
download_status_map_update_from_v2_networkstatus();
@@ -1896,7 +1946,7 @@ download_status_map_update_from_v2_networkstatus(void)
dl_status = digestmap_new();
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
- SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
+ SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) {
const char *d = rs->descriptor_digest;
download_status_t *s;
if (digestmap_get(dl_status, d))
@@ -1924,7 +1974,8 @@ routerstatus_list_update_named_server_map(void)
named_server_map = strmap_new();
strmap_free(unnamed_server_map, NULL);
unnamed_server_map = strmap_new();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs,
+ SMARTLIST_FOREACH(current_consensus->routerstatus_list,
+ const routerstatus_t *, rs,
{
if (rs->is_named) {
strmap_set_lc(named_server_map, rs->nickname,
@@ -1944,9 +1995,8 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures)
{
trusted_dir_server_t *ds;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
- int namingdir = authdir && options->NamingAuthoritativeDir;
networkstatus_t *ns = current_consensus;
if (!ns || !smartlist_len(ns->routerstatus_list))
return;
@@ -1960,25 +2010,12 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
tor_memcmp(rs->identity_digest,
router->cache_info.identity_digest, DIGEST_LEN),
{
- /* We have no routerstatus for this router. Clear flags and skip it. */
- if (!namingdir)
- router->is_named = 0;
- if (!authdir) {
- if (router->purpose == ROUTER_PURPOSE_GENERAL)
- router_clear_status_flags(router);
- }
}) {
/* We have a routerstatus for this router. */
const char *digest = router->cache_info.identity_digest;
ds = router_get_trusteddirserver_by_digest(digest);
- if (!namingdir) {
- if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
- router->is_named = 1;
- else
- router->is_named = 0;
- }
/* Is it the same descriptor, or only the same identity? */
if (tor_memeq(router->cache_info.signed_descriptor_digest,
rs->descriptor_digest, DIGEST_LEN)) {
@@ -1986,28 +2023,17 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
router->cache_info.last_listed_as_valid_until = ns->valid_until;
}
- if (!authdir) {
- /* If we're not an authdir, believe others. */
- router->is_valid = rs->is_valid;
- router->is_running = rs->is_running;
- router->is_fast = rs->is_fast;
- router->is_stable = rs->is_stable;
- router->is_possible_guard = rs->is_possible_guard;
- router->is_exit = rs->is_exit;
- router->is_bad_directory = rs->is_bad_directory;
- router->is_bad_exit = rs->is_bad_exit;
- router->is_hs_dir = rs->is_hs_dir;
- } else {
+ if (authdir) {
/* If we _are_ an authority, we should check whether this router
* is one that will cause us to need a reachability test. */
routerinfo_t *old_router =
- router_get_by_digest(router->cache_info.identity_digest);
+ router_get_mutable_by_digest(router->cache_info.identity_digest);
if (old_router != router) {
router->needs_retest_if_added =
dirserv_should_launch_reachability_test(router, old_router);
}
}
- if (router->is_running && ds) {
+ if (rs->is_flagged_running && ds) {
download_status_reset(&ds->v2_ns_dl_status);
}
if (reset_failures) {
@@ -2016,10 +2042,9 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
} SMARTLIST_FOREACH_JOIN_END(rs, router);
/* Now update last_listed_as_valid_until from v2 networkstatuses. */
- /* XXXX If this is slow, we need to rethink the code. */
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, {
time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
- SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
+ SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs,
routers, routerinfo_t *, ri,
tor_memcmp(rs->identity_digest,
ri->cache_info.identity_digest, DIGEST_LEN),
@@ -2040,7 +2065,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
void
signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
{
- networkstatus_t *ns = current_consensus;
+ networkstatus_t *ns = current_ns_consensus;
if (!ns)
return;
@@ -2048,11 +2073,11 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
char dummy[DIGEST_LEN];
/* instantiates the digest map. */
memset(dummy, 0, sizeof(dummy));
- router_get_consensus_status_by_descriptor_digest(dummy);
+ router_get_consensus_status_by_descriptor_digest(ns, dummy);
}
SMARTLIST_FOREACH(descs, signed_descriptor_t *, d,
{
- routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
+ const routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
d->signed_descriptor_digest);
if (rs) {
if (ns->valid_until > d->last_listed_as_valid_until)
@@ -2065,7 +2090,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
* return the result in a newly allocated string. Used only by controller
* interface (for now.) */
char *
-networkstatus_getinfo_helper_single(routerstatus_t *rs)
+networkstatus_getinfo_helper_single(const routerstatus_t *rs)
{
char buf[RS_ENTRY_LEN+1];
routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT);
@@ -2098,6 +2123,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
statuses = smartlist_create();
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
if (ri->cache_info.published_on < cutoff)
continue;
if (ri->purpose != purpose)
@@ -2105,7 +2133,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
dirserv_set_router_is_running(ri, now);
/* then generate and write out status lines for each of them */
- set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0, 0);
+ set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0, 0);
smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
});
@@ -2120,7 +2148,7 @@ void
networkstatus_dump_bridge_status_to_file(time_t now)
{
char *status = networkstatus_getinfo_by_purpose("bridge", now);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
size_t len = strlen(options->DataDirectory) + 32;
char *fname = tor_malloc(len);
tor_snprintf(fname, len, "%s"PATH_SEPARATOR"networkstatus-bridges",
@@ -2174,7 +2202,7 @@ get_net_param_from_list(smartlist_t *net_params, const char *param_name,
* <b>min_val</b> and at most <b>max_val</b> and raise/cap the parsed value
* if necessary. */
int32_t
-networkstatus_get_param(networkstatus_t *ns, const char *param_name,
+networkstatus_get_param(const networkstatus_t *ns, const char *param_name,
int32_t default_val, int32_t min_val, int32_t max_val)
{
if (!ns) /* if they pass in null, go find it ourselves */
@@ -2253,7 +2281,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg)
{
- routerstatus_t *status;
+ const routerstatus_t *status;
(void) conn;
if (!current_consensus) {
@@ -2264,7 +2292,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
if (!strcmp(question, "ns/all")) {
smartlist_t *statuses = smartlist_create();
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
+ const routerstatus_t *, rs,
{
smartlist_add(statuses, networkstatus_getinfo_helper_single(rs));
});
@@ -2308,8 +2336,9 @@ networkstatus_free_all(void)
digestmap_free(v2_download_status_map, _tor_free);
v2_download_status_map = NULL;
- networkstatus_vote_free(current_consensus);
- current_consensus = NULL;
+ networkstatus_vote_free(current_ns_consensus);
+ networkstatus_vote_free(current_md_consensus);
+ current_md_consensus = current_ns_consensus = NULL;
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i];
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index ec2e8f884d..1b10f27388 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -38,31 +38,46 @@ int router_set_networkstatus_v2(const char *s, time_t arrived_at,
void networkstatus_v2_list_clean(time_t now);
int compare_digest_to_routerstatus_entry(const void *_key,
const void **_member);
-routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
+const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
const char *digest);
-routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
+const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
+ const char *digest);
+routerstatus_t *networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns,
+ const char *digest);
+routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
const smartlist_t *networkstatus_get_v2_list(void);
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
-routerstatus_t *router_get_consensus_status_by_id(const char *digest);
-routerstatus_t *router_get_consensus_status_by_descriptor_digest(
- const char *digest);
-routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
- int warn_if_unnamed);
+const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
+routerstatus_t *router_get_mutable_consensus_status_by_id(
+ const char *digest);
+const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest);
+routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest);
+const routerstatus_t *router_get_consensus_status_by_nickname(
+ const char *nickname,
+ int warn_if_unnamed);
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
int networkstatus_nickname_is_unnamed(const char *nickname);
-void networkstatus_consensus_download_failed(int status_code);
+void networkstatus_consensus_download_failed(int status_code,
+ const char *flavname);
void update_consensus_networkstatus_fetch_time(time_t now);
-int should_delay_dir_fetches(or_options_t *options);
+int should_delay_dir_fetches(const or_options_t *options);
void update_networkstatus_downloads(time_t now);
void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_t *networkstatus_get_latest_consensus(void);
+networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
+ consensus_flavor_t f);
networkstatus_t *networkstatus_get_live_consensus(time_t now);
-networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now);
+networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
+ int flavor);
#define NSSET_FROM_CACHE 1
#define NSSET_WAS_WAITING_FOR_CERTS 2
#define NSSET_DONT_DOWNLOAD_CERTS 4
@@ -78,10 +93,11 @@ void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
void signed_descs_update_status_from_consensus_networkstatus(
smartlist_t *descs);
-char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
+char *networkstatus_getinfo_helper_single(const routerstatus_t *rs);
char *networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now);
void networkstatus_dump_bridge_status_to_file(time_t now);
-int32_t networkstatus_get_param(networkstatus_t *ns, const char *param_name,
+int32_t networkstatus_get_param(const networkstatus_t *ns,
+ const char *param_name,
int32_t default_val, int32_t min_val,
int32_t max_val);
int getinfo_helper_networkstatus(control_connection_t *conn,
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
new file mode 100644
index 0000000000..b93b919c13
--- /dev/null
+++ b/src/or/nodelist.c
@@ -0,0 +1,758 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "config.h"
+#include "dirserv.h"
+#include "microdesc.h"
+#include "networkstatus.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
+
+#include <string.h>
+
+static void nodelist_drop_node(node_t *node, int remove_from_ht);
+static void node_free(node_t *node);
+
+/** A nodelist_t holds a node_t object for every router we're "willing to use
+ * for something". Specifically, it should hold a node_t for every node that
+ * is currently in the routerlist, or currently in the consensus we're using.
+ */
+typedef struct nodelist_t {
+ /* A list of all the nodes. */
+ smartlist_t *nodes;
+ /* Hash table to map from node ID digest to node. */
+ HT_HEAD(nodelist_map, node_t) nodes_by_id;
+
+} nodelist_t;
+
+static INLINE unsigned int
+node_id_hash(const node_t *node)
+{
+#if SIZEOF_INT == 4
+ const uint32_t *p = (const uint32_t*)node->identity;
+ return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
+#elif SIZEOF_INT == 8
+ const uint64_t *p = (const uint32_t*)node->identity;
+ const uint32_t *p32 = (const uint32_t*)node->identity;
+ return p[0] ^ p[1] ^ p32[4];
+#endif
+}
+
+static INLINE unsigned int
+node_id_eq(const node_t *node1, const node_t *node2)
+{
+ return tor_memeq(node1->identity, node2->identity, DIGEST_LEN);
+}
+
+HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq);
+HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq,
+ 0.6, malloc, realloc, free);
+
+/** The global nodelist. */
+static nodelist_t *the_nodelist=NULL;
+
+/** Create an empty nodelist if we haven't done so already. */
+static void
+init_nodelist(void)
+{
+ if (PREDICT_UNLIKELY(the_nodelist == NULL)) {
+ the_nodelist = tor_malloc_zero(sizeof(nodelist_t));
+ HT_INIT(nodelist_map, &the_nodelist->nodes_by_id);
+ the_nodelist->nodes = smartlist_create();
+ }
+}
+
+/** As node_get_by_id, but returns a non-const pointer */
+node_t *
+node_get_mutable_by_id(const char *identity_digest)
+{
+ node_t search, *node;
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return NULL;
+
+ memcpy(&search.identity, identity_digest, DIGEST_LEN);
+ node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search);
+ return node;
+}
+
+/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
+ * if no such node exists. */
+const node_t *
+node_get_by_id(const char *identity_digest)
+{
+ return node_get_mutable_by_id(identity_digest);
+}
+
+/** Internal: return the node_t whose identity_digest is
+ * <b>identity_digest</b>. If none exists, create a new one, add it to the
+ * nodelist, and return it.
+ *
+ * Requires that the nodelist be initialized.
+ */
+static node_t *
+node_get_or_create(const char *identity_digest)
+{
+ node_t *node;
+
+ if ((node = node_get_mutable_by_id(identity_digest)))
+ return node;
+
+ node = tor_malloc_zero(sizeof(node_t));
+ memcpy(node->identity, identity_digest, DIGEST_LEN);
+ HT_INSERT(nodelist_map, &the_nodelist->nodes_by_id, node);
+
+ smartlist_add(the_nodelist->nodes, node);
+ node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1;
+
+ node->country = -1;
+
+ return node;
+}
+
+/** Add <b>ri</b> to the nodelist. */
+node_t *
+nodelist_add_routerinfo(routerinfo_t *ri)
+{
+ node_t *node;
+ init_nodelist();
+ node = node_get_or_create(ri->cache_info.identity_digest);
+ node->ri = ri;
+
+ if (node->country == -1)
+ node_set_country(node);
+
+ if (authdir_mode(get_options())) {
+ const char *discard=NULL;
+ uint32_t status = dirserv_router_get_status(ri, &discard);
+ dirserv_set_node_flags_from_authoritative_status(node, status);
+ }
+
+ return node;
+}
+
+/** Set the appropriate node_t to use <b>md</b> as its microdescriptor.
+ *
+ * Called when a new microdesc has arrived and the usable consensus flavor
+ * is "microdesc".
+ **/
+node_t *
+nodelist_add_microdesc(microdesc_t *md)
+{
+ networkstatus_t *ns =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ const routerstatus_t *rs;
+ node_t *node;
+ if (ns == NULL)
+ return NULL;
+ init_nodelist();
+
+ /* Microdescriptors don't carry an identity digest, so we need to figure
+ * it out by looking up the routerstatus. */
+ rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
+ if (rs == NULL)
+ return NULL;
+ node = node_get_mutable_by_id(rs->identity_digest);
+ if (node) {
+ if (node->md)
+ node->md->held_by_nodes--;
+ node->md = md;
+ md->held_by_nodes++;
+ }
+ return node;
+}
+
+/** Tell the nodelist that the current usable consensus to <b>ns</b>.
+ * This makes the nodelist change all of the routerstatus entries for
+ * the nodes, drop nodes that no longer have enough info to get used,
+ * and grab microdescriptors into nodes as appropriate.
+ */
+void
+nodelist_set_consensus(networkstatus_t *ns)
+{
+ const or_options_t *options = get_options();
+ int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
+
+ init_nodelist();
+ if (ns->flavor == FLAV_MICRODESC)
+ (void) get_microdesc_cache(); /* Make sure it exists first. */
+
+ SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
+ node->rs = NULL);
+
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ node_t *node = node_get_or_create(rs->identity_digest);
+ node->rs = rs;
+ if (ns->flavor == FLAV_MICRODESC) {
+ if (node->md == NULL ||
+ tor_memneq(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) {
+ if (node->md)
+ node->md->held_by_nodes--;
+ node->md = microdesc_cache_lookup_by_digest256(NULL,
+ rs->descriptor_digest);
+ if (node->md)
+ node->md->held_by_nodes++;
+ }
+ }
+
+ node_set_country(node);
+
+ /* If we're not an authdir, believe others. */
+ if (!authdir) {
+ node->is_valid = rs->is_valid;
+ node->is_running = rs->is_flagged_running;
+ node->is_fast = rs->is_fast;
+ node->is_stable = rs->is_stable;
+ node->is_possible_guard = rs->is_possible_guard;
+ node->is_exit = rs->is_exit;
+ node->is_bad_directory = rs->is_bad_directory;
+ node->is_bad_exit = rs->is_bad_exit;
+ node->is_hs_dir = rs->is_hs_dir;
+ }
+
+ } SMARTLIST_FOREACH_END(rs);
+
+ nodelist_purge();
+
+ if (! authdir) {
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ /* We have no routerstatus for this router. Clear flags so we can skip
+ * it, maybe.*/
+ if (!node->rs) {
+ tor_assert(node->ri); /* if it had only an md, or nothing, purge
+ * would have removed it. */
+ if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) {
+ /* Clear all flags. */
+ node->is_valid = node->is_running = node->is_hs_dir =
+ node->is_fast = node->is_stable =
+ node->is_possible_guard = node->is_exit =
+ node->is_bad_exit = node->is_bad_directory = 0;
+ }
+ }
+ } SMARTLIST_FOREACH_END(node);
+ }
+}
+
+/** Helper: return true iff a node has a usable amount of information*/
+static INLINE int
+node_is_usable(const node_t *node)
+{
+ return (node->rs) || (node->ri);
+}
+
+/** Tell the nodelist that <b>md</b> is no longer a microdescriptor for the
+ * node with <b>identity_digest</b>. */
+void
+nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
+{
+ node_t *node = node_get_mutable_by_id(identity_digest);
+ if (node && node->md == md) {
+ node->md = NULL;
+ md->held_by_nodes--;
+ }
+}
+
+/** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */
+void
+nodelist_remove_routerinfo(routerinfo_t *ri)
+{
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (node && node->ri == ri) {
+ node->ri = NULL;
+ if (! node_is_usable(node)) {
+ nodelist_drop_node(node, 1);
+ node_free(node);
+ }
+ }
+}
+
+/** Remove <b>node</b> from the nodelist. (Asserts that it was there to begin
+ * with.) */
+static void
+nodelist_drop_node(node_t *node, int remove_from_ht)
+{
+ node_t *tmp;
+ int idx;
+ if (remove_from_ht) {
+ tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
+ tor_assert(tmp == node);
+ }
+
+ idx = node->nodelist_idx;
+ tor_assert(idx >= 0);
+
+ tor_assert(node == smartlist_get(the_nodelist->nodes, idx));
+ smartlist_del(the_nodelist->nodes, idx);
+ if (idx < smartlist_len(the_nodelist->nodes)) {
+ tmp = smartlist_get(the_nodelist->nodes, idx);
+ tmp->nodelist_idx = idx;
+ }
+ node->nodelist_idx = -1;
+}
+
+/** Release storage held by <b>node</b> */
+static void
+node_free(node_t *node)
+{
+ if (!node)
+ return;
+ if (node->md)
+ node->md->held_by_nodes--;
+ tor_assert(node->nodelist_idx == -1);
+ tor_free(node);
+}
+
+/** Remove all entries from the nodelist that don't have enough info to be
+ * usable for anything. */
+void
+nodelist_purge(void)
+{
+ node_t **iter;
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return;
+
+ /* Remove the non-usable nodes. */
+ for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) {
+ node_t *node = *iter;
+
+ if (node->md && !node->rs) {
+ /* An md is only useful if there is an rs. */
+ node->md->held_by_nodes--;
+ node->md = NULL;
+ }
+
+ if (node_is_usable(node)) {
+ iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter);
+ } else {
+ iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter);
+ nodelist_drop_node(node, 0);
+ node_free(node);
+ }
+ }
+ nodelist_assert_ok();
+}
+
+/** Release all storage held by the nodelist. */
+void
+nodelist_free_all(void)
+{
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return;
+
+ HT_CLEAR(nodelist_map, &the_nodelist->nodes_by_id);
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ node->nodelist_idx = -1;
+ node_free(node);
+ } SMARTLIST_FOREACH_END(node);
+
+ smartlist_free(the_nodelist->nodes);
+
+ tor_free(the_nodelist);
+}
+
+/** Check that the nodelist is internally consistent, and consistent with
+ * the directory info it's derived from.
+ */
+void
+nodelist_assert_ok(void)
+{
+ routerlist_t *rl = router_get_routerlist();
+ networkstatus_t *ns = networkstatus_get_latest_consensus();
+ digestmap_t *dm;
+
+ if (!the_nodelist)
+ return;
+
+ dm = digestmap_new();
+
+ /* every routerinfo in rl->routers should be in the nodelist. */
+ if (rl) {
+ SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node && node->ri == ri);
+ tor_assert(fast_memeq(ri->cache_info.identity_digest,
+ node->identity, DIGEST_LEN));
+ tor_assert(! digestmap_get(dm, node->identity));
+ digestmap_set(dm, node->identity, (void*)node);
+ } SMARTLIST_FOREACH_END(ri);
+ }
+
+ /* every routerstatus in ns should be in the nodelist */
+ if (ns) {
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ const node_t *node = node_get_by_id(rs->identity_digest);
+ tor_assert(node && node->rs == rs);
+ tor_assert(fast_memeq(rs->identity_digest, node->identity, DIGEST_LEN));
+ digestmap_set(dm, node->identity, (void*)node);
+ if (ns->flavor == FLAV_MICRODESC) {
+ /* If it's a microdesc consensus, every entry that has a
+ * microdescriptor should be in the nodelist.
+ */
+ microdesc_t *md =
+ microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
+ tor_assert(md == node->md);
+ if (md)
+ tor_assert(md->held_by_nodes >= 1);
+ }
+ } SMARTLIST_FOREACH_END(rs);
+ }
+
+ /* The nodelist should have no other entries, and its entries should be
+ * well-formed. */
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ tor_assert(digestmap_get(dm, node->identity) != NULL);
+ tor_assert(node_sl_idx == node->nodelist_idx);
+ } SMARTLIST_FOREACH_END(node);
+
+ tor_assert((long)smartlist_len(the_nodelist->nodes) ==
+ (long)HT_SIZE(&the_nodelist->nodes_by_id));
+
+ digestmap_free(dm, NULL);
+}
+
+/** Return a list of a node_t * for every node we know about. The caller
+ * MUST NOT modify the list. (You can set and clear flags in the nodes if
+ * you must, but you must not add or remove nodes.) */
+smartlist_t *
+nodelist_get_list(void)
+{
+ init_nodelist();
+ return the_nodelist->nodes;
+}
+
+/** Given a hex-encoded nickname of the format DIGEST, $DIGEST, $DIGEST=name,
+ * or $DIGEST~name, return the node with the matching identity digest and
+ * nickname (if any). Return NULL if no such node exists, or if <b>hex_id</b>
+ * is not well-formed. */
+const node_t *
+node_get_by_hex_id(const char *hex_id)
+{
+ char digest_buf[DIGEST_LEN];
+ char nn_buf[MAX_NICKNAME_LEN+1];
+ char nn_char='\0';
+
+ if (hex_digest_nickname_decode(hex_id, digest_buf, &nn_char, nn_buf)==0) {
+ const node_t *node = node_get_by_id(digest_buf);
+ if (!node)
+ return NULL;
+ if (nn_char) {
+ const char *real_name = node_get_nickname(node);
+ if (!real_name || strcasecmp(real_name, nn_buf))
+ return NULL;
+ if (nn_char == '=') {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nn_buf);
+ if (!named_id || tor_memneq(named_id, digest_buf, DIGEST_LEN))
+ return NULL;
+ }
+ }
+ return node;
+ }
+
+ return NULL;
+}
+
+/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
+ * the corresponding node_t, or NULL if none exists. Warn the user if
+ * <b>warn_if_unnamed</b> is set, and they have specified a router by
+ * nickname, but the Named flag isn't set for that router. */
+const node_t *
+node_get_by_nickname(const char *nickname, int warn_if_unnamed)
+{
+ const node_t *node;
+ if (!the_nodelist)
+ return NULL;
+
+ /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
+ if ((node = node_get_by_hex_id(nickname)) != NULL)
+ return node;
+
+ if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME))
+ return NULL;
+
+ /* Okay, so if we get here, the nickname is just a nickname. Is there
+ * a binding for it in the consensus? */
+ {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nickname);
+ if (named_id)
+ return node_get_by_id(named_id);
+ }
+
+ /* Is it marked as owned-by-someone-else? */
+ if (networkstatus_nickname_is_unnamed(nickname)) {
+ log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some "
+ "router that holds it, but not one listed in the current "
+ "consensus.", escaped(nickname));
+ return NULL;
+ }
+
+ /* Okay, so the name is not canonical for anybody. */
+ {
+ smartlist_t *matches = smartlist_create();
+ const node_t *choice = NULL;
+
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ if (!strcasecmp(node_get_nickname(node), nickname))
+ smartlist_add(matches, node);
+ } SMARTLIST_FOREACH_END(node);
+
+ if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ int any_unwarned = 0;
+ SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) {
+ if (!node->name_lookup_warned) {
+ node->name_lookup_warned = 1;
+ any_unwarned = 1;
+ }
+ } SMARTLIST_FOREACH_END(node);
+
+ if (any_unwarned) {
+ log_warn(LD_CONFIG, "There are multiple matches for the name %s, "
+ "but none is listed as Named in the directory consensus. "
+ "Choosing one arbitrarily.", nickname);
+ }
+ } else if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ char fp[HEX_DIGEST_LEN+1];
+ node_t *node = smartlist_get(matches, 0);
+ if (node->name_lookup_warned) {
+ base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN);
+ log_warn(LD_CONFIG,
+ "You specified a server \"%s\" by name, but the directory "
+ "authorities do not have any key registered for this "
+ "nickname -- so it could be used by any server, not just "
+ "the one you meant. "
+ "To make sure you get the same server in the future, refer "
+ "to it by key, as \"$%s\".", nickname, fp);
+ node->name_lookup_warned = 1;
+ }
+ }
+
+ if (smartlist_len(matches))
+ choice = smartlist_get(matches, 0);
+
+ smartlist_free(matches);
+ return choice;
+ }
+}
+
+/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
+const char *
+node_get_nickname(const node_t *node)
+{
+ tor_assert(node);
+ if (node->rs)
+ return node->rs->nickname;
+ else if (node->ri)
+ return node->ri->nickname;
+ else
+ return NULL;
+}
+
+/** Return true iff the nickname of <b>node</b> is canonical, based on the
+ * latest consensus. */
+int
+node_is_named(const node_t *node)
+{
+ const char *named_id;
+ const char *nickname = node_get_nickname(node);
+ if (!nickname)
+ return 0;
+ named_id = networkstatus_get_router_digest_by_nickname(nickname);
+ if (!named_id)
+ return 0;
+ return tor_memeq(named_id, node->identity, DIGEST_LEN);
+}
+
+/** Return true iff <b>node</b> appears to be a directory authority or
+ * directory cache */
+int
+node_is_dir(const node_t *node)
+{
+ if (node->rs)
+ return node->rs->dir_port != 0;
+ else if (node->ri)
+ return node->ri->dir_port != 0;
+ else
+ return 0;
+}
+
+/** Return true iff <b>node</b> has either kind of usable descriptor -- that
+ * is, a routerdecriptor or a microdescriptor. */
+int
+node_has_descriptor(const node_t *node)
+{
+ return (node->ri ||
+ (node->rs && node->md));
+}
+
+/** Return the router_purpose of <b>node</b>. */
+int
+node_get_purpose(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->purpose;
+ else
+ return ROUTER_PURPOSE_GENERAL;
+}
+
+/** Compute the verbose ("extended") nickname of <b>node</b> and store it
+ * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at
+ * <b>verbose_nickname_out</b> */
+void
+node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out)
+{
+ const char *nickname = node_get_nickname(node);
+ int is_named = node_is_named(node);
+ verbose_name_out[0] = '$';
+ base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity,
+ DIGEST_LEN);
+ if (!nickname)
+ return;
+ verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+ strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+}
+
+/** Return true iff it seems that <b>node</b> allows circuits to exit
+ * through it directlry from the client. */
+int
+node_allows_single_hop_exits(const node_t *node)
+{
+ if (node && node->ri)
+ return node->ri->allow_single_hop_exits;
+ else
+ return 0;
+}
+
+/** Return true iff it seems that <b>node</b> has an exit policy that doesn't
+ * actually permit anything to exit, or we don't know its exit policy */
+int
+node_exit_policy_rejects_all(const node_t *node)
+{
+ if (node->rejects_all)
+ return 1;
+
+ if (node->ri)
+ return node->ri->policy_is_reject_star;
+ else if (node->md)
+ return node->md->exit_policy == NULL ||
+ short_policy_is_reject_star(node->md->exit_policy);
+ else
+ return 1;
+}
+
+/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
+int
+node_get_addr(const node_t *node, tor_addr_t *addr_out)
+{
+ if (node->ri) {
+ tor_addr_from_ipv4h(addr_out, node->ri->addr);
+ return 0;
+ } else if (node->rs) {
+ tor_addr_from_ipv4h(addr_out, node->rs->addr);
+ return 0;
+ }
+ return -1;
+}
+
+/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
+ * seem to have one. */
+uint32_t
+node_get_addr_ipv4h(const node_t *node)
+{
+ if (node->ri) {
+ return node->ri->addr;
+ } else if (node->rs) {
+ return node->rs->addr;
+ }
+ return 0;
+}
+
+/** Copy a string representation of the IP address for <b>node</b> into the
+ * <b>len</b>-byte buffer at <b>buf</b>.
+ */
+void
+node_get_address_string(const node_t *node, char *buf, size_t len)
+{
+ if (node->ri) {
+ strlcpy(buf, node->ri->address, len);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ tor_addr_to_str(buf, &addr, len, 0);
+ } else {
+ buf[0] = '\0';
+ }
+}
+
+/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have
+ * one. */
+long
+node_get_declared_uptime(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->uptime;
+ else
+ return -1;
+}
+
+/** Return <b>node</b>'s declared or_port */
+uint16_t
+node_get_orport(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->or_port;
+ else if (node->rs)
+ return node->rs->or_port;
+ else
+ return 0;
+}
+
+/** Return <b>node</b>'s platform string, or NULL if we don't know it. */
+const char *
+node_get_platform(const node_t *node)
+{
+ /* If we wanted, we could record the version in the routerstatus_t, since
+ * the consensus lists it. We don't, though, so this function just won't
+ * work with microdescriptors. */
+ if (node->ri)
+ return node->ri->platform;
+ else
+ return NULL;
+}
+
+/** Return <b>node</b>'s time of publication, or 0 if we don't have one. */
+time_t
+node_get_published_on(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->cache_info.published_on;
+ else
+ return 0;
+}
+
+/** Return true iff <b>node</b> is one representing this router. */
+int
+node_is_me(const node_t *node)
+{
+ return router_digest_is_me(node->identity);
+}
+
+/** Return <b>node</b> declared family (as a list of names), or NULL if
+ * the node didn't declare a family. */
+const smartlist_t *
+node_get_declared_family(const node_t *node)
+{
+ if (node->ri && node->ri->declared_family)
+ return node->ri->declared_family;
+ else if (node->md && node->md->family)
+ return node->md->family;
+ else
+ return NULL;
+}
+
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
new file mode 100644
index 0000000000..bd2e63953c
--- /dev/null
+++ b/src/or/nodelist.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file microdesc.h
+ * \brief Header file for microdesc.c.
+ **/
+
+#ifndef _TOR_NODELIST_H
+#define _TOR_NODELIST_H
+
+node_t *node_get_mutable_by_id(const char *identity_digest);
+const node_t *node_get_by_id(const char *identity_digest);
+const node_t *node_get_by_hex_id(const char *identity_digest);
+node_t *nodelist_add_routerinfo(routerinfo_t *ri);
+node_t *nodelist_add_microdesc(microdesc_t *md);
+void nodelist_set_consensus(networkstatus_t *ns);
+
+void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
+void nodelist_remove_routerinfo(routerinfo_t *ri);
+void nodelist_purge(void);
+
+void nodelist_free_all(void);
+void nodelist_assert_ok(void);
+
+const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed);
+void node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out);
+int node_is_named(const node_t *node);
+int node_is_dir(const node_t *node);
+int node_has_descriptor(const node_t *node);
+int node_get_purpose(const node_t *node);
+#define node_is_bridge(node) \
+ (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
+int node_is_me(const node_t *node);
+int node_exit_policy_rejects_all(const node_t *node);
+int node_get_addr(const node_t *node, tor_addr_t *addr_out);
+uint32_t node_get_addr_ipv4h(const node_t *node);
+int node_allows_single_hop_exits(const node_t *node);
+uint16_t node_get_orport(const node_t *node);
+const char *node_get_nickname(const node_t *node);
+const char *node_get_platform(const node_t *node);
+void node_get_address_string(const node_t *node, char *cp, size_t len);
+long node_get_declared_uptime(const node_t *node);
+time_t node_get_published_on(const node_t *node);
+const smartlist_t *node_get_declared_family(const node_t *node);
+
+smartlist_t *nodelist_get_list(void);
+
+/* XXXX These need to move out of routerlist.c */
+void nodelist_refresh_countries(void);
+void node_set_country(node_t *node);
+void nodelist_add_node_and_family(smartlist_t *nodes, const node_t *node);
+int nodes_in_same_family(const node_t *node1, const node_t *node2);
+
+#endif
+
diff --git a/src/or/ntmain.c b/src/or/ntmain.c
index b2fee648cc..8d03ea8087 100644
--- a/src/or/ntmain.c
+++ b/src/or/ntmain.c
@@ -193,7 +193,6 @@ nt_service_loadlibrary(void)
*/
int
nt_service_is_stopping(void)
-/* XXXX this function would probably _love_ to be inline, in 0.2.0. */
{
/* If we haven't loaded the function pointers, we can't possibly be an NT
* service trying to shut down. */
@@ -728,6 +727,7 @@ nt_service_parse_options(int argc, char **argv, int *should_exit)
if ((argc >= 3) &&
(!strcmp(argv[1], "-service") || !strcmp(argv[1], "--service"))) {
nt_service_loadlibrary();
+ *should_exit = 1;
if (!strcmp(argv[2], "install"))
return nt_service_install(argc, argv);
if (!strcmp(argv[2], "remove"))
@@ -737,7 +737,6 @@ nt_service_parse_options(int argc, char **argv, int *should_exit)
if (!strcmp(argv[2], "stop"))
return nt_service_cmd_stop();
printf("Unrecognized service command '%s'\n", argv[2]);
- *should_exit = 1;
return 1;
}
if (argc >= 2) {
diff --git a/src/or/or.h b/src/or/or.h
index 3510ab0421..9d6f605024 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -23,8 +23,12 @@
#endif
#ifdef MS_WINDOWS
+#ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+#endif
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
#define WIN32_LEAN_AND_MEAN
#endif
@@ -83,6 +87,13 @@
#define snprintf _snprintf
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#include <event2/buffer.h>
+#include <event2/util.h>
+#endif
+
+#include "crypto.h"
#include "tortls.h"
#include "../common/torlog.h"
#include "container.h"
@@ -225,15 +236,30 @@ typedef enum {
#define PROXY_CONNECT 1
#define PROXY_SOCKS4 2
#define PROXY_SOCKS5 3
+/* !!!! If there is ever a PROXY_* type over 2, we must grow the proxy_type
+ * field in or_connection_t */
+/* pluggable transports proxy type */
+#define PROXY_PLUGGABLE 4
/* Proxy client handshake states */
-#define PROXY_HTTPS_WANT_CONNECT_OK 1
-#define PROXY_SOCKS4_WANT_CONNECT_OK 2
-#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 3
-#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 4
-#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 5
-#define PROXY_SOCKS5_WANT_CONNECT_OK 6
-#define PROXY_CONNECTED 7
+/* We use a proxy but we haven't even connected to it yet. */
+#define PROXY_INFANT 1
+/* We use an HTTP proxy and we've sent the CONNECT command. */
+#define PROXY_HTTPS_WANT_CONNECT_OK 2
+/* We use a SOCKS4 proxy and we've sent the CONNECT command. */
+#define PROXY_SOCKS4_WANT_CONNECT_OK 3
+/* We use a SOCKS5 proxy and we try to negotiate without
+ any authentication . */
+#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 4
+/* We use a SOCKS5 proxy and we try to negotiate with
+ Username/Password authentication . */
+#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 5
+/* We use a SOCKS5 proxy and we just sent our credentials. */
+#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
+/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
+#define PROXY_SOCKS5_WANT_CONNECT_OK 7
+/* We use a proxy and we CONNECTed successfully!. */
+#define PROXY_CONNECTED 8
/** True iff <b>x</b> is an edge connection. */
#define CONN_IS_EDGE(x) \
@@ -257,22 +283,27 @@ typedef enum {
#define OR_CONN_STATE_CONNECTING 1
/** State for a connection to an OR: waiting for proxy handshake to complete */
#define OR_CONN_STATE_PROXY_HANDSHAKING 2
-/** State for a connection to an OR or client: SSL is handshaking, not done
+/** State for an OR connection client: SSL is handshaking, not done
* yet. */
#define OR_CONN_STATE_TLS_HANDSHAKING 3
/** State for a connection to an OR: We're doing a second SSL handshake for
- * renegotiation purposes. */
+ * renegotiation purposes. (V2 handshake only.) */
#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4
/** State for a connection at an OR: We're waiting for the client to
- * renegotiate. */
+ * renegotiate (to indicate a v2 handshake) or send a versions cell (to
+ * indicate a v3 handshake) */
#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5
-/** State for a connection to an OR: We're done with our SSL handshake, but we
- * haven't yet negotiated link protocol versions and sent a netinfo cell.
- */
-#define OR_CONN_STATE_OR_HANDSHAKING 6
-/** State for a connection to an OR: Ready to send/receive cells. */
-#define OR_CONN_STATE_OPEN 7
-#define _OR_CONN_STATE_MAX 7
+/** State for an OR connection: We're done with our SSL handshake, we've done
+ * renegotiation, but we haven't yet negotiated link protocol versions and
+ * sent a netinfo cell. */
+#define OR_CONN_STATE_OR_HANDSHAKING_V2 6
+/** State for an OR connection: We're done with our SSL handshake, but we
+ * haven't yet negotiated link protocol versions, done a V3 handshake, and
+ * sent a netinfo cell. */
+#define OR_CONN_STATE_OR_HANDSHAKING_V3 7
+/** State for an OR connection: Ready to send/receive cells. */
+#define OR_CONN_STATE_OPEN 8
+#define _OR_CONN_STATE_MAX 8
#define _EXIT_CONN_STATE_MIN 1
/** State for an exit connection: waiting for response from DNS farm. */
@@ -386,7 +417,9 @@ typedef enum {
/** A connection to a hidden service directory server: download a v2 rendezvous
* descriptor. */
#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
-#define _DIR_PURPOSE_MAX 18
+/** A connection to a directory server: download a microdescriptor. */
+#define DIR_PURPOSE_FETCH_MICRODESC 19
+#define _DIR_PURPOSE_MAX 19
/** True iff <b>p</b> is a purpose corresponding to uploading data to a
* directory server. */
@@ -792,9 +825,10 @@ typedef enum {
#define CELL_NETINFO 8
#define CELL_RELAY_EARLY 9
-/** True iff the cell command <b>x</b> is one that implies a variable-length
- * cell. */
-#define CELL_COMMAND_IS_VAR_LENGTH(x) ((x) == CELL_VERSIONS)
+#define CELL_VPADDING 128
+#define CELL_CERTS 129
+#define CELL_AUTH_CHALLENGE 130
+#define CELL_AUTHENTICATE 131
/** How long to test reachability before complaining to the user. */
#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
@@ -807,6 +841,9 @@ typedef enum {
* Tor 0.1.2.x is obsolete, we can remove this. */
#define DEFAULT_CLIENT_NICKNAME "client"
+/** Name chosen by routers that don't configure nicknames */
+#define UNNAMED_ROUTER_NICKNAME "Unnamed"
+
/** Number of bytes in a SOCKS4 header. */
#define SOCKS4_NETWORK_LEN 8
@@ -857,7 +894,7 @@ typedef struct var_cell_t {
/** Number of bytes actually stored in <b>payload</b> */
uint16_t payload_len;
/** Payload of this cell */
- uint8_t payload[1];
+ uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
} var_cell_t;
/** A cell as packed for writing to the network. */
@@ -901,14 +938,21 @@ typedef struct {
typedef struct buf_t buf_t;
typedef struct socks_request_t socks_request_t;
+#ifdef USE_BUFFEREVENTS
+#define generic_buffer_t struct evbuffer
+#else
+#define generic_buffer_t buf_t
+#endif
/* Values for connection_t.magic: used to make sure that downcasts (casts from
* connection_t to foo_connection_t) are safe. */
#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
#define OR_CONNECTION_MAGIC 0x7D31FF03u
#define EDGE_CONNECTION_MAGIC 0xF0374013u
+#define ENTRY_CONNECTION_MAGIC 0xbb4a5703
#define DIR_CONNECTION_MAGIC 0x9988ffeeu
#define CONTROL_CONNECTION_MAGIC 0x8abc765du
+#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u
/** Description of a connection to another host or process, and associated
* data.
@@ -974,6 +1018,7 @@ typedef struct connection_t {
/** Our socket; -1 if this connection is closed, or has no socket. */
tor_socket_t s;
int conn_array_index; /**< Index into the global connection array. */
+
struct event *read_event; /**< Libevent event structure. */
struct event *write_event; /**< Libevent event structure. */
buf_t *inbuf; /**< Buffer holding data read over this connection. */
@@ -984,6 +1029,11 @@ typedef struct connection_t {
* read? */
time_t timestamp_lastwritten; /**< When was the last time libevent said we
* could write? */
+
+#ifdef USE_BUFFEREVENTS
+ struct bufferevent *bufev; /**< A Libevent buffered IO structure. */
+#endif
+
time_t timestamp_created; /**< When was this connection_t created? */
/* XXXX_IP6 make this IPv6-capable */
@@ -1008,17 +1058,73 @@ typedef struct connection_t {
/** Unique identifier for this connection on this Tor instance. */
uint64_t global_identifier;
- /* XXXX023 move this field, and all the listener-only fields (just
- socket_family, I think), into a new listener_connection_t subtype. */
+ /** Unique ID for measuring tunneled network status requests. */
+ uint64_t dirreq_id;
+} connection_t;
+
+typedef struct listener_connection_t {
+ connection_t _base;
+
/** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
* to the evdns_server_port it uses to listen to and answer connections. */
struct evdns_server_port *dns_server_port;
- /** Unique ID for measuring tunneled network status requests. */
- uint64_t dirreq_id;
-} connection_t;
+ /** @name Isolation parameters
+ *
+ * For an AP listener, these fields describe how to isolate streams that
+ * arrive on the listener.
+ *
+ * @{
+ */
+ /** The session group for this listener. */
+ int session_group;
+ /** One or more ISO_ flags to describe how to isolate streams. */
+ uint8_t isolation_flags;
+ /**@}*/
+
+} listener_connection_t;
+
+/** Minimum length of the random part of an AUTH_CHALLENGE cell. */
+#define OR_AUTH_CHALLENGE_LEN 32
-/** Stores flags and information related to the portion of a v2 Tor OR
+/**
+ * @name Certificate types for CERTS cells.
+ *
+ * These values are defined by the protocol, and affect how an X509
+ * certificate in a CERTS cell is interpreted and used.
+ *
+ * @{ */
+/** A certificate that authenticates a TLS link key. The subject key
+ * must match the key used in the TLS handshake; it must be signed by
+ * the identity key. */
+#define OR_CERT_TYPE_TLS_LINK 1
+/** A self-signed identity certificate. The subject key must be a
+ * 1024-bit RSA key. */
+#define OR_CERT_TYPE_ID_1024 2
+/** A certificate that authenticates a key used in an AUTHENTICATE cell
+ * in the v3 handshake. The subject key must be a 1024-bit RSA key; it
+ * must be signed by the identity key */
+#define OR_CERT_TYPE_AUTH_1024 3
+/**@}*/
+
+/** The one currently supported type of AUTHENTICATE cell. It contains
+ * a bunch of structures signed with an RSA1024 key. The signed
+ * structures include a HMAC using negotiated TLS secrets, and a digest
+ * of all cells sent or received before the AUTHENTICATE cell (including
+ * the random server-generated AUTH_CHALLENGE cell).
+ */
+#define AUTHTYPE_RSA_SHA256_TLSSECRET 1
+
+/** The length of the part of the AUTHENTICATE cell body that the client and
+ * server can generate independently (when using RSA_SHA256_TLSSECRET). It
+ * contains everything except the client's timestamp, the client's randomly
+ * generated nonce, and the signature. */
+#define V3_AUTH_FIXED_PART_LEN (8+(32*6))
+/** The length of the part of the AUTHENTICATE cell body that the client
+ * signs. */
+#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
+
+/** Stores flags and information related to the portion of a v2/v3 Tor OR
* connection handshake that happens after the TLS handshake is finished.
*/
typedef struct or_handshake_state_t {
@@ -1029,6 +1135,52 @@ typedef struct or_handshake_state_t {
unsigned int started_here : 1;
/** True iff we have received and processed a VERSIONS cell. */
unsigned int received_versions : 1;
+ /** True iff we have received and processed an AUTH_CHALLENGE cell */
+ unsigned int received_auth_challenge : 1;
+ /** True iff we have received and processed a CERTS cell. */
+ unsigned int received_certs_cell : 1;
+ /** True iff we have received and processed an AUTHENTICATE cell */
+ unsigned int received_authenticate : 1;
+
+ /* True iff we've received valid authentication to some identity. */
+ unsigned int authenticated : 1;
+
+ /** True iff we should feed outgoing cells into digest_sent and
+ * digest_received respectively.
+ *
+ * From the server's side of the v3 handshake, we want to capture everything
+ * from the VERSIONS cell through and including the AUTH_CHALLENGE cell.
+ * From the client's, we want to capture everything from the VERSIONS cell
+ * through but *not* including the AUTHENTICATE cell.
+ *
+ * @{ */
+ unsigned int digest_sent_data : 1;
+ unsigned int digest_received_data : 1;
+ /**@}*/
+
+ /** Identity digest that we have received and authenticated for our peer
+ * on this connection. */
+ uint8_t authenticated_peer_id[DIGEST_LEN];
+
+ /** Digests of the cells that we have sent or received as part of a V3
+ * handshake. Used for making and checking AUTHENTICATE cells.
+ *
+ * @{
+ */
+ crypto_digest_env_t *digest_sent;
+ crypto_digest_env_t *digest_received;
+ /** @} */
+
+ /** Certificates that a connection initiator sent us in a CERTS cell; we're
+ * holding on to them until we get an AUTHENTICATE cell.
+ *
+ * @{
+ */
+ /** The cert for the key that's supposed to sign the AUTHENTICATE cell */
+ tor_cert_t *auth_cert;
+ /** A self-signed identity certificate */
+ tor_cert_t *id_cert;
+ /**@}*/
} or_handshake_state_t;
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
@@ -1068,6 +1220,13 @@ typedef struct or_connection_t {
* router itself has a problem.
*/
unsigned int is_bad_for_new_circs:1;
+ /** True iff we have decided that the other end of this connection
+ * is a client. Connections with this flag set should never be used
+ * to satisfy an EXTEND request. */
+ unsigned int is_connection_with_client:1;
+ /** True iff this is an outgoing connection. */
+ unsigned int is_outgoing:1;
+ unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
uint8_t link_proto; /**< What protocol version are we using? 0 for
* "none negotiated yet." */
circid_t next_circ_id; /**< Which circ_id do we try to use next on
@@ -1083,10 +1242,16 @@ typedef struct or_connection_t {
/* bandwidth* and *_bucket only used by ORs in OPEN state: */
int bandwidthrate; /**< Bytes/s added to the bucket. (OPEN ORs only.) */
int bandwidthburst; /**< Max bucket size for this conn. (OPEN ORs only.) */
+#ifndef USE_BUFFEREVENTS
int read_bucket; /**< When this hits 0, stop receiving. Every second we
* add 'bandwidthrate' to this, capping it at
* bandwidthburst. (OPEN ORs only) */
int write_bucket; /**< When this hits 0, stop writing. Like read_bucket. */
+#else
+ /** DOCDOC */
+ /* XXXX we could share this among all connections. */
+ struct ev_token_bucket_cfg *bucket_cfg;
+#endif
int n_circuits; /**< How many circuits use this connection as p_conn or
* n_conn ? */
@@ -1107,29 +1272,31 @@ typedef struct or_connection_t {
unsigned active_circuit_pqueue_last_recalibrated;
struct or_connection_t *next_with_same_id; /**< Next connection with same
* identity digest as this one. */
+
+ tor_libevent_action_t *pending_action;
} or_connection_t;
-/** Subtype of connection_t for an "edge connection" -- that is, a socks (ap)
+/** Subtype of connection_t for an "edge connection" -- that is, an entry (ap)
* connection, or an exit. */
typedef struct edge_connection_t {
connection_t _base;
struct edge_connection_t *next_stream; /**< Points to the next stream at this
* edge, if any */
- struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ
- * this conn exits at. */
int package_window; /**< How many more relay cells can I send into the
* circuit? */
int deliver_window; /**< How many more relay cells can end at me? */
- /** Nickname of planned exit node -- used with .exit support. */
- char *chosen_exit_name;
-
- socks_request_t *socks_request; /**< SOCKS structure describing request (AP
- * only.) */
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
* connection is using. */
+ /** A pointer to which node in the circ this conn exits at. Set for AP
+ * connections and for hidden service exit connections. */
+ struct crypt_path_t *cpath_layer;
+ /** What rendezvous service are we querying for (if an AP) or providing (if
+ * an exit)? */
+ rend_data_t *rend_data;
+
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
* connection. Exit connections only. */
@@ -1145,14 +1312,62 @@ typedef struct edge_connection_t {
/** Bytes written since last call to control_event_stream_bandwidth_used() */
uint32_t n_written;
- /** What rendezvous service are we querying for? (AP only) */
- rend_data_t *rend_data;
+ /** True iff this connection is for a DNS request only. */
+ unsigned int is_dns_request:1;
+
+ unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
+ * connections. Set once we've set the stream end,
+ * and check in connection_about_to_close_connection().
+ */
+ /** True iff we've blocked reading until the circuit has fewer queued
+ * cells. */
+ unsigned int edge_blocked_on_circ:1;
+
+} edge_connection_t;
+
+/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS
+ * connection, a DNS request, a TransPort connection or a NATD connection */
+typedef struct entry_connection_t {
+ edge_connection_t _edge;
+
+ /** Nickname of planned exit node -- used with .exit support. */
+ char *chosen_exit_name;
+
+ socks_request_t *socks_request; /**< SOCKS structure describing request (AP
+ * only.) */
+
+ /* === Isolation related, AP only. === */
+ /** AP only: based on which factors do we isolate this stream? */
+ uint8_t isolation_flags;
+ /** AP only: what session group is this stream in? */
+ int session_group;
+ /** AP only: The newnym epoch in which we created this connection. */
+ unsigned nym_epoch;
+ /** AP only: The original requested address before we rewrote it. */
+ char *original_dest_address;
+ /* Other fields to isolate on already exist. The ClientAddr is addr. The
+ ClientProtocol is a combination of type and socks_request->
+ socks_version. SocksAuth is socks_request->username/password.
+ DestAddr is in socks_request->address. */
/** Number of times we've reassigned this application connection to
* a new circuit. We keep track because the timeout is longer if we've
* already retried several times. */
uint8_t num_socks_retries;
+ /** For AP connections only: buffer for data that we have sent
+ * optimistically, which we might need to re-send if we have to
+ * retry this connection. */
+ generic_buffer_t *pending_optimistic_data;
+ /* For AP connections only: buffer for data that we previously sent
+ * optimistically which we are currently re-sending as we retry this
+ * connection. */
+ generic_buffer_t *sending_optimistic_data;
+
+ /** If this is a DNSPort connection, this field holds the pending DNS
+ * request that we're going to try to answer. */
+ struct evdns_server_request *dns_server_request;
+
#define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10
/** Number of times we've launched a circuit to handle this stream. If
* it gets too high, that could indicate an inconsistency between our
@@ -1160,9 +1375,6 @@ typedef struct edge_connection_t {
* stream to one of the available circuits" logic. */
unsigned int num_circuits_launched:4;
- /** True iff this connection is for a DNS request only. */
- unsigned int is_dns_request:1;
-
/** True iff this stream must attach to a one-hop circuit (e.g. for
* begin_dir). */
unsigned int want_onehop:1;
@@ -1170,13 +1382,6 @@ typedef struct edge_connection_t {
* itself rather than BEGIN (either via onehop or via a whole circuit). */
unsigned int use_begindir:1;
- unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
- * connections. Set once we've set the stream end,
- * and check in connection_about_to_close_connection().
- */
- /** True iff we've blocked reading until the circuit has fewer queued
- * cells. */
- unsigned int edge_blocked_on_circ:1;
/** For AP connections only. If 1, and we fail to reach the chosen exit,
* stop requiring it. */
unsigned int chosen_exit_optional:1;
@@ -1190,19 +1395,26 @@ typedef struct edge_connection_t {
* NATd connection */
unsigned int is_transparent_ap:1;
- /** If this is a DNSPort connection, this field holds the pending DNS
- * request that we're going to try to answer. */
- struct evdns_server_request *dns_server_request;
+ /** For AP connections only: Set if this connection's target exit node
+ * allows optimistic data (that is, data sent on this stream before
+ * the exit has sent a CONNECTED cell) and we have chosen to use it.
+ */
+ unsigned int may_use_optimistic_data : 1;
-} edge_connection_t;
+} entry_connection_t;
/** Subtype of connection_t for an "directory connection" -- that is, an HTTP
* connection to retrieve or serve directory material. */
typedef struct dir_connection_t {
connection_t _base;
- char *requested_resource; /**< Which 'resource' did we ask the directory
- * for? */
+ /** Which 'resource' did we ask the directory for? This is typically the part
+ * of the URL string that defines, relative to the directory conn purpose,
+ * what thing we want. For example, in router descriptor downloads by
+ * descriptor digest, it contains "d/", then one ore more +-separated
+ * fingerprints.
+ **/
+ char *requested_resource;
unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
/* Used only for server sides of some dir connections, to implement
@@ -1262,6 +1474,11 @@ typedef struct control_connection_t {
/** Helper macro: Given a pointer to to._base, of type from*, return &to. */
#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, _base))
+/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
+#define ENTRY_TO_EDGE_CONN(c) (&(((c))->_edge))
+/** Cast a entry_connection_t subtype pointer to a connection_t **/
+#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c)))
+
/** Convert a connection_t* to an or_connection_t*; assert if the cast is
* invalid. */
static or_connection_t *TO_OR_CONN(connection_t *);
@@ -1271,9 +1488,18 @@ static dir_connection_t *TO_DIR_CONN(connection_t *);
/** Convert a connection_t* to an edge_connection_t*; assert if the cast is
* invalid. */
static edge_connection_t *TO_EDGE_CONN(connection_t *);
+/** Convert a connection_t* to an entry_connection_t*; assert if the cast is
+ * invalid. */
+static entry_connection_t *TO_ENTRY_CONN(connection_t *);
+/** Convert a edge_connection_t* to an entry_connection_t*; assert if the cast
+ * is invalid. */
+static entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
/** Convert a connection_t* to an control_connection_t*; assert if the cast is
* invalid. */
static control_connection_t *TO_CONTROL_CONN(connection_t *);
+/** Convert a connection_t* to an listener_connection_t*; assert if the cast is
+ * invalid. */
+static listener_connection_t *TO_LISTENER_CONN(connection_t *);
static INLINE or_connection_t *TO_OR_CONN(connection_t *c)
{
@@ -1287,14 +1513,75 @@ static INLINE dir_connection_t *TO_DIR_CONN(connection_t *c)
}
static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c)
{
- tor_assert(c->magic == EDGE_CONNECTION_MAGIC);
+ tor_assert(c->magic == EDGE_CONNECTION_MAGIC ||
+ c->magic == ENTRY_CONNECTION_MAGIC);
return DOWNCAST(edge_connection_t, c);
}
+static INLINE entry_connection_t *TO_ENTRY_CONN(connection_t *c)
+{
+ tor_assert(c->magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge._base);
+}
+static INLINE entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *c)
+{
+ tor_assert(c->_base.magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge);
+}
static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
{
tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
return DOWNCAST(control_connection_t, c);
}
+static INLINE listener_connection_t *TO_LISTENER_CONN(connection_t *c)
+{
+ tor_assert(c->magic == LISTENER_CONNECTION_MAGIC);
+ return DOWNCAST(listener_connection_t, c);
+}
+
+/* Conditional macros to help write code that works whether bufferevents are
+ disabled or not.
+
+ We can't just write:
+ if (conn->bufev) {
+ do bufferevent stuff;
+ } else {
+ do other stuff;
+ }
+ because the bufferevent stuff won't even compile unless we have a fairly
+ new version of Libevent. Instead, we say:
+ IF_HAS_BUFFEREVENT(conn, { do_bufferevent_stuff } );
+ or:
+ IF_HAS_BUFFEREVENT(conn, {
+ do bufferevent stuff;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ do non-bufferevent stuff;
+ }
+ If we're compiling with bufferevent support, then the macros expand more or
+ less to:
+ if (conn->bufev) {
+ do_bufferevent_stuff;
+ } else {
+ do non-bufferevent stuff;
+ }
+ and if we aren't using bufferevents, they expand more or less to:
+ { do non-bufferevent stuff; }
+*/
+#ifdef USE_BUFFEREVENTS
+#define HAS_BUFFEREVENT(c) (((c)->bufev) != NULL)
+#define IF_HAS_BUFFEREVENT(c, stmt) \
+ if ((c)->bufev) do { \
+ stmt ; \
+ } while (0)
+#define ELSE_IF_NO_BUFFEREVENT ; else
+#define IF_HAS_NO_BUFFEREVENT(c) \
+ if (NULL == (c)->bufev)
+#else
+#define HAS_BUFFEREVENT(c) (0)
+#define IF_HAS_BUFFEREVENT(c, stmt) (void)0
+#define ELSE_IF_NO_BUFFEREVENT ;
+#define IF_HAS_NO_BUFFEREVENT(c) \
+ if (1)
+#endif
/** What action type does an address policy indicate: accept or reject? */
typedef enum {
@@ -1411,11 +1698,6 @@ typedef struct signed_descriptor_t {
* networkstatus that listed it. 0 for "never listed in a consensus or
* status, so far as we know." */
time_t last_listed_as_valid_until;
-#ifdef TRACK_SERVED_TIME
- /** The last time we served anybody this descriptor. Used for internal
- * testing to see whether we're holding on to descriptors too long. */
- time_t last_served_at; /*XXXX remove if not useful. */
-#endif
/* If true, we do not ever try to save this object in the cache. */
unsigned int do_not_cache : 1;
/* If true, this item is meant to represent an extrainfo. */
@@ -1459,59 +1741,49 @@ typedef struct {
char *contact_info; /**< Declared contact info for this router. */
unsigned int is_hibernating:1; /**< Whether the router claims to be
* hibernating */
- unsigned int has_old_dnsworkers:1; /**< Whether the router is using
- * dnsworker code. */
- unsigned int caches_extra_info:1; /**< Whether the router caches and serves
- * extrainfo documents. */
- unsigned int allow_single_hop_exits:1; /**< Whether the router allows
- * single hop exits. */
-
- /* local info */
- unsigned int is_running:1; /**< As far as we know, is this OR currently
- * running? */
- unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
- * (For Authdir: Have we validated this OR?)
- */
- unsigned int is_named:1; /**< Do we believe the nickname that this OR gives
- * us? */
- unsigned int is_fast:1; /** Do we think this is a fast OR? */
- unsigned int is_stable:1; /** Do we think this is a stable OR? */
- unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
- unsigned int is_exit:1; /**< Do we think this is an OK exit? */
- unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
- * or otherwise nasty? */
- unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
- * underpowered, or otherwise useless? */
+ unsigned int caches_extra_info:1; /**< Whether the router says it caches and
+ * serves extrainfo documents. */
+ unsigned int allow_single_hop_exits:1; /**< Whether the router says
+ * it allows single hop exits. */
+
unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
* a hidden service directory. */
- unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
- * directory according to the authorities. */
unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
* router rejects everything. */
/** True if, after we have added this router, we should re-launch
* tests for it. */
unsigned int needs_retest_if_added:1;
-/** Tor can use this router for general positions in circuits. */
+/** Tor can use this router for general positions in circuits; we got it
+ * from a directory server as usual, or we're an authority and a server
+ * uploaded it. */
#define ROUTER_PURPOSE_GENERAL 0
-/** Tor should avoid using this router for circuit-building. */
+/** Tor should avoid using this router for circuit-building: we got it
+ * from a crontroller. If the controller wants to use it, it'll have to
+ * ask for it by identity. */
#define ROUTER_PURPOSE_CONTROLLER 1
-/** Tor should use this router only for bridge positions in circuits. */
+/** Tor should use this router only for bridge positions in circuits: we got
+ * it via a directory request from the bridge itself, or a bridge
+ * authority. x*/
#define ROUTER_PURPOSE_BRIDGE 2
/** Tor should not use this router; it was marked in cached-descriptors with
* a purpose we didn't recognize. */
#define ROUTER_PURPOSE_UNKNOWN 255
- uint8_t purpose; /** What positions in a circuit is this router good for? */
+ /* In what way did we find out about this router? One of ROUTER_PURPOSE_*.
+ * Routers of different purposes are kept segregated and used for different
+ * things; see notes on ROUTER_PURPOSE_* macros above.
+ */
+ uint8_t purpose;
/* The below items are used only by authdirservers for
* reachability testing. */
+
/** When was the last time we could reach this OR? */
time_t last_reachable;
/** When did we start testing reachability for this OR? */
time_t testing_since;
- /** According to the geoip db what country is this router in? */
- country_t country;
+
} routerinfo_t;
/** Information needed to keep and cache a signed extra-info document. */
@@ -1537,8 +1809,9 @@ typedef struct routerstatus_t {
* has. */
char identity_digest[DIGEST_LEN]; /**< Digest of the router's identity
* key. */
- char descriptor_digest[DIGEST_LEN]; /**< Digest of the router's most recent
- * descriptor. */
+ /** Digest of the router's most recent descriptor or microdescriptor.
+ * If it's a descriptor, we only use the first DIGEST_LEN bytes. */
+ char descriptor_digest[DIGEST256_LEN];
uint32_t addr; /**< IPv4 address for this router. */
uint16_t or_port; /**< OR port for this router. */
uint16_t dir_port; /**< Directory port for this router. */
@@ -1546,7 +1819,11 @@ typedef struct routerstatus_t {
unsigned int is_exit:1; /**< True iff this router is a good exit. */
unsigned int is_stable:1; /**< True iff this router stays up a long time. */
unsigned int is_fast:1; /**< True iff this router has good bandwidth. */
- unsigned int is_running:1; /**< True iff this router is up. */
+ /** True iff this router is called 'running' in the consensus. We give it
+ * this funny name so that we don't accidentally use this bit as a view of
+ * whether we think the router is *currently* running. If that's what you
+ * want to know, look at is_running in node_t. */
+ unsigned int is_flagged_running:1;
unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */
unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
* router. */
@@ -1577,6 +1854,12 @@ typedef struct routerstatus_t {
/** True iff this router is a version that, if it caches directory info,
* we can get v3 downloads from. */
unsigned int version_supports_v3_dir:1;
+ /** True iff this router is a version that, if it caches directory info,
+ * we can get microdescriptors from. */
+ unsigned int version_supports_microdesc_cache:1;
+ /** True iff this router is a version that allows DATA cells to arrive on
+ * a stream before it has sent a CONNECTED cell. */
+ unsigned int version_supports_optimistic_data:1;
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
@@ -1598,15 +1881,31 @@ typedef struct routerstatus_t {
* from this authority.) Applies in v2 networkstatus document only.
*/
unsigned int need_to_mirror:1;
- unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
- * to this (unnamed) router by nickname?
- */
time_t last_dir_503_at; /**< When did this router last tell us that it
* was too busy to serve directory info? */
download_status_t dl_status;
} routerstatus_t;
+/** A single entry in a parsed policy summary, describing a range of ports. */
+typedef struct short_policy_entry_t {
+ uint16_t min_port, max_port;
+} short_policy_entry_t;
+
+/** A short_poliy_t is the parsed version of a policy summary. */
+typedef struct short_policy_t {
+ /** True if the members of 'entries' are port ranges to accept; false if
+ * they are port ranges to reject */
+ unsigned int is_accept : 1;
+ /** The actual number of values in 'entries'. */
+ unsigned int n_entries : 31;
+ /** An array of 0 or more short_policy_entry_t values, each describing a
+ * range of ports that this policy accepts or rejects (depending on the
+ * value of is_accept).
+ */
+ short_policy_entry_t entries[FLEXIBLE_ARRAY_MEMBER];
+} short_policy_t;
+
/** A microdescriptor is the smallest amount of information needed to build a
* circuit through a router. They are generated by the directory authorities,
* using information from the uploaded routerinfo documents. They are not
@@ -1626,6 +1925,11 @@ typedef struct microdesc_t {
saved_location_t saved_location : 3;
/** If true, do not attempt to cache this microdescriptor on disk. */
unsigned int no_save : 1;
+ /** If true, this microdesc has an entry in the microdesc_map */
+ unsigned int held_in_map : 1;
+ /** Reference count: how many node_ts have a reference to this microdesc? */
+ unsigned int held_by_nodes;
+
/** If saved_location == SAVED_IN_CACHE, this field holds the offset of the
* microdescriptor in the cache. */
off_t off;
@@ -1648,15 +1952,83 @@ typedef struct microdesc_t {
crypto_pk_env_t *onion_pkey;
/** As routerinfo_t.family */
smartlist_t *family;
- /** Encoded exit policy summary */
- char *exitsummary; /**< exit policy summary -
- * XXX this probably should not stay a string. */
+ /** Exit policy summary */
+ short_policy_t *exit_policy;
} microdesc_t;
+/** A node_t represents a Tor router.
+ *
+ * Specifically, a node_t is a Tor router as we are using it: a router that
+ * we are considering for circuits, connections, and so on. A node_t is a
+ * thin wrapper around the routerstatus, routerinfo, and microdesc for a
+ * single wrapper, and provides a consistent interface for all of them.
+ *
+ * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
+ * and a microdesc have[*] only the information read from a router
+ * descriptor, a consensus entry, and a microdescriptor (respectively)...
+ * a node_t has flags based on *our own current opinion* of the node.
+ *
+ * [*] Actually, there is some leftover information in each that is mutable.
+ * We should try to excise that.
+ */
+typedef struct node_t {
+ /* Indexing information */
+
+ /** Used to look up the node_t by its identity digest. */
+ HT_ENTRY(node_t) ht_ent;
+ /** Position of the node within the list of nodes */
+ int nodelist_idx;
+
+ /** The identity digest of this node_t. No more than one node_t per
+ * identity may exist at a time. */
+ char identity[DIGEST_LEN];
+
+ microdesc_t *md;
+ routerinfo_t *ri;
+ routerstatus_t *rs;
+
+ /* local info: copied from routerstatus, then possibly frobbed based
+ * on experience. Authorities set this stuff directly. */
+
+ unsigned int is_running:1; /**< As far as we know, is this OR currently
+ * running? */
+ unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
+ * (For Authdir: Have we validated this OR?)
+ */
+ unsigned int is_fast:1; /** Do we think this is a fast OR? */
+ unsigned int is_stable:1; /** Do we think this is a stable OR? */
+ unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
+ unsigned int is_exit:1; /**< Do we think this is an OK exit? */
+ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
+ * or otherwise nasty? */
+ unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
+ * underpowered, or otherwise useless? */
+ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
+ * directory according to the authorities. */
+
+ /* Local info: warning state. */
+
+ unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
+ * to this (unnamed) router by nickname?
+ */
+
+ /** Local info: we treat this node as if it rejects everything */
+ unsigned int rejects_all:1;
+
+ /* Local info: derived. */
+
+ /** According to the geoip db what country is this router in? */
+ country_t country;
+} node_t;
+
/** How many times will we try to download a router's descriptor before giving
* up? */
#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
+/** How many times will we try to download a microdescriptor before giving
+ * up? */
+#define MAX_MICRODESC_DOWNLOAD_FAILURES 8
+
/** Contents of a v2 (non-consensus, non-vote) network status object. */
typedef struct networkstatus_v2_t {
/** When did we receive the network-status document? */
@@ -1770,9 +2142,6 @@ typedef enum {
FLAV_MICRODESC = 1,
} consensus_flavor_t;
-/** Which consensus flavor do we actually want to use to build circuits? */
-#define USABLE_CONSENSUS_FLAVOR FLAV_NS
-
/** How many different consensus flavors are there? */
#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
@@ -1942,24 +2311,33 @@ typedef struct authority_cert_t {
uint8_t is_cross_certified;
} authority_cert_t;
-/** Bitfield enum type listing types of directory authority/directory
- * server. */
+/** Bitfield enum type listing types of information that directory authorities
+ * can be authoritative about, and that directory caches may or may not cache.
+ *
+ * Note that the granularity here is based on authority granularity and on
+ * cache capabilities. Thus, one particular bit may correspond in practice to
+ * a few types of directory info, so long as every authority that pronounces
+ * officially about one of the types prounounces officially about all of them,
+ * and so long as every cache that caches one of them caches all of them.
+ */
typedef enum {
- NO_AUTHORITY = 0,
+ NO_DIRINFO = 0,
/** Serves/signs v1 directory information: Big lists of routers, and short
* routerstatus documents. */
- V1_AUTHORITY = 1 << 0,
+ V1_DIRINFO = 1 << 0,
/** Serves/signs v2 directory information: i.e. v2 networkstatus documents */
- V2_AUTHORITY = 1 << 1,
+ V2_DIRINFO = 1 << 1,
/** Serves/signs v3 directory information: votes, consensuses, certs */
- V3_AUTHORITY = 1 << 2,
+ V3_DIRINFO = 1 << 2,
/** Serves hidden service descriptors. */
- HIDSERV_AUTHORITY = 1 << 3,
+ HIDSERV_DIRINFO = 1 << 3,
/** Serves bridge descriptors. */
- BRIDGE_AUTHORITY = 1 << 4,
- /** Serves extrainfo documents. (XXX Not precisely an authority type)*/
- EXTRAINFO_CACHE = 1 << 5,
-} authority_type_t;
+ BRIDGE_DIRINFO = 1 << 4,
+ /** Serves extrainfo documents. */
+ EXTRAINFO_DIRINFO=1 << 5,
+ /** Serves microdescriptors. */
+ MICRODESC_DIRINFO=1 << 6,
+} dirinfo_type_t;
#define CRYPT_PATH_MAGIC 0x70127012u
@@ -2032,15 +2410,15 @@ typedef struct {
/** How to extend to the planned exit node. */
extend_info_t *chosen_exit;
/** Whether every node in the circ must have adequate uptime. */
- int need_uptime;
+ unsigned int need_uptime : 1;
/** Whether every node in the circ must have adequate capacity. */
- int need_capacity;
+ unsigned int need_capacity : 1;
/** Whether the last hop was picked with exiting in mind. */
- int is_internal;
- /** Did we pick this as a one-hop tunnel (not safe for other conns)?
- * These are for encrypted connections that exit to this router, not
+ unsigned int is_internal : 1;
+ /** Did we pick this as a one-hop tunnel (not safe for other streams)?
+ * These are for encrypted dir conns that exit to this router, not
* for arbitrary exits from the circuit. */
- int onehop_tunnel;
+ unsigned int onehop_tunnel : 1;
/** The crypt_path_t to append after rendezvous: used for rendezvous. */
crypt_path_t *pending_final_cpath;
/** How many times has building a circuit for this task failed? */
@@ -2138,7 +2516,10 @@ typedef struct circuit_t {
* length ONIONSKIN_CHALLENGE_LEN. */
char *n_conn_onionskin;
- struct timeval timestamp_created; /**< When was the circuit created? */
+ /** When was this circuit created? We keep this timestamp with a higher
+ * resolution than most so that the circuit-build-time tracking code can
+ * get millisecond resolution. */
+ struct timeval timestamp_created;
/** When the circuit was first used, or 0 if the circuit is clean.
*
* XXXX023 Note that some code will artifically adjust this value backward
@@ -2236,6 +2617,55 @@ typedef struct origin_circuit_t {
/* XXXX NM This can get re-used after 2**32 circuits. */
uint32_t global_identifier;
+ /** True if we have associated one stream to this circuit, thereby setting
+ * the isolation paramaters for this circuit. Note that this doesn't
+ * necessarily mean that we've <em>attached</em> any streams to the circuit:
+ * we may only have marked up this circuit during the launch process.
+ */
+ unsigned int isolation_values_set : 1;
+ /** True iff any stream has <em>ever</em> been attached to this circuit.
+ *
+ * In a better world we could use timestamp_dirty for this, but
+ * timestamp_dirty is far too overloaded at the moment.
+ */
+ unsigned int isolation_any_streams_attached : 1;
+
+ /** A bitfield of ISO_* flags for every isolation field such that this
+ * circuit has had streams with more than one value for that field
+ * attached to it. */
+ uint8_t isolation_flags_mixed;
+
+ /** @name Isolation parameters
+ *
+ * If any streams have been associated with this circ (isolation_values_set
+ * == 1), and all streams associated with the circuit have had the same
+ * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
+ * elements hold the value for that field.
+ *
+ * Note again that "associated" is not the same as "attached": we
+ * preliminarily associate streams with a circuit while the circuit is being
+ * launched, so that we can tell whether we need to launch more circuits.
+ *
+ * @{
+ */
+ uint8_t client_proto_type;
+ uint8_t client_proto_socksver;
+ uint16_t dest_port;
+ tor_addr_t client_addr;
+ char *dest_address;
+ int session_group;
+ unsigned nym_epoch;
+ size_t socks_username_len;
+ uint8_t socks_password_len;
+ /* Note that the next two values are NOT NUL-terminated; see
+ socks_username_len and socks_password_len for their lengths. */
+ char *socks_username;
+ char *socks_password;
+ /** Global identifier for the first stream attached here; used by
+ * ISO_STREAM. */
+ uint64_t associated_isolated_stream_global_id;
+ /**@}*/
+
} origin_circuit_t;
/** An or_circuit_t holds information needed to implement a circuit at an
@@ -2354,11 +2784,79 @@ typedef enum invalid_router_usage_t {
#define MIN_CONSTRAINED_TCP_BUFFER 2048
#define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */
+/** @name Isolation flags
+
+ Ways to isolate client streams
+
+ @{
+*/
+/** Isolate based on destination port */
+#define ISO_DESTPORT (1u<<0)
+/** Isolate based on destination address */
+#define ISO_DESTADDR (1u<<1)
+/** Isolate based on SOCKS authentication */
+#define ISO_SOCKSAUTH (1u<<2)
+/** Isolate based on client protocol choice */
+#define ISO_CLIENTPROTO (1u<<3)
+/** Isolate based on client address */
+#define ISO_CLIENTADDR (1u<<4)
+/** Isolate based on session group (always on). */
+#define ISO_SESSIONGRP (1u<<5)
+/** Isolate based on newnym epoch (always on). */
+#define ISO_NYM_EPOCH (1u<<6)
+/** Isolate all streams (Internal only). */
+#define ISO_STREAM (1u<<7)
+/**@}*/
+
+/** Default isolation level for ports. */
+#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH)
+
+/** Indicates that we haven't yet set a session group on a port_cfg_t. */
+#define SESSION_GROUP_UNSET -1
+/** Session group reserved for directory connections */
+#define SESSION_GROUP_DIRCONN -2
+/** Session group reserved for resolve requests launched by a controller */
+#define SESSION_GROUP_CONTROL_RESOLVE -3
+/** First automatically allocated session group number */
+#define SESSION_GROUP_FIRST_AUTO -4
+
+/** Configuration for a single port that we're listening on. */
+typedef struct port_cfg_t {
+ tor_addr_t addr; /**< The actual IP to listen on, if !is_unix_addr. */
+ int port; /**< The configured port, or CFG_AUTO_PORT to tell Tor to pick its
+ * own port. */
+ uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
+ unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
+
+ /* Client port types (socks, dns, trans, natd) only: */
+ uint8_t isolation_flags; /**< Zero or more isolation flags */
+ int session_group; /**< A session group, or -1 if this port is not in a
+ * session group. */
+
+ /* Unix sockets only: */
+ /** Path for an AF_UNIX address */
+ char unix_addr[FLEXIBLE_ARRAY_MEMBER];
+} port_cfg_t;
+
+/** Ordinary configuration line. */
+#define CONFIG_LINE_NORMAL 0
+/** Appends to previous configuration for the same option, even if we
+ * would ordinary replace it. */
+#define CONFIG_LINE_APPEND 1
+/* Removes all previous configuration for an option. */
+#define CONFIG_LINE_CLEAR 2
+
/** A linked list of lines in a config file. */
typedef struct config_line_t {
char *key;
char *value;
struct config_line_t *next;
+ /** What special treatment (if any) does this line require? */
+ unsigned int command:2;
+ /** If true, subsequent assignments to this linelist should replace
+ * it, not extend it. Set only on the first item in a linelist in an
+ * or_options_t. */
+ unsigned int fragile:1;
} config_line_t;
typedef struct routerset_t routerset_t;
@@ -2380,6 +2878,7 @@ typedef struct {
config_line_t *Logs; /**< New-style list of configuration lines
* for logs */
+ int LogTimeGranularity; /**< Log resolution in milliseconds. */
int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
* each log message occurs? */
@@ -2390,6 +2889,8 @@ typedef struct {
char *Address; /**< OR only: configured address for this onion router. */
char *PidFile; /**< Where to store PID of Tor process. */
+ int DynamicDHGroups; /**< Dynamic generation of prime moduli for use in DH.*/
+
routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
* country codes and IP address patterns of ORs to
* consider as exits. */
@@ -2448,16 +2949,17 @@ typedef struct {
char *User; /**< Name of user to run Tor as. */
char *Group; /**< Name of group to run Tor as. */
int ORPort; /**< Port to listen on for OR connections. */
- int SocksPort; /**< Port to listen on for SOCKS connections. */
- /** Port to listen on for transparent pf/netfilter connections. */
- int TransPort;
- int NATDPort; /**< Port to listen on for transparent natd connections. */
+ config_line_t *SocksPort; /**< Ports to listen on for SOCKS connections. */
+ /** Ports to listen on for transparent pf/netfilter connections. */
+ config_line_t *TransPort;
+ config_line_t *NATDPort; /**< Ports to listen on for transparent natd
+ * connections. */
int ControlPort; /**< Port to listen on for control connections. */
config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on
* for control connections. */
int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
int DirPort; /**< Port to listen on for directory connections. */
- int DNSPort; /**< Port to listen on for DNS requests. */
+ config_line_t *DNSPort; /**< Port to listen on for DNS requests. */
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory
@@ -2485,6 +2987,12 @@ typedef struct {
int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
config_line_t *Bridges; /**< List of bootstrap bridge addresses. */
+ config_line_t *ClientTransportPlugin; /**< List of client
+ transport plugins. */
+
+ config_line_t *ServerTransportPlugin; /**< List of client
+ transport plugins. */
+
int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
* this explicit so we can change how we behave in the
* future. */
@@ -2499,8 +3007,8 @@ typedef struct {
/** To what authority types do we publish our descriptor? Choices are
* "v1", "v2", "v3", "bridge", or "". */
smartlist_t *PublishServerDescriptor;
- /** An authority type, derived from PublishServerDescriptor. */
- authority_type_t _PublishServerDescriptor;
+ /** A bitfield of authority types, derived from PublishServerDescriptor. */
+ dirinfo_type_t _PublishServerDescriptor;
/** Boolean: do we publish hidden service descriptors to the HS auths? */
int PublishHidServDescriptors;
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
@@ -2532,12 +3040,10 @@ typedef struct {
uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */
/** Whether we should drop exit streams from Tors that we don't know are
- * relays. One of "0" (never refuse), "1" (always refuse), or "auto" (do
+ * relays. One of "0" (never refuse), "1" (always refuse), or "-1" (do
* what the consensus says, defaulting to 'refuse' if the consensus says
* nothing). */
- char *RefuseUnknownExits;
- /** Parsed version of RefuseUnknownExits. -1 for auto. */
- int RefuseUnknownExits_;
+ int RefuseUnknownExits;
/** Application ports that require all nodes in circ to have sufficient
* uptime. */
@@ -2608,6 +3114,9 @@ typedef struct {
* authorizations for hidden services */
char *ContactInfo; /**< Contact info to be published in the directory. */
+ int HeartbeatPeriod; /**< Log heartbeat messages after this many seconds
+ * have passed. */
+
char *HTTPProxy; /**< hostname[:port] to use as http proxy, if any. */
tor_addr_t HTTPProxyAddr; /**< Parsed IPv4 addr for http proxy, if any. */
uint16_t HTTPProxyPort; /**< Parsed port for http proxy, if any. */
@@ -2645,7 +3154,8 @@ typedef struct {
char *MyFamily; /**< Declared family for this OR. */
config_line_t *NodeFamilies; /**< List of config lines for
- * node families */
+ * node families */
+ smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */
config_line_t *AuthDirBadDir; /**< Address policy for descriptors to
* mark as bad dir mirrors. */
config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
@@ -2666,6 +3176,18 @@ typedef struct {
* number of servers per IP address shared
* with an authority. */
+ /** Should we assign the Guard flag to relays which would allow
+ * exploitation of CVE-2011-2768 against their clients? */
+ int GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays;
+
+ /** If non-zero, always vote the Fast flag for any relay advertising
+ * this amount of capacity or more. */
+ uint64_t AuthDirFastGuarantee;
+
+ /** If non-zero, this advertised capacity or more is always sufficient
+ * to satisfy the bandwidth requirement for the Guard flag. */
+ uint64_t AuthDirGuardBWGuarantee;
+
char *AccountingStart; /**< How long is the accounting interval, and when
* does it start? */
uint64_t AccountingMax; /**< How many bytes do we allow per accounting
@@ -2711,6 +3233,8 @@ typedef struct {
* log whether it was DNS-leaking or not? */
int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
* acceleration where available? */
+ /** Token Bucket Refill resolution in milliseconds. */
+ int TokenBucketRefillInterval;
char *AccelName; /**< Optional hardware acceleration engine name. */
char *AccelDir; /**< Optional hardware acceleration engine search dir. */
int UseEntryGuards; /**< Boolean: Do we try to enter from a smallish number
@@ -2742,10 +3266,14 @@ typedef struct {
disclaimer. This allows a server administrator to show
that they're running Tor and anyone visiting their server
will know this without any specialized knowledge. */
+ int DisableDebuggerAttachment; /**< Currently Linux only specific attempt to
+ disable ptrace; needs BSD testing. */
/** Boolean: if set, we start even if our resolv.conf file is missing
* or broken. */
int ServerDNSAllowBrokenConfig;
-
+ /** Boolean: if set, then even connections to private addresses will get
+ * rate-limited. */
+ int CountPrivateBandwidth;
smartlist_t *ServerDNSTestAddresses; /**< A list of addresses that definitely
* should be resolvable. Used for
* testing our DNS server. */
@@ -2755,6 +3283,10 @@ typedef struct {
* possible. */
int PreferTunneledDirConns; /**< If true, avoid dirservers that don't
* support BEGIN_DIR, when possible. */
+ int PortForwarding; /**< If true, use NAT-PMP or UPnP to automatically
+ * forward the DirPort and ORPort on the NAT device */
+ char *PortForwardingHelper; /** < Filename or full path of the port
+ forwarding helper executable */
int AllowNonRFC953Hostnames; /**< If true, we allow connections to hostnames
* with weird characters. */
/** If true, we try resolving hostnames with weird characters. */
@@ -2792,6 +3324,9 @@ typedef struct {
/** If true, the user wants us to collect statistics on port usage. */
int ExitPortStatistics;
+ /** If true, the user wants us to collect connection statistics. */
+ int ConnDirectionStatistics;
+
/** If true, the user wants us to collect cell statistics. */
int CellStatistics;
@@ -2888,16 +3423,44 @@ typedef struct {
*/
double CircuitPriorityHalflife;
+ /** If true, do not enable IOCP on windows with bufferevents, even if
+ * we think we could. */
+ int DisableIOCP;
+ /** For testing only: will go away in 0.2.3.x. */
+ int _UseFilteringSSLBufferevents;
+
/** Set to true if the TestingTorNetwork configuration option is set.
* This is used so that options_validate() has a chance to realize that
* the defaults have changed. */
int _UsingTestNetworkDefaults;
+ /** If 1, we try to use microdescriptors to build circuits. If 0, we don't.
+ * If -1, Tor decides. */
+ int UseMicrodescriptors;
+
/** File where we should write the ControlPort. */
char *ControlPortWriteToFile;
/** Should that file be group-readable? */
int ControlPortFileGroupReadable;
+#define MAX_MAX_CLIENT_CIRCUITS_PENDING 1024
+ /** Maximum number of non-open general-purpose origin circuits to allow at
+ * once. */
+ int MaxClientCircuitsPending;
+
+ /** If 1, we always send optimistic data when it's supported. If 0, we
+ * never use it. If -1, we do what the consensus says. */
+ int OptimisticData;
+
+ /** If 1, and we are using IOCP, we set the kernel socket SNDBUF and RCVBUF
+ * to 0 to try to save kernel memory and avoid the dread "Out of buffers"
+ * issue. */
+ int UserspaceIOCPBuffers;
+
+ /** If 1, we accept and launch no external network connections, except on
+ * control ports. */
+ int DisableNetwork;
+
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
@@ -2924,6 +3487,8 @@ typedef struct {
/** A list of Entry Guard-related configuration lines. */
config_line_t *EntryGuards;
+ config_line_t *TransportProxies;
+
/** These fields hold information on the history of bandwidth usage for
* servers. The "Ends" fields hold the time when we last updated the
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
@@ -2976,6 +3541,8 @@ static INLINE void or_state_mark_dirty(or_state_t *state, time_t when)
#define MAX_SOCKS_REPLY_LEN 1024
#define MAX_SOCKS_ADDR_LEN 256
+#define SOCKS_NO_AUTH 0x00
+#define SOCKS_USER_PASS 0x02
/** Please open a TCP connection to this addr:port. */
#define SOCKS_COMMAND_CONNECT 0x01
@@ -2995,10 +3562,17 @@ struct socks_request_t {
/** Which version of SOCKS did the client use? One of "0, 4, 5" -- where
* 0 means that no socks handshake ever took place, and this is just a
* stub connection (e.g. see connection_ap_make_link()). */
- char socks_version;
- int command; /**< What is this stream's goal? One from the above list. */
+ uint8_t socks_version;
+ /** If using socks5 authentication, which authentication type did we
+ * negotiate? currently we support 0 (no authentication) and 2
+ * (username/password). */
+ uint8_t auth_type;
+ /** What is this stream's goal? One of the SOCKS_COMMAND_* values */
+ uint8_t command;
+ /** Which kind of listener created this stream? */
+ uint8_t listener_type;
size_t replylen; /**< Length of <b>reply</b>. */
- char reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
+ uint8_t reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
* we want to specify our own socks reply,
* rather than using the default socks4 or
* socks5 socks reply. We use this for the
@@ -3010,10 +3584,21 @@ struct socks_request_t {
unsigned int has_finished : 1; /**< Has the SOCKS handshake finished? Used to
* make sure we send back a socks reply for
* every connection. */
+ unsigned int got_auth : 1; /**< Have we received any authentication data? */
+
+ /** Number of bytes in username; 0 if username is NULL */
+ size_t usernamelen;
+ /** Number of bytes in password; 0 if password is NULL */
+ uint8_t passwordlen;
+ /** The negotiated username value if any (for socks5), or the entire
+ * authentication string (for socks4). This value is NOT nul-terminated;
+ * see usernamelen for its length. */
+ char *username;
+ /** The negotiated password value if any (for socks5). This value is NOT
+ * nul-terminated; see passwordlen for its length. */
+ char *password;
};
-/* all the function prototypes go here */
-
/********************************* circuitbuild.c **********************/
/** How many hops does a general-purpose circuit have by default? */
@@ -3426,7 +4011,7 @@ typedef enum {
ADDR_POLICY_PROBABLY_ACCEPTED=1,
/** Part of the address was unknown, but as far as we can tell, it was
* rejected. */
- ADDR_POLICY_PROBABLY_REJECTED=2
+ ADDR_POLICY_PROBABLY_REJECTED=2,
} addr_policy_result_t;
/********************************* rephist.c ***************************/
@@ -3582,7 +4167,7 @@ typedef struct trusted_dir_server_t {
unsigned int has_accepted_serverdesc:1;
/** What kind of authority is this? (Bitfield.) */
- authority_type_t type;
+ dirinfo_type_t type;
download_status_t v2_ns_dl_status; /**< Status of downloading this server's
* v2 network status. */
@@ -3628,6 +4213,8 @@ typedef struct trusted_dir_server_t {
* fetches to _any_ single directory server.]
*/
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
+#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
+
#define _PDS_PREFER_TUNNELED_DIR_CONNS (1<<16)
/** Possible ways to weight routers when choosing one randomly. See
@@ -3645,7 +4232,8 @@ typedef enum {
CRN_NEED_GUARD = 1<<2,
CRN_ALLOW_INVALID = 1<<3,
/* XXXX not used, apparently. */
- CRN_WEIGHT_AS_EXIT = 1<<5
+ CRN_WEIGHT_AS_EXIT = 1<<5,
+ CRN_NEED_DESC = 1<<6
} router_crn_flags_t;
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
diff --git a/src/or/policies.c b/src/or/policies.c
index c87036013d..40e5277478 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "config.h"
#include "dirserv.h"
+#include "nodelist.h"
#include "policies.h"
#include "routerparse.h"
#include "ht.h"
@@ -82,15 +83,15 @@ policy_expand_private(smartlist_t **policy)
continue;
}
for (i = 0; private_nets[i]; ++i) {
- addr_policy_t policy;
- memcpy(&policy, p, sizeof(addr_policy_t));
- policy.is_private = 0;
- policy.is_canonical = 0;
- if (tor_addr_parse_mask_ports(private_nets[i], &policy.addr,
- &policy.maskbits, &port_min, &port_max)<0) {
+ addr_policy_t newpolicy;
+ memcpy(&newpolicy, p, sizeof(addr_policy_t));
+ newpolicy.is_private = 0;
+ newpolicy.is_canonical = 0;
+ if (tor_addr_parse_mask_ports(private_nets[i], &newpolicy.addr,
+ &newpolicy.maskbits, &port_min, &port_max)<0) {
tor_assert(0);
}
- smartlist_add(tmp, addr_policy_get_canonical_entry(&policy));
+ smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy));
}
addr_policy_free(p);
});
@@ -163,7 +164,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
static int
parse_reachable_addresses(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int ret = 0;
if (options->ReachableDirAddresses &&
@@ -261,7 +262,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port)
/** Return true iff we think our firewall will let us make an OR connection to
* <b>ri</b>. */
int
-fascist_firewall_allows_or(routerinfo_t *ri)
+fascist_firewall_allows_or(const routerinfo_t *ri)
{
/* XXXX proposal 118 */
tor_addr_t addr;
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(routerinfo_t *ri)
return fascist_firewall_allows_address_or(&addr, ri->or_port);
}
+/** Return true iff we think our firewall will let us make an OR connection to
+ * <b>node</b>. */
+int
+fascist_firewall_allows_node(const node_t *node)
+{
+ if (node->ri) {
+ return fascist_firewall_allows_or(node->ri);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+ } else {
+ return 1;
+ }
+}
+
/** Return true iff we think our firewall will let us make a directory
* connection to addr:port. */
int
@@ -339,7 +356,7 @@ authdir_policy_badexit_address(uint32_t addr, uint16_t port)
* options in <b>options</b>, return -1 and set <b>msg</b> to a newly
* allocated description of the error. Else return 0. */
int
-validate_addr_policies(or_options_t *options, char **msg)
+validate_addr_policies(const or_options_t *options, char **msg)
{
/* XXXX Maybe merge this into parse_policies_from_options, to make sure
* that the two can't go out of sync. */
@@ -423,7 +440,7 @@ load_policy_from_option(config_line_t *config, smartlist_t **policy,
/** Set all policies based on <b>options</b>, which should have been validated
* first by validate_addr_policies. */
int
-policies_parse_from_options(or_options_t *options)
+policies_parse_from_options(const or_options_t *options)
{
int ret = 0;
if (load_policy_from_option(options->SocksPolicy, &socks_policy, -1) < 0)
@@ -553,18 +570,6 @@ addr_policy_get_canonical_entry(addr_policy_t *e)
return found->policy;
}
-/** As compare_tor_addr_to_addr_policy, but instead of a tor_addr_t, takes
- * in host order. */
-addr_policy_result_t
-compare_addr_to_addr_policy(uint32_t addr, uint16_t port,
- const smartlist_t *policy)
-{
- /*XXXX deprecate this function when possible. */
- tor_addr_t a;
- tor_addr_from_ipv4h(&a, addr);
- return compare_tor_addr_to_addr_policy(&a, port, policy);
-}
-
/** Helper for compare_tor_addr_to_addr_policy. Implements the case where
* addr and port are both known. */
static addr_policy_result_t
@@ -684,7 +689,7 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port,
if (!policy) {
/* no policy? accept all. */
return ADDR_POLICY_ACCEPTED;
- } else if (tor_addr_is_null(addr)) {
+ } else if (addr == NULL || tor_addr_is_null(addr)) {
tor_assert(port != 0);
return compare_unknown_tor_addr_to_addr_policy(port, policy);
} else if (port == 0) {
@@ -866,15 +871,11 @@ policies_exit_policy_append_reject_star(smartlist_t **dest)
append_exit_policy_string(dest, "reject *:*");
}
-/** Replace the exit policy of <b>r</b> with reject *:*. */
+/** Replace the exit policy of <b>node</b> with reject *:* */
void
-policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
+policies_set_node_exitpolicy_to_reject_all(node_t *node)
{
- addr_policy_t *item;
- addr_policy_list_free(r->exit_policy);
- r->exit_policy = smartlist_create();
- item = router_parse_addr_policy_item_from_string("reject *:*", -1);
- smartlist_add(r->exit_policy, item);
+ node->rejects_all = 1;
}
/** Return 1 if there is at least one /8 subnet in <b>policy</b> that
@@ -1085,7 +1086,7 @@ policy_summary_split(smartlist_t *summary,
int start_at_index;
int i = 0;
- /* XXXX Do a binary search if run time matters */
+
while (AT(i)->prt_max < prt_min)
i++;
if (AT(i)->prt_min != prt_min) {
@@ -1298,6 +1299,186 @@ policy_summarize(smartlist_t *policy)
return result;
}
+/** Convert a summarized policy string into a short_policy_t. Return NULL
+ * if the string is not well-formed. */
+short_policy_t *
+parse_short_policy(const char *summary)
+{
+ const char *orig_summary = summary;
+ short_policy_t *result;
+ int is_accept;
+ int n_entries;
+ short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */
+ const char *next;
+
+ if (!strcmpstart(summary, "accept ")) {
+ is_accept = 1;
+ summary += strlen("accept ");
+ } else if (!strcmpstart(summary, "reject ")) {
+ is_accept = 0;
+ summary += strlen("reject ");
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword");
+ return NULL;
+ }
+
+ n_entries = 0;
+ for ( ; *summary; summary = next) {
+ const char *comma = strchr(summary, ',');
+ unsigned low, high;
+ char dummy;
+ char ent_buf[32];
+
+ next = comma ? comma+1 : strchr(summary, '\0');
+
+ if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) {
+ /* unrecognized entry format. skip it. */
+ continue;
+ }
+ if (next-summary < 2) {
+ /* empty; skip it. */
+ continue;
+ }
+
+ memcpy(ent_buf, summary, next-summary-1);
+ ent_buf[next-summary-1] = '\0';
+
+ if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) {
+ if (low<1 || low>65535 || high<1 || high>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ } else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) {
+ if (low<1 || low>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ high = low;
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ entries[n_entries].min_port = low;
+ entries[n_entries].max_port = high;
+ n_entries++;
+ }
+
+ if (n_entries == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found no port-range entries in summary %s", escaped(orig_summary));
+ return NULL;
+ }
+
+ {
+ size_t size = STRUCT_OFFSET(short_policy_t, entries) +
+ sizeof(short_policy_entry_t)*(n_entries);
+ result = tor_malloc_zero(size);
+
+ tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size);
+ }
+
+ result->is_accept = is_accept;
+ result->n_entries = n_entries;
+ memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries);
+ return result;
+}
+
+/** Release all storage held in <b>policy</b>. */
+void
+short_policy_free(short_policy_t *policy)
+{
+ tor_free(policy);
+}
+
+/** See whether the <b>addr</b>:<b>port</b> address is likely to be accepted
+ * or rejected by the summarized policy <b>policy</b>. Return values are as
+ * for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy
+ * functions, requires the <b>port</b> be specified. */
+addr_policy_result_t
+compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy)
+{
+ int i;
+ int found_match = 0;
+ int accept;
+ (void)addr;
+
+ tor_assert(port != 0);
+
+ if (addr && tor_addr_is_null(addr))
+ addr = NULL; /* Unspec means 'no address at all,' in this context. */
+
+ if (addr && (tor_addr_is_internal(addr, 0) ||
+ tor_addr_is_loopback(addr)))
+ return ADDR_POLICY_REJECTED;
+
+ for (i=0; i < policy->n_entries; ++i) {
+ const short_policy_entry_t *e = &policy->entries[i];
+ if (e->min_port <= port && port <= e->max_port) {
+ found_match = 1;
+ break;
+ }
+ }
+
+ if (found_match)
+ accept = policy->is_accept;
+ else
+ accept = ! policy->is_accept;
+
+ /* ???? are these right? */
+ if (accept)
+ return ADDR_POLICY_PROBABLY_ACCEPTED;
+ else
+ return ADDR_POLICY_REJECTED;
+}
+
+/** Return true iff <b>policy</b> seems reject all ports */
+int
+short_policy_is_reject_star(const short_policy_t *policy)
+{
+ /* This doesn't need to be as much on the lookout as policy_is_reject_star,
+ * since policy summaries are from the consensus or from consensus
+ * microdescs.
+ */
+ tor_assert(policy);
+ /* Check for an exact match of "reject 1-65535". */
+ return (policy->is_accept == 0 && policy->n_entries == 1 &&
+ policy->entries[0].min_port == 1 &&
+ policy->entries[0].max_port == 65535);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
+ const node_t *node)
+{
+ if (node->rejects_all)
+ return ADDR_POLICY_REJECTED;
+
+ if (node->ri)
+ return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy);
+ else if (node->md) {
+ if (node->md->exit_policy == NULL)
+ return ADDR_POLICY_REJECTED;
+ else
+ return compare_tor_addr_to_short_policy(addr, port,
+ node->md->exit_policy);
+ } else
+ return ADDR_POLICY_PROBABLY_REJECTED;
+}
+
/** Implementation for GETINFO control command: knows the answer for questions
* about "exit-policy/..." */
int
diff --git a/src/or/policies.h b/src/or/policies.h
index b2947c67e7..51716ab0a7 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -19,7 +19,8 @@
int firewall_is_fascist_or(void);
int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
-int fascist_firewall_allows_or(routerinfo_t *ri);
+int fascist_firewall_allows_or(const routerinfo_t *ri);
+int fascist_firewall_allows_node(const node_t *node);
int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
int dir_policy_permits_address(const tor_addr_t *addr);
int socks_policy_permits_address(const tor_addr_t *addr);
@@ -28,21 +29,23 @@ int authdir_policy_valid_address(uint32_t addr, uint16_t port);
int authdir_policy_baddir_address(uint32_t addr, uint16_t port);
int authdir_policy_badexit_address(uint32_t addr, uint16_t port);
-int validate_addr_policies(or_options_t *options, char **msg);
+int validate_addr_policies(const or_options_t *options, char **msg);
void policy_expand_private(smartlist_t **policy);
-int policies_parse_from_options(or_options_t *options);
+int policies_parse_from_options(const or_options_t *options);
addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent);
int cmp_addr_policies(smartlist_t *a, smartlist_t *b);
addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
uint16_t port, const smartlist_t *policy);
-addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
- uint16_t port, const smartlist_t *policy);
+
+addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
+ uint16_t port, const node_t *node);
+
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int rejectprivate, const char *local_address,
int add_default_policy);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
-void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter);
+void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
int exit_policy_is_general_exit(smartlist_t *policy);
int policy_is_reject_star(const smartlist_t *policy);
int getinfo_helper_policies(control_connection_t *conn,
@@ -57,5 +60,12 @@ void policies_free_all(void);
char *policy_summarize(smartlist_t *policy);
+short_policy_t *parse_short_policy(const char *summary);
+void short_policy_free(short_policy_t *policy);
+int short_policy_is_reject_star(const short_policy_t *policy);
+addr_policy_result_t compare_tor_addr_to_short_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy);
+
#endif
diff --git a/src/or/relay.c b/src/or/relay.c
index d9b9d0c486..ac3114bda5 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -11,6 +11,7 @@
**/
#include <math.h>
+#define RELAY_PRIVATE
#include "or.h"
#include "buffers.h"
#include "circuitbuild.h"
@@ -24,6 +25,7 @@
#include "main.h"
#include "mempool.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -32,9 +34,6 @@
#include "routerlist.h"
#include "routerparse.h"
-static int relay_crypt(circuit_t *circ, cell_t *cell,
- cell_direction_t cell_direction,
- crypt_path_t **layer_hint, char *recognized);
static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
cell_direction_t cell_direction,
crypt_path_t *layer_hint);
@@ -296,7 +295,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
* Return -1 to indicate that we should mark the circuit for close,
* else return 0.
*/
-static int
+int
relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
crypt_path_t **layer_hint, char *recognized)
{
@@ -648,6 +647,7 @@ connection_edge_send_command(edge_connection_t *fromconn,
{
/* XXXX NM Split this function into a separate versions per circuit type? */
circuit_t *circ;
+ crypt_path_t *cpath_layer = fromconn->cpath_layer;
tor_assert(fromconn);
circ = fromconn->on_circuit;
@@ -662,7 +662,8 @@ connection_edge_send_command(edge_connection_t *fromconn,
if (!circ) {
if (fromconn->_base.type == CONN_TYPE_AP) {
log_info(LD_APP,"no circ. Closing conn.");
- connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL);
+ connection_mark_unattached_ap(EDGE_TO_ENTRY_CONN(fromconn),
+ END_STREAM_REASON_INTERNAL);
} else {
log_info(LD_EXIT,"no circ. Closing conn.");
fromconn->edge_has_sent_end = 1; /* no circ to send to */
@@ -674,7 +675,7 @@ connection_edge_send_command(edge_connection_t *fromconn,
return relay_send_command_from_edge(fromconn->stream_id, circ,
relay_command, payload,
- payload_len, fromconn->cpath_layer);
+ payload_len, cpath_layer);
}
/** How many times will I retry a stream that fails due to DNS
@@ -702,22 +703,24 @@ edge_reason_is_retriable(int reason)
static int
connection_ap_process_end_not_open(
relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
- edge_connection_t *conn, crypt_path_t *layer_hint)
+ entry_connection_t *conn, crypt_path_t *layer_hint)
{
struct in_addr in;
- routerinfo_t *exitrouter;
+ node_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE);
int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
(void) layer_hint; /* unused */
if (rh->length > 0 && edge_reason_is_retriable(reason) &&
- !connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */
- ) {
+ /* avoid retry if rend */
+ !connection_edge_is_rendezvous_stream(edge_conn)) {
+ const char *chosen_exit_digest =
+ circ->build_state->chosen_exit->identity_digest;
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address),
stream_end_reason_to_string(reason));
- exitrouter =
- router_get_by_digest(circ->build_state->chosen_exit->identity_digest);
+ exitrouter = node_get_mutable_by_id(chosen_exit_digest);
switch (reason) {
case END_STREAM_REASON_EXITPOLICY:
if (rh->length >= 5) {
@@ -752,8 +755,8 @@ connection_ap_process_end_not_open(
log_info(LD_APP,
"Exitrouter %s seems to be more restrictive than its exit "
"policy. Not using this router as exit for now.",
- router_describe(exitrouter));
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ node_describe(exitrouter));
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
/* rewrite it to an IP if we learned one. */
if (addressmap_rewrite(conn->socks_request->address,
@@ -818,7 +821,7 @@ connection_ap_process_end_not_open(
case END_STREAM_REASON_HIBERNATING:
case END_STREAM_REASON_RESOURCELIMIT:
if (exitrouter) {
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
if (conn->chosen_exit_optional) {
/* stop wanting a specific exit */
@@ -838,7 +841,7 @@ connection_ap_process_end_not_open(
stream_end_reason_to_string(rh->length > 0 ? reason : -1));
circuit_log_path(LOG_INFO,LD_APP,circ);
/* need to test because of detach_retriable */
- if (!conn->_base.marked_for_close)
+ if (!ENTRY_TO_CONN(conn)->marked_for_close)
connection_mark_unattached_ap(conn, control_reason);
return 0;
}
@@ -847,7 +850,7 @@ connection_ap_process_end_not_open(
* dotted-quad representation of <b>new_addr</b> (given in host order),
* and send an appropriate REMAP event. */
static void
-remap_event_helper(edge_connection_t *conn, uint32_t new_addr)
+remap_event_helper(entry_connection_t *conn, uint32_t new_addr)
{
struct in_addr in;
@@ -873,7 +876,8 @@ connection_edge_process_relay_cell_not_open(
if (rh->command == RELAY_COMMAND_END) {
if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) {
return connection_ap_process_end_not_open(rh, cell,
- TO_ORIGIN_CIRCUIT(circ), conn,
+ TO_ORIGIN_CIRCUIT(circ),
+ EDGE_TO_ENTRY_CONN(conn),
layer_hint);
} else {
/* we just got an 'end', don't need to send one */
@@ -887,6 +891,7 @@ connection_edge_process_relay_cell_not_open(
if (conn->_base.type == CONN_TYPE_AP &&
rh->command == RELAY_COMMAND_CONNECTED) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
log_fn(LOG_PROTOCOL_WARN, LD_APP,
@@ -901,29 +906,26 @@ connection_edge_process_relay_cell_not_open(
int ttl;
if (!addr || (get_options()->ClientDNSRejectInternalAddresses &&
is_internal_IP(addr, 0))) {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
- a.s_addr = htonl(addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_APP,
- "...but it claims the IP address was %s. Closing.", buf);
+ log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
+ fmt_addr32(addr));
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
return 0;
}
if (rh->length >= 8)
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
else
ttl = -1;
- client_dns_set_addressmap(conn->socks_request->address, addr,
- conn->chosen_exit_name, ttl);
+ client_dns_set_addressmap(entry_conn->socks_request->address, addr,
+ entry_conn->chosen_exit_name, ttl);
- remap_event_helper(conn, addr);
+ remap_event_helper(entry_conn, addr);
}
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
/* don't send a socks reply to transparent conns */
- if (!conn->socks_request->has_finished)
- connection_ap_handshake_socks_reply(conn, NULL, 0, 0);
+ if (!entry_conn->socks_request->has_finished)
+ connection_ap_handshake_socks_reply(entry_conn, NULL, 0, 0);
/* Was it a linked dir conn? If so, a dir request just started to
* fetch something; this could be a bootstrap status milestone. */
@@ -946,6 +948,12 @@ connection_edge_process_relay_cell_not_open(
break;
}
}
+ /* This is definitely a success, so forget about any pending data we
+ * had sent. */
+ if (entry_conn->pending_optimistic_data) {
+ generic_buffer_free(entry_conn->pending_optimistic_data);
+ entry_conn->pending_optimistic_data = NULL;
+ }
/* handle anything that might have queued */
if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) {
@@ -960,17 +968,18 @@ connection_edge_process_relay_cell_not_open(
int ttl;
int answer_len;
uint8_t answer_type;
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while "
"not in state resolve_wait. Dropping.");
return 0;
}
- tor_assert(SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command));
+ tor_assert(SOCKS_COMMAND_IS_RESOLVE(entry_conn->socks_request->command));
answer_len = cell->payload[RELAY_HEADER_SIZE+1];
if (rh->length < 2 || answer_len+2>rh->length) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Dropping malformed 'resolved' cell");
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
return 0;
}
answer_type = cell->payload[RELAY_HEADER_SIZE];
@@ -983,19 +992,17 @@ connection_edge_process_relay_cell_not_open(
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
if (get_options()->ClientDNSRejectInternalAddresses &&
is_internal_IP(addr, 0)) {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
- a.s_addr = htonl(addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", buf);
- connection_ap_handshake_socks_resolved(conn,
+ log_info(LD_APP,"Got a resolve with answer %s. Rejecting.",
+ fmt_addr32(addr));
+ connection_ap_handshake_socks_resolved(entry_conn,
RESOLVED_TYPE_ERROR_TRANSIENT,
0, NULL, 0, TIME_MAX);
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
return 0;
}
}
- connection_ap_handshake_socks_resolved(conn,
+ connection_ap_handshake_socks_resolved(entry_conn,
answer_type,
cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
cell->payload+RELAY_HEADER_SIZE+2, /*answer*/
@@ -1003,9 +1010,9 @@ connection_edge_process_relay_cell_not_open(
-1);
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
- remap_event_helper(conn, addr);
+ remap_event_helper(entry_conn, addr);
}
- connection_mark_unattached_ap(conn,
+ connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_DONE |
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
return 0;
@@ -1039,6 +1046,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
relay_header_t rh;
unsigned domain = layer_hint?LD_APP:LD_EXIT;
int reason;
+ int optimistic_data = 0; /* Set to 1 if we receive data on a stream
+ * that's in the EXIT_CONN_STATE_RESOLVING
+ * or EXIT_CONN_STATE_CONNECTING states. */
tor_assert(cell);
tor_assert(circ);
@@ -1058,9 +1068,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
/* either conn is NULL, in which case we've got a control cell, or else
* conn points to the recognized stream. */
- if (conn && !connection_state_is_open(TO_CONN(conn)))
- return connection_edge_process_relay_cell_not_open(
- &rh, cell, circ, conn, layer_hint);
+ if (conn && !connection_state_is_open(TO_CONN(conn))) {
+ if (conn->_base.type == CONN_TYPE_EXIT &&
+ (conn->_base.state == EXIT_CONN_STATE_CONNECTING ||
+ conn->_base.state == EXIT_CONN_STATE_RESOLVING) &&
+ rh.command == RELAY_COMMAND_DATA) {
+ /* Allow DATA cells to be delivered to an exit node in state
+ * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
+ * This speeds up HTTP, for example. */
+ optimistic_data = 1;
+ } else {
+ return connection_edge_process_relay_cell_not_open(
+ &rh, cell, circ, conn, layer_hint);
+ }
+ }
switch (rh.command) {
case RELAY_COMMAND_DROP:
@@ -1127,7 +1148,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
stats_n_data_bytes_received += rh.length;
connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
rh.length, TO_CONN(conn));
- connection_edge_consider_sending_sendme(conn);
+
+ if (!optimistic_data) {
+ /* Only send a SENDME if we're not getting optimistic data; otherwise
+ * a SENDME could arrive before the CONNECTED.
+ */
+ connection_edge_consider_sending_sendme(conn);
+ }
+
return 0;
case RELAY_COMMAND_END:
reason = rh.length > 0 ?
@@ -1142,9 +1170,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
conn->_base.s,
stream_end_reason_to_string(reason),
conn->stream_id);
- if (conn->socks_request && !conn->socks_request->has_finished)
- log_warn(LD_BUG,
- "open stream hasn't sent socks answer yet? Closing.");
+ if (conn->_base.type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ if (entry_conn->socks_request &&
+ !entry_conn->socks_request->has_finished)
+ log_warn(LD_BUG,
+ "open stream hasn't sent socks answer yet? Closing.");
+ }
/* We just *got* an end; no reason to send one. */
conn->edge_has_sent_end = 1;
if (!conn->end_reason)
@@ -1152,8 +1184,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (!conn->_base.marked_for_close) {
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
return 0;
case RELAY_COMMAND_EXTEND:
@@ -1324,10 +1355,17 @@ int
connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
int *max_cells)
{
- size_t amount_to_process, length;
+ size_t bytes_to_process, length;
char payload[CELL_PAYLOAD_SIZE];
circuit_t *circ;
- unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT;
+ const unsigned domain = conn->_base.type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
+ int sending_from_optimistic = 0;
+ const int sending_optimistically =
+ conn->_base.type == CONN_TYPE_AP &&
+ conn->_base.state != AP_CONN_STATE_OPEN;
+ entry_connection_t *entry_conn =
+ conn->_base.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL;
+ crypt_path_t *cpath_layer = conn->cpath_layer;
tor_assert(conn);
@@ -1350,7 +1388,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return -1;
}
- if (circuit_consider_stop_edge_reading(circ, conn->cpath_layer))
+ if (circuit_consider_stop_edge_reading(circ, cpath_layer))
return 0;
if (conn->package_window <= 0) {
@@ -1360,44 +1398,75 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return 0;
}
- amount_to_process = buf_datalen(conn->_base.inbuf);
+ sending_from_optimistic = entry_conn &&
+ entry_conn->sending_optimistic_data != NULL;
+
+ if (PREDICT_UNLIKELY(sending_from_optimistic)) {
+ bytes_to_process = generic_buffer_len(entry_conn->sending_optimistic_data);
+ if (PREDICT_UNLIKELY(!bytes_to_process)) {
+ log_warn(LD_BUG, "sending_optimistic_data was non-NULL but empty");
+ bytes_to_process = connection_get_inbuf_len(TO_CONN(conn));
+ sending_from_optimistic = 0;
+ }
+ } else {
+ bytes_to_process = connection_get_inbuf_len(TO_CONN(conn));
+ }
- if (!amount_to_process)
+ if (!bytes_to_process)
return 0;
- if (!package_partial && amount_to_process < RELAY_PAYLOAD_SIZE)
+ if (!package_partial && bytes_to_process < RELAY_PAYLOAD_SIZE)
return 0;
- if (amount_to_process > RELAY_PAYLOAD_SIZE) {
+ if (bytes_to_process > RELAY_PAYLOAD_SIZE) {
length = RELAY_PAYLOAD_SIZE;
} else {
- length = amount_to_process;
+ length = bytes_to_process;
}
stats_n_data_bytes_packaged += length;
stats_n_data_cells_packaged += 1;
- connection_fetch_from_buf(payload, length, TO_CONN(conn));
+ if (PREDICT_UNLIKELY(sending_from_optimistic)) {
+ /* XXX023 We could be more efficient here by sometimes packing
+ * previously-sent optimistic data in the same cell with data
+ * from the inbuf. */
+ generic_buffer_get(entry_conn->sending_optimistic_data, payload, length);
+ if (!generic_buffer_len(entry_conn->sending_optimistic_data)) {
+ generic_buffer_free(entry_conn->sending_optimistic_data);
+ entry_conn->sending_optimistic_data = NULL;
+ }
+ } else {
+ connection_fetch_from_buf(payload, length, TO_CONN(conn));
+ }
log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s,
- (int)length, (int)buf_datalen(conn->_base.inbuf));
+ (int)length, (int)connection_get_inbuf_len(TO_CONN(conn)));
+
+ if (sending_optimistically && !sending_from_optimistic) {
+ /* This is new optimistic data; remember it in case we need to detach and
+ retry */
+ if (!entry_conn->pending_optimistic_data)
+ entry_conn->pending_optimistic_data = generic_buffer_new();
+ generic_buffer_add(entry_conn->pending_optimistic_data, payload, length);
+ }
if (connection_edge_send_command(conn, RELAY_COMMAND_DATA,
payload, length) < 0 )
/* circuit got marked for close, don't continue, don't need to mark conn */
return 0;
- if (!conn->cpath_layer) { /* non-rendezvous exit */
+ if (!cpath_layer) { /* non-rendezvous exit */
tor_assert(circ->package_window > 0);
circ->package_window--;
} else { /* we're an AP, or an exit on a rendezvous circ */
- tor_assert(conn->cpath_layer->package_window > 0);
- conn->cpath_layer->package_window--;
+ tor_assert(cpath_layer->package_window > 0);
+ cpath_layer->package_window--;
}
if (--conn->package_window <= 0) { /* is it 0 after decrement? */
connection_stop_reading(TO_CONN(conn));
log_debug(domain,"conn->package_window reached 0.");
- circuit_consider_stop_edge_reading(circ, conn->cpath_layer);
+ circuit_consider_stop_edge_reading(circ, cpath_layer);
return 0; /* don't process the inbuf any more */
}
log_debug(domain,"conn->package_window is now %d",conn->package_window);
@@ -1436,7 +1505,7 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn)
}
while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
- log_debug(conn->cpath_layer?LD_APP:LD_EXIT,
+ log_debug(conn->_base.type == CONN_TYPE_AP ?LD_APP:LD_EXIT,
"Outbuf %d, Queuing stream sendme.",
(int)conn->_base.outbuf_flushlen);
conn->deliver_window += STREAMWINDOW_INCREMENT;
@@ -1532,7 +1601,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
- if (buf_datalen(conn->_base.inbuf) > 0)
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
@@ -1543,7 +1612,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
- if (buf_datalen(conn->_base.inbuf) > 0)
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
@@ -1582,7 +1651,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
}
/* If there's still data to read, we'll be coming back to this stream. */
- if (buf_datalen(conn->_base.inbuf))
+ if (connection_get_inbuf_len(TO_CONN(conn)))
++n_streams_left;
/* If the circuit won't accept any more data, return without looking
@@ -1638,9 +1707,10 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
if (layer_hint->package_window <= 0) {
log_debug(domain,"yes, at-origin. stopped.");
for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
- conn=conn->next_stream)
+ conn=conn->next_stream) {
if (conn->cpath_layer == layer_hint)
connection_stop_reading(TO_CONN(conn));
+ }
return 1;
}
return 0;
@@ -1995,7 +2065,8 @@ static int ewma_enabled = 0;
/** Adjust the global cell scale factor based on <b>options</b> */
void
-cell_ewma_set_scale_factor(or_options_t *options, networkstatus_t *consensus)
+cell_ewma_set_scale_factor(const or_options_t *options,
+ const networkstatus_t *consensus)
{
int32_t halflife_ms;
double halflife;
@@ -2246,7 +2317,7 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn,
edge->edge_blocked_on_circ = block;
}
- if (!conn->read_event) {
+ if (!conn->read_event && !HAS_BUFFEREVENT(conn)) {
/* This connection is a placeholder for something; probably a DNS
* request. It can't actually stop or start reading.*/
continue;
@@ -2321,13 +2392,13 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
/* Calculate the exact time that this cell has spent in the queue. */
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
- struct timeval now;
+ struct timeval tvnow;
uint32_t flushed;
uint32_t cell_waiting_time;
insertion_time_queue_t *it_queue = queue->insertion_times;
- tor_gettimeofday_cached(&now);
- flushed = (uint32_t)((now.tv_sec % SECONDS_IN_A_DAY) * 100L +
- (uint32_t)now.tv_usec / (uint32_t)10000L);
+ tor_gettimeofday_cached(&tvnow);
+ flushed = (uint32_t)((tvnow.tv_sec % SECONDS_IN_A_DAY) * 100L +
+ (uint32_t)tvnow.tv_usec / (uint32_t)10000L);
if (!it_queue || !it_queue->first) {
log_info(LD_GENERAL, "Cannot determine insertion time of cell. "
"Looks like the CellStatistics option was "
@@ -2447,7 +2518,7 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
make_circuit_active_on_conn(circ, orconn);
}
- if (! buf_datalen(orconn->_base.outbuf)) {
+ if (! connection_get_outbuf_len(TO_CONN(orconn))) {
/* There is no data at all waiting to be sent on the outbuf. Add a
* cell, so that we can notice when it gets flushed, flushed_some can
* get called, and we can start putting more data onto the buffer then.
diff --git a/src/or/relay.h b/src/or/relay.h
index f64752da5d..1cd4008bb9 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -60,11 +60,16 @@ const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
const uint8_t *payload,
int payload_len);
unsigned cell_ewma_get_tick(void);
-void cell_ewma_set_scale_factor(or_options_t *options,
- networkstatus_t *consensus);
+void cell_ewma_set_scale_factor(const or_options_t *options,
+ const networkstatus_t *consensus);
void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn);
void tor_gettimeofday_cache_clear(void);
+#ifdef RELAY_PRIVATE
+int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
+ crypt_path_t **layer_hint, char *recognized);
+#endif
+
#endif
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 0a9e2a605f..6a45207e29 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -16,6 +16,7 @@
#include "connection_edge.h"
#include "directory.h"
#include "main.h"
+#include "nodelist.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -80,8 +81,8 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ)
/** Extend the introduction circuit <b>circ</b> to another valid
* introduction point for the hidden service it is trying to connect
* to, or mark it and launch a new circuit if we can't extend it.
- * Return 0 on success. Return -1 and mark the introduction
- * circuit on failure.
+ * Return 0 on success or possible success. Return -1 and mark the
+ * introduction circuit for close on permanent failure.
*
* On failure, the caller is responsible for marking the associated
* rendezvous circuit for close. */
@@ -106,17 +107,11 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ)
result = circuit_extend_to_new_exit(circ, extend_info);
} else {
log_info(LD_REND,
- "Building a new introduction circuit, this time to %s.",
- safe_str_client(extend_info_describe(extend_info)));
+ "Closing intro circ %d (out of RELAY_EARLY cells).",
+ circ->_base.n_circ_id);
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
- if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING,
- extend_info,
- CIRCLAUNCH_IS_INTERNAL)) {
- log_warn(LD_REND, "Building introduction circuit failed.");
- result = -1;
- } else {
- result = 0;
- }
+ /* connection_ap_handshake_attach_circuit will launch a new intro circ. */
+ result = 0;
}
extend_info_free(extend_info);
return result;
@@ -144,6 +139,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
tor_assert(rendcirc->rend_data);
tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address,
rendcirc->rend_data->onion_address));
+ tor_assert(!(introcirc->build_state->onehop_tunnel));
+ tor_assert(!(rendcirc->build_state->onehop_tunnel));
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
&entry) < 1) {
@@ -334,6 +331,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
}
tor_assert(circ->build_state->chosen_exit);
+ tor_assert(!(circ->build_state->onehop_tunnel));
tor_assert(circ->rend_data);
if (request_len == 0) {
@@ -345,6 +343,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
rendcirc = circuit_get_by_rend_query_and_purpose(
circ->rend_data->onion_address, CIRCUIT_PURPOSE_C_REND_READY);
if (rendcirc) { /* remember the ack */
+ tor_assert(!(rendcirc->build_state->onehop_tunnel));
rendcirc->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
/* Set timestamp_dirty, because circuit_expire_building expects
* it to specify when a circuit entered the
@@ -367,8 +366,8 @@ rend_client_introduction_acked(origin_circuit_t *circ,
safe_str_client(circ->rend_data->onion_address),
safe_str_client(extend_info_describe(circ->build_state->chosen_exit)));
if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit,
- circ->rend_data,
- INTRO_POINT_FAILURE_GENERIC)>0){
+ circ->rend_data,
+ INTRO_POINT_FAILURE_GENERIC)>0) {
/* There are introduction points left. Re-extend the circuit to
* another intro point and try again. */
int result = rend_client_reextend_intro_circuit(circ);
@@ -385,9 +384,12 @@ rend_client_introduction_acked(origin_circuit_t *circ,
#define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60)
/** Contains the last request times to hidden service directories for
- * certain queries; keys are strings consisting of base32-encoded
- * hidden service directory identities and base32-encoded descriptor IDs;
- * values are pointers to timestamps of the last requests. */
+ * certain queries; each key is a string consisting of the
+ * concatenation of a base32-encoded HS directory identity digest, a
+ * base32-encoded HS descriptor ID, and a hidden service address
+ * (without the ".onion" part); each value is a pointer to a time_t
+ * holding the time of the last request for that descriptor ID to that
+ * HS directory. */
static strmap_t *last_hid_serv_requests_ = NULL;
/** Returns last_hid_serv_requests_, initializing it to a new strmap if
@@ -400,23 +402,34 @@ get_last_hid_serv_requests(void)
return last_hid_serv_requests_;
}
+#define LAST_HID_SERV_REQUEST_KEY_LEN (REND_DESC_ID_V2_LEN_BASE32 + \
+ REND_DESC_ID_V2_LEN_BASE32 + \
+ REND_SERVICE_ID_LEN_BASE32)
+
/** Look up the last request time to hidden service directory <b>hs_dir</b>
- * for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
+ * for descriptor ID <b>desc_id_base32</b> for the service specified in
+ * <b>rend_query</b>. If <b>set</b> is non-zero,
* assign the current time <b>now</b> and return that. Otherwise, return
* the most recent request time, or 0 if no such request has been sent
* before. */
static time_t
lookup_last_hid_serv_request(routerstatus_t *hs_dir,
- const char *desc_id_base32, time_t now, int set)
+ const char *desc_id_base32,
+ const rend_data_t *rend_query,
+ time_t now, int set)
{
char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
- char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
+ char hsdir_desc_comb_id[LAST_HID_SERV_REQUEST_KEY_LEN + 1];
time_t *last_request_ptr;
strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
hs_dir->identity_digest, DIGEST_LEN);
- tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
- hsdir_id_base32, desc_id_base32);
+ tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s%s",
+ hsdir_id_base32,
+ desc_id_base32,
+ rend_query->onion_address);
+ /* XXX023 tor_assert(strlen(hsdir_desc_comb_id) ==
+ LAST_HID_SERV_REQUEST_KEY_LEN); */
if (set) {
time_t *oldptr;
last_request_ptr = tor_malloc_zero(sizeof(time_t));
@@ -434,10 +447,10 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir,
* it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD
* seconds any more. */
static void
-directory_clean_last_hid_serv_requests(void)
+directory_clean_last_hid_serv_requests(time_t now)
{
strmap_iter_t *iter;
- time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
+ time_t cutoff = now - REND_HID_SERV_DIR_REQUERY_PERIOD;
strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
for (iter = strmap_iter_init(last_hid_serv_requests);
!strmap_iter_done(iter); ) {
@@ -455,6 +468,33 @@ directory_clean_last_hid_serv_requests(void)
}
}
+/** Remove all requests related to the hidden service named
+ * <b>onion_address</b> from the history of times of requests to
+ * hidden service directories. */
+static void
+purge_hid_serv_from_last_hid_serv_requests(const char *onion_address)
+{
+ strmap_iter_t *iter;
+ strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
+ /* XXX023 tor_assert(strlen(onion_address) == REND_SERVICE_ID_LEN_BASE32); */
+ for (iter = strmap_iter_init(last_hid_serv_requests);
+ !strmap_iter_done(iter); ) {
+ const char *key;
+ void *val;
+ strmap_iter_get(iter, &key, &val);
+ /* XXX023 tor_assert(strlen(key) == LAST_HID_SERV_REQUEST_KEY_LEN); */
+ if (tor_memeq(key + LAST_HID_SERV_REQUEST_KEY_LEN -
+ REND_SERVICE_ID_LEN_BASE32,
+ onion_address,
+ REND_SERVICE_ID_LEN_BASE32)) {
+ iter = strmap_iter_next_rmv(last_hid_serv_requests, iter);
+ tor_free(val);
+ } else {
+ iter = strmap_iter_next(last_hid_serv_requests, iter);
+ }
+ }
+}
+
/** Purge the history of request times to hidden service directories,
* so that future lookups of an HS descriptor will not fail because we
* accessed all of the HSDir relays responsible for the descriptor
@@ -476,12 +516,11 @@ rend_client_purge_last_hid_serv_requests(void)
}
/** Determine the responsible hidden service directories for <b>desc_id</b>
- * and fetch the descriptor belonging to that ID from one of them. Only
- * send a request to hidden service directories that we did not try within
- * the last REND_HID_SERV_DIR_REQUERY_PERIOD seconds; on success, return 1,
+ * and fetch the descriptor with that ID from one of them. Only
+ * send a request to a hidden service directory that we have not yet tried
+ * during this attempt to connect to this hidden service; on success, return 1,
* in the case that no hidden service directory is left to ask for the
- * descriptor, return 0, and in case of a failure -1. <b>query</b> is only
- * passed for pretty log statements. */
+ * descriptor, return 0, and in case of a failure -1. */
static int
directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
{
@@ -501,12 +540,16 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
/* Only select those hidden service directories to which we did not send
* a request recently and for which we have a router descriptor here. */
- directory_clean_last_hid_serv_requests(); /* Clean request history first. */
+
+ /* Clean request history first. */
+ directory_clean_last_hid_serv_requests(now);
SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
- if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) +
- REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
- !router_get_by_digest(dir->identity_digest))
+ time_t last = lookup_last_hid_serv_request(
+ dir, desc_id_base32, rend_query, 0, 0);
+ const node_t *node = node_get_by_id(dir->identity_digest);
+ if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
+ !node || !node_has_descriptor(node))
SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
});
@@ -519,9 +562,9 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
return 0;
}
- /* Remember, that we are requesting a descriptor from this hidden service
+ /* Remember that we are requesting a descriptor from this hidden service
* directory now. */
- lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1);
+ lookup_last_hid_serv_request(hs_dir, desc_id_base32, rend_query, now, 1);
/* Encode descriptor cookie for logging purposes. */
if (rend_query->auth_type != REND_NO_AUTH) {
@@ -859,40 +902,42 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
void
rend_client_desc_trynow(const char *query)
{
- edge_connection_t *conn;
+ entry_connection_t *conn;
rend_cache_entry_t *entry;
+ const rend_data_t *rend_data;
time_t now = time(NULL);
smartlist_t *conns = get_connection_array();
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, _conn) {
- if (_conn->type != CONN_TYPE_AP ||
- _conn->state != AP_CONN_STATE_RENDDESC_WAIT ||
- _conn->marked_for_close)
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ if (base_conn->type != CONN_TYPE_AP ||
+ base_conn->state != AP_CONN_STATE_RENDDESC_WAIT ||
+ base_conn->marked_for_close)
continue;
- conn = TO_EDGE_CONN(_conn);
- if (!conn->rend_data)
+ conn = TO_ENTRY_CONN(base_conn);
+ rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
+ if (!rend_data)
continue;
- if (rend_cmp_service_ids(query, conn->rend_data->onion_address))
+ if (rend_cmp_service_ids(query, rend_data->onion_address))
continue;
- assert_connection_ok(TO_CONN(conn), now);
- if (rend_cache_lookup_entry(conn->rend_data->onion_address, -1,
+ assert_connection_ok(base_conn, now);
+ if (rend_cache_lookup_entry(rend_data->onion_address, -1,
&entry) == 1 &&
rend_client_any_intro_points_usable(entry)) {
/* either this fetch worked, or it failed but there was a
* valid entry from before which we should reuse */
log_info(LD_REND,"Rend desc is usable. Launching circuits.");
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
/* restart their timeout values, so they get a fair shake at
* connecting to the hidden service. */
- conn->_base.timestamp_created = now;
- conn->_base.timestamp_lastread = now;
- conn->_base.timestamp_lastwritten = now;
+ base_conn->timestamp_created = now;
+ base_conn->timestamp_lastread = now;
+ base_conn->timestamp_lastwritten = now;
if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */
log_warn(LD_REND,"Rendezvous attempt failed. Closing.");
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
} else { /* 404, or fetch didn't get that far */
@@ -902,7 +947,7 @@ rend_client_desc_trynow(const char *query)
connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
rend_client_note_connection_attempt_ended(query);
}
- } SMARTLIST_FOREACH_END(_conn);
+ } SMARTLIST_FOREACH_END(base_conn);
}
/** Clear temporary state used only during an attempt to connect to
@@ -925,6 +970,9 @@ rend_client_note_connection_attempt_ended(const char *onion_address)
rend_intro_point_t *, ip,
ip->timed_out = 0; );
}
+
+ /* Remove the HS's entries in last_hid_serv_requests. */
+ purge_hid_serv_from_last_hid_serv_requests(onion_address);
}
/** Return a newly allocated extend_info_t* for a randomly chosen introduction
@@ -966,8 +1014,7 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
int i;
rend_intro_point_t *intro;
- routerinfo_t *router;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *usable_nodes;
int n_excluded = 0;
@@ -1000,21 +1047,33 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
intro = smartlist_get(usable_nodes, i);
/* Do we need to look up the router or is the extend info complete? */
if (!intro->extend_info->onion_key) {
+ const node_t *node;
+ extend_info_t *new_extend_info;
if (tor_digest_is_zero(intro->extend_info->identity_digest))
- router = router_get_by_hexdigest(intro->extend_info->nickname);
+ node = node_get_by_hex_id(intro->extend_info->nickname);
else
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node) {
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
intro->extend_info->nickname);
smartlist_del(usable_nodes, i);
goto again;
}
- extend_info_free(intro->extend_info);
- intro->extend_info = extend_info_from_router(router);
+ new_extend_info = extend_info_from_node(node);
+ if (!new_extend_info) {
+ log_info(LD_REND, "We don't have a descriptor for the intro-point relay "
+ "'%s'; trying another.",
+ extend_info_describe(intro->extend_info));
+ smartlist_del(usable_nodes, i);
+ goto again;
+ } else {
+ extend_info_free(intro->extend_info);
+ intro->extend_info = new_extend_info;
+ }
+ tor_assert(intro->extend_info != NULL);
}
/* Check if we should refuse to talk to this router. */
- if (options->ExcludeNodes && strict &&
+ if (strict &&
routerset_contains_extendinfo(options->ExcludeNodes,
intro->extend_info)) {
n_excluded++;
@@ -1031,8 +1090,13 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
int
rend_client_any_intro_points_usable(const rend_cache_entry_t *entry)
{
- return rend_client_get_random_intro_impl(
- entry, get_options()->StrictNodes, 0) != NULL;
+ extend_info_t *extend_info =
+ rend_client_get_random_intro_impl(entry, get_options()->StrictNodes, 0);
+
+ int rv = (extend_info != NULL);
+
+ extend_info_free(extend_info);
+ return rv;
}
/** Client-side authorizations for hidden services; map of onion address to
@@ -1080,7 +1144,8 @@ rend_service_authorization_free_all(void)
* service and add it to the local map of hidden service authorizations.
* Return 0 for success and -1 for failure. */
int
-rend_parse_service_authorization(or_options_t *options, int validate_only)
+rend_parse_service_authorization(const or_options_t *options,
+ int validate_only)
{
config_line_t *line;
int res = -1;
diff --git a/src/or/rendclient.h b/src/or/rendclient.h
index d87cb1fe3b..89da47789a 100644
--- a/src/or/rendclient.h
+++ b/src/or/rendclient.h
@@ -46,7 +46,7 @@ int rend_client_any_intro_points_usable(const rend_cache_entry_t *entry);
int rend_client_send_introduction(origin_circuit_t *introcirc,
origin_circuit_t *rendcirc);
-int rend_parse_service_authorization(or_options_t *options,
+int rend_parse_service_authorization(const or_options_t *options,
int validate_only);
rend_service_authorization_t *rend_client_lookup_service_authorization(
const char *onion_address);
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 2ca001d984..d09e6566c2 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -819,14 +819,13 @@ rend_cache_free_all(void)
/** Removes all old entries from the service descriptor cache.
*/
void
-rend_cache_clean(void)
+rend_cache_clean(time_t now)
{
strmap_iter_t *iter;
const char *key;
void *val;
rend_cache_entry_t *ent;
- time_t cutoff;
- cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
+ time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) {
strmap_iter_get(iter, &key, &val);
ent = (rend_cache_entry_t*)val;
@@ -854,10 +853,10 @@ rend_cache_purge(void)
/** Remove all old v2 descriptors and those for which this hidden service
* directory is not responsible for any more. */
void
-rend_cache_clean_v2_descs_as_dir(void)
+rend_cache_clean_v2_descs_as_dir(time_t now)
{
digestmap_iter_t *iter;
- time_t cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
+ time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
for (iter = digestmap_iter_init(rend_cache_v2_dir);
!digestmap_iter_done(iter); ) {
const char *key;
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index c51039f1f2..0d64466dbe 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -34,8 +34,8 @@ void rend_encoded_v2_service_descriptor_free(
void rend_intro_point_free(rend_intro_point_t *intro);
void rend_cache_init(void);
-void rend_cache_clean(void);
-void rend_cache_clean_v2_descs_as_dir(void);
+void rend_cache_clean(time_t now);
+void rend_cache_clean_v2_descs_as_dir(time_t now);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_valid_service_id(const char *query);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 2c54f3059d..0ded538bef 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -14,6 +14,7 @@
#include "config.h"
#include "directory.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendservice.h"
@@ -188,14 +189,17 @@ rend_add_service(rend_service_t *service)
if (service->auth_type != REND_NO_AUTH &&
smartlist_len(service->clients) == 0) {
- log_warn(LD_CONFIG, "Hidden service with client authorization but no "
- "clients; ignoring.");
+ log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
+ "clients; ignoring.",
+ escaped(service->directory));
rend_service_free(service);
return;
}
if (!smartlist_len(service->ports)) {
- log_warn(LD_CONFIG, "Hidden service with no ports configured; ignoring.");
+ log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
+ "ignoring.",
+ escaped(service->directory));
rend_service_free(service);
} else {
int dupe = 0;
@@ -274,7 +278,7 @@ parse_port_config(const char *string)
} else {
addrport = smartlist_get(sl,1);
if (strchr(addrport, ':') || strchr(addrport, '.')) {
- if (tor_addr_port_parse(addrport, &addr, &p)<0) {
+ if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
log_warn(LD_CONFIG,"Unparseable address in hidden service port "
"configuration.");
goto err;
@@ -308,7 +312,7 @@ parse_port_config(const char *string)
* normal, but don't actually change the configured services.)
*/
int
-rend_config_services(or_options_t *options, int validate_only)
+rend_config_services(const or_options_t *options, int validate_only)
{
config_line_t *line;
rend_service_t *service = NULL;
@@ -946,8 +950,9 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
time_t now = time(NULL);
char diffie_hellman_hash[DIGEST_LEN];
time_t *access_time;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
@@ -1101,7 +1106,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
} else {
char *rp_nickname;
size_t nickname_field_len;
- routerinfo_t *router;
+ const node_t *node;
int version;
if (*buf == 1) {
rp_nickname = buf+1;
@@ -1128,8 +1133,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
len -= nickname_field_len;
len -= rp_nickname - buf; /* also remove header space used by version, if
* any */
- router = router_get_by_nickname(rp_nickname, 0);
- if (!router) {
+ node = node_get_by_nickname(rp_nickname, 0);
+ if (!node) {
log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
escaped_safe_str_client(rp_nickname));
/* XXXX Add a no-such-router reason? */
@@ -1137,7 +1142,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
goto err;
}
- extend_info = extend_info_from_router(router);
+ extend_info = extend_info_from_node(node);
}
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -1147,7 +1152,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
}
/* Check if we'd refuse to talk to this router */
- if (options->ExcludeNodes && options->StrictNodes &&
+ if (options->StrictNodes &&
routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) {
log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
"exclude, and StrictNodes is set. Refusing service.");
@@ -1435,6 +1440,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
crypto_pk_env_t *intro_key;
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->cpath);
tor_assert(circuit->rend_data);
@@ -1454,7 +1460,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
* redefine this one as a general circuit or close it, depending. */
if (count_established_intro_points(serviceid) >
(int)service->n_intro_points_wanted) { /* XXX023 remove cast */
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ExcludeNodes) {
/* XXXX in some future version, we can test whether the transition is
allowed or not given the actual nodes in the circuit. But for now,
@@ -1468,7 +1474,20 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
"circuit, but we already have enough. Redefining purpose to "
"general; leaving as internal.");
+
TO_CIRCUIT(circuit)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
+
+ {
+ rend_data_t *rend_data = circuit->rend_data;
+ circuit->rend_data = NULL;
+ rend_data_free(rend_data);
+ }
+ {
+ crypto_pk_env_t *intro_key = circuit->intro_key;
+ circuit->intro_key = NULL;
+ crypto_free_pk_env(intro_key);
+ }
+
circuit_has_opened(circuit);
return;
}
@@ -1578,6 +1597,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
hop = circuit->build_state->pending_final_cpath;
tor_assert(hop);
@@ -1735,12 +1755,14 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
for (j = 0; j < smartlist_len(responsible_dirs); j++) {
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
char *hs_dir_ip;
+ const node_t *node;
hs_dir = smartlist_get(responsible_dirs, j);
if (smartlist_digest_isin(renddesc->successful_uploads,
hs_dir->identity_digest))
/* Don't upload descriptor if we succeeded in doing so last time. */
continue;
- if (!router_get_by_digest(hs_dir->identity_digest)) {
+ node = node_get_by_id(hs_dir->identity_digest);
+ if (!node || !node_has_descriptor(node)) {
log_info(LD_REND, "Not sending publish request for v2 descriptor to "
"hidden service directory %s; we don't have its "
"router descriptor. Queuing for later upload.",
@@ -1963,21 +1985,21 @@ void
rend_services_introduce(void)
{
int i,j,r;
- routerinfo_t *router;
+ const node_t *node;
rend_service_t *service;
rend_intro_point_t *intro;
int intro_point_set_changed, prev_intro_nodes;
unsigned int n_intro_points_unexpired;
unsigned int n_intro_points_to_open;
- smartlist_t *intro_routers;
+ smartlist_t *intro_nodes;
time_t now;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
- intro_routers = smartlist_create();
+ intro_nodes = smartlist_create();
now = time(NULL);
for (i=0; i < smartlist_len(rend_service_list); ++i) {
- smartlist_clear(intro_routers);
+ smartlist_clear(intro_nodes);
service = smartlist_get(rend_service_list, i);
tor_assert(service);
@@ -2024,8 +2046,8 @@ rend_services_introduce(void)
continue;
}
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router || !intro_circ) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node || !intro_circ) {
int removing_this_intro_point_changes_the_intro_point_set = 1;
log_info(LD_REND, "Giving up on %s as intro point for %s"
" (circuit disappeared).",
@@ -2071,8 +2093,8 @@ rend_services_introduce(void)
if (intro != NULL && intro->time_expiring == -1)
++n_intro_points_unexpired;
- if (router)
- smartlist_add(intro_routers, router);
+ if (node)
+ smartlist_add(intro_nodes, (void*)node);
} SMARTLIST_FOREACH_END(intro);
if (!intro_point_set_changed &&
@@ -2113,12 +2135,12 @@ rend_services_introduce(void)
for (j = (int)n_intro_points_unexpired;
j < (int)n_intro_points_to_open;
++j) { /* XXXX remove casts */
- router_crn_flags_t flags = CRN_NEED_UPTIME;
+ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
flags |= CRN_ALLOW_INVALID;
- router = router_choose_random_node(intro_routers,
- options->ExcludeNodes, flags);
- if (!router) {
+ node = router_choose_random_node(intro_nodes,
+ options->ExcludeNodes, flags);
+ if (!node) {
log_warn(LD_REND,
"Could only establish %d introduction points for %s; "
"wanted %u.",
@@ -2127,9 +2149,9 @@ rend_services_introduce(void)
break;
}
intro_point_set_changed = 1;
- smartlist_add(intro_routers, router);
+ smartlist_add(intro_nodes, (void*)node);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
intro->time_published = -1;
@@ -2137,7 +2159,7 @@ rend_services_introduce(void)
intro->time_expiring = -1;
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
- safe_str_client(router_describe(router)),
+ safe_str_client(node_describe(node)),
safe_str_client(service->service_id));
}
@@ -2156,7 +2178,7 @@ rend_services_introduce(void)
}
}
}
- smartlist_free(intro_routers);
+ smartlist_free(intro_nodes);
}
/** Regenerate and upload rendezvous service descriptors for all
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index 70389afe9a..8a2994c4c0 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -13,7 +13,7 @@
#define _TOR_RENDSERVICE_H
int num_rend_services(void);
-int rend_config_services(or_options_t *options, int validate_only);
+int rend_config_services(const or_options_t *options, int validate_only);
int rend_service_load_keys(void);
void rend_services_introduce(void);
void rend_consider_services_upload(time_t now);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 1dd3d94fd0..6bbb93b821 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -7,7 +7,7 @@
* \brief Basic history and "reputation" functionality to remember
* which servers have worked in the past, how much bandwidth we've
* been using, which ports we tend to want, and so on; further,
- * exit port statistics and cell statistics.
+ * exit port statistics, cell statistics, and connection statistics.
**/
#include "or.h"
@@ -15,6 +15,7 @@
#include "circuituse.h"
#include "config.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
@@ -643,7 +644,7 @@ rep_hist_dump_stats(time_t now, int severity)
size_t len;
int ret;
unsigned long upt, downt;
- routerinfo_t *r;
+ const node_t *node;
rep_history_clean(now - get_options()->RephistTrackTime);
@@ -657,8 +658,8 @@ rep_hist_dump_stats(time_t now, int severity)
digestmap_iter_get(orhist_it, &digest1, &or_history_p);
or_history = (or_history_t*) or_history_p;
- if ((r = router_get_by_digest(digest1)))
- name1 = r->nickname;
+ if ((node = node_get_by_id(digest1)) && node_get_nickname(node))
+ name1 = node_get_nickname(node);
else
name1 = "(unknown)";
base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
@@ -688,8 +689,8 @@ rep_hist_dump_stats(time_t now, int severity)
lhist_it = digestmap_iter_next(or_history->link_history_map,
lhist_it)) {
digestmap_iter_get(lhist_it, &digest2, &link_history_p);
- if ((r = router_get_by_digest(digest2)))
- name2 = r->nickname;
+ if ((node = node_get_by_id(digest2)) && node_get_nickname(node))
+ name2 = node_get_nickname(node);
else
name2 = "(unknown)";
@@ -823,7 +824,7 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down)
base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN);
if (missing_means_down && hist->start_of_run &&
- !router_get_by_digest(digest)) {
+ !router_get_by_id_digest(digest)) {
/* We think this relay is running, but it's not listed in our
* routerlist. Somehow it fell out without telling us it went
* down. Complain and also correct it. */
@@ -938,28 +939,32 @@ rep_hist_get_router_stability_doc(time_t now)
}
DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
- routerinfo_t *ri;
+ const node_t *node;
char dbuf[BASE64_DIGEST_LEN+1];
char header_buf[512];
char *info;
digest_to_base64(dbuf, id);
- ri = router_get_by_digest(id);
- if (ri) {
- char *ip = tor_dup_ip(ri->addr);
+ node = node_get_by_id(id);
+ if (node) {
+ char ip[INET_NTOA_BUF_LEN+1];
char tbuf[ISO_TIME_LEN+1];
- format_iso_time(tbuf, ri->cache_info.published_on);
+ time_t published = node_get_published_on(node);
+ node_get_address_string(node,ip,sizeof(ip));
+ if (published > 0)
+ format_iso_time(tbuf, published);
+ else
+ strlcpy(tbuf, "???", sizeof(tbuf));
tor_snprintf(header_buf, sizeof(header_buf),
"router %s %s %s\n"
"published %s\n"
"relevant-flags %s%s%s\n"
"declared-uptime %ld\n",
- dbuf, ri->nickname, ip,
+ dbuf, node_get_nickname(node), ip,
tbuf,
- ri->is_running ? "Running " : "",
- ri->is_valid ? "Valid " : "",
- ri->is_hibernating ? "Hibernating " : "",
- ri->uptime);
- tor_free(ip);
+ node->is_running ? "Running " : "",
+ node->is_valid ? "Valid " : "",
+ node->ri && node->ri->is_hibernating ? "Hibernating " : "",
+ node_get_declared_uptime(node));
} else {
tor_snprintf(header_buf, sizeof(header_buf),
"router %s {no descriptor}\n", dbuf);
@@ -1474,7 +1479,7 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b)
{
char *cp = buf;
int i, n;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
uint64_t cutoff;
if (b->num_maxes_set <= b->next_max_idx) {
@@ -1770,10 +1775,13 @@ rep_hist_load_state(or_state_t *state, char **err)
/*********************************************************************/
+typedef struct predicted_port_t {
+ uint16_t port;
+ time_t time;
+} predicted_port_t;
+
/** A list of port numbers that have been used recently. */
static smartlist_t *predicted_ports_list=NULL;
-/** The corresponding most recently used time for each port. */
-static smartlist_t *predicted_ports_times=NULL;
/** We just got an application request for a connection with
* port <b>port</b>. Remember it for the future, so we can keep
@@ -1782,14 +1790,11 @@ static smartlist_t *predicted_ports_times=NULL;
static void
add_predicted_port(time_t now, uint16_t port)
{
- /* XXXX we could just use uintptr_t here, I think. -NM */
- uint16_t *tmp_port = tor_malloc(sizeof(uint16_t));
- time_t *tmp_time = tor_malloc(sizeof(time_t));
- *tmp_port = port;
- *tmp_time = now;
- rephist_total_alloc += sizeof(uint16_t) + sizeof(time_t);
- smartlist_add(predicted_ports_list, tmp_port);
- smartlist_add(predicted_ports_times, tmp_time);
+ predicted_port_t *pp = tor_malloc(sizeof(predicted_port_t));
+ pp->port = port;
+ pp->time = now;
+ rephist_total_alloc += sizeof(*pp);
+ smartlist_add(predicted_ports_list, pp);
}
/** Initialize whatever memory and structs are needed for predicting
@@ -1800,7 +1805,6 @@ static void
predicted_ports_init(void)
{
predicted_ports_list = smartlist_create();
- predicted_ports_times = smartlist_create();
add_predicted_port(time(NULL), 80); /* add one to kickstart us */
}
@@ -1810,12 +1814,11 @@ predicted_ports_init(void)
static void
predicted_ports_free(void)
{
- rephist_total_alloc -= smartlist_len(predicted_ports_list)*sizeof(uint16_t);
- SMARTLIST_FOREACH(predicted_ports_list, char *, cp, tor_free(cp));
+ rephist_total_alloc -=
+ smartlist_len(predicted_ports_list)*sizeof(predicted_port_t);
+ SMARTLIST_FOREACH(predicted_ports_list, predicted_port_t *,
+ pp, tor_free(pp));
smartlist_free(predicted_ports_list);
- rephist_total_alloc -= smartlist_len(predicted_ports_times)*sizeof(time_t);
- SMARTLIST_FOREACH(predicted_ports_times, char *, cp, tor_free(cp));
- smartlist_free(predicted_ports_times);
}
/** Remember that <b>port</b> has been asked for as of time <b>now</b>.
@@ -1825,24 +1828,17 @@ predicted_ports_free(void)
void
rep_hist_note_used_port(time_t now, uint16_t port)
{
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
-
tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
if (!port) /* record nothing */
return;
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_port == port) {
- *tmp_time = now;
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (pp->port == port) {
+ pp->time = now;
return;
}
- }
+ } SMARTLIST_FOREACH_END(pp);
/* it's not there yet; we need to add it */
add_predicted_port(now, port);
}
@@ -1851,36 +1847,28 @@ rep_hist_note_used_port(time_t now, uint16_t port)
* we'll want to make connections to the same port in the future. */
#define PREDICTED_CIRCS_RELEVANCE_TIME (60*60)
-/** Return a pointer to the list of port numbers that
+/** Return a newly allocated pointer to a list of uint16_t * for ports that
* are likely to be asked for in the near future.
- *
- * The caller promises not to mess with it.
*/
smartlist_t *
rep_hist_get_predicted_ports(time_t now)
{
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
-
+ smartlist_t *out = smartlist_create();
tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
/* clean out obsolete entries */
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- log_debug(LD_CIRC, "Expiring predicted port %d", *tmp_port);
- smartlist_del(predicted_ports_list, i);
- smartlist_del(predicted_ports_times, i);
- rephist_total_alloc -= sizeof(uint16_t)+sizeof(time_t);
- tor_free(tmp_port);
- tor_free(tmp_time);
- i--;
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (pp->time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
+ log_debug(LD_CIRC, "Expiring predicted port %d", pp->port);
+
+ rephist_total_alloc -= sizeof(predicted_port_t);
+ tor_free(pp);
+ SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
+ } else {
+ smartlist_add(out, tor_memdup(&pp->port, sizeof(uint16_t)));
}
- }
- return predicted_ports_list;
+ } SMARTLIST_FOREACH_END(pp);
+ return out;
}
/** The user asked us to do a resolve. Rather than keeping track of
@@ -2116,7 +2104,9 @@ rep_hist_exit_stats_term(void)
tor_free(exit_streams);
}
-/** Helper for qsort: compare two ints. */
+/** Helper for qsort: compare two ints. Does not handle overflow properly,
+ * but works fine for sorting an array of port numbers, which is what we use
+ * it for. */
static int
_compare_int(const void *x, const void *y)
{
@@ -2124,7 +2114,8 @@ _compare_int(const void *x, const void *y)
}
/** Return a newly allocated string containing the exit port statistics
- * until <b>now</b>, or NULL if we're not collecting exit stats. */
+ * until <b>now</b>, or NULL if we're not collecting exit stats. Caller
+ * must ensure start_of_exit_stats_interval is in the past. */
char *
rep_hist_format_exit_stats(time_t now)
{
@@ -2143,6 +2134,8 @@ rep_hist_format_exit_stats(time_t now)
if (!start_of_exit_stats_interval)
return NULL; /* Not initialized. */
+ tor_assert(now >= start_of_exit_stats_interval);
+
/* Go through all ports to find the n ports that saw most written and
* read bytes.
*
@@ -2374,41 +2367,60 @@ typedef struct circ_buffer_stats_t {
/** List of circ_buffer_stats_t. */
static smartlist_t *circuits_for_buffer_stats = NULL;
+/** Remember cell statistics <b>mean_num_cells_in_queue</b>,
+ * <b>mean_time_cells_in_queue</b>, and <b>processed_cells</b> of a
+ * circuit. */
+void
+rep_hist_add_buffer_stats(double mean_num_cells_in_queue,
+ double mean_time_cells_in_queue, uint32_t processed_cells)
+{
+ circ_buffer_stats_t *stat;
+ if (!start_of_buffer_stats_interval)
+ return; /* Not initialized. */
+ stat = tor_malloc_zero(sizeof(circ_buffer_stats_t));
+ stat->mean_num_cells_in_queue = mean_num_cells_in_queue;
+ stat->mean_time_cells_in_queue = mean_time_cells_in_queue;
+ stat->processed_cells = processed_cells;
+ if (!circuits_for_buffer_stats)
+ circuits_for_buffer_stats = smartlist_create();
+ smartlist_add(circuits_for_buffer_stats, stat);
+}
+
/** Remember cell statistics for circuit <b>circ</b> at time
* <b>end_of_interval</b> and reset cell counters in case the circuit
* remains open in the next measurement interval. */
void
rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
{
- circ_buffer_stats_t *stat;
time_t start_of_interval;
int interval_length;
or_circuit_t *orcirc;
+ double mean_num_cells_in_queue, mean_time_cells_in_queue;
+ uint32_t processed_cells;
if (CIRCUIT_IS_ORIGIN(circ))
return;
orcirc = TO_OR_CIRCUIT(circ);
if (!orcirc->processed_cells)
return;
- if (!circuits_for_buffer_stats)
- circuits_for_buffer_stats = smartlist_create();
- start_of_interval = circ->timestamp_created.tv_sec >
- start_of_buffer_stats_interval ?
+ start_of_interval = (circ->timestamp_created.tv_sec >
+ start_of_buffer_stats_interval) ?
circ->timestamp_created.tv_sec :
start_of_buffer_stats_interval;
interval_length = (int) (end_of_interval - start_of_interval);
if (interval_length <= 0)
return;
- stat = tor_malloc_zero(sizeof(circ_buffer_stats_t));
- stat->processed_cells = orcirc->processed_cells;
+ processed_cells = orcirc->processed_cells;
/* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */
- stat->mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time /
+ mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time /
(double) interval_length / 1000.0 / 2.0;
- stat->mean_time_cells_in_queue =
+ mean_time_cells_in_queue =
(double) orcirc->total_cell_waiting_time /
(double) orcirc->processed_cells;
- smartlist_add(circuits_for_buffer_stats, stat);
orcirc->total_cell_waiting_time = 0;
orcirc->processed_cells = 0;
+ rep_hist_add_buffer_stats(mean_num_cells_in_queue,
+ mean_time_cells_in_queue,
+ processed_cells);
}
/** Sorting helper: return -1, 1, or 0 based on comparison of two
@@ -2430,136 +2442,536 @@ _buffer_stats_compare_entries(const void **_a, const void **_b)
void
rep_hist_buffer_stats_term(void)
{
- start_of_buffer_stats_interval = 0;
+ rep_hist_reset_buffer_stats(0);
+}
+
+/** Clear history of circuit statistics and set the measurement interval
+ * start to <b>now</b>. */
+void
+rep_hist_reset_buffer_stats(time_t now)
+{
if (!circuits_for_buffer_stats)
circuits_for_buffer_stats = smartlist_create();
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *,
stat, tor_free(stat));
smartlist_clear(circuits_for_buffer_stats);
+ start_of_buffer_stats_interval = now;
}
-/** Write buffer statistics to $DATADIR/stats/buffer-stats and return when
- * we would next want to write exit stats. */
-time_t
-rep_hist_buffer_stats_write(time_t now)
+/** Return a newly allocated string containing the buffer statistics until
+ * <b>now</b>, or NULL if we're not collecting buffer stats. Caller must
+ * ensure start_of_buffer_stats_interval is in the past. */
+char *
+rep_hist_format_buffer_stats(time_t now)
{
- char *statsdir = NULL, *filename = NULL;
- char written[ISO_TIME_LEN+1];
- open_file_t *open_file = NULL;
- FILE *out;
#define SHARES 10
int processed_cells[SHARES], circs_in_share[SHARES],
number_of_circuits, i;
double queued_cells[SHARES], time_in_queue[SHARES];
- smartlist_t *str_build = NULL;
- char *str = NULL, *buf = NULL;
- circuit_t *circ;
+ char *buf = NULL;
+ smartlist_t *processed_cells_strings, *queued_cells_strings,
+ *time_in_queue_strings;
+ char *processed_cells_string, *queued_cells_string,
+ *time_in_queue_string;
+ char t[ISO_TIME_LEN+1];
+ char *result;
if (!start_of_buffer_stats_interval)
- return 0; /* Not initialized. */
- if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
- goto done; /* Not ready to write */
+ return NULL; /* Not initialized. */
- str_build = smartlist_create();
+ tor_assert(now >= start_of_buffer_stats_interval);
- /* add current circuits to stats */
- for (circ = _circuit_get_global_list(); circ; circ = circ->next)
- rep_hist_buffer_stats_add_circ(circ, now);
- /* calculate deciles */
+ /* Calculate deciles if we saw at least one circuit. */
memset(processed_cells, 0, SHARES * sizeof(int));
memset(circs_in_share, 0, SHARES * sizeof(int));
memset(queued_cells, 0, SHARES * sizeof(double));
memset(time_in_queue, 0, SHARES * sizeof(double));
if (!circuits_for_buffer_stats)
circuits_for_buffer_stats = smartlist_create();
- smartlist_sort(circuits_for_buffer_stats,
- _buffer_stats_compare_entries);
number_of_circuits = smartlist_len(circuits_for_buffer_stats);
- if (number_of_circuits < 1) {
- log_info(LD_HIST, "Attempt to write cell statistics to disk failed. "
- "We haven't seen a single circuit to report about.");
- goto done;
+ if (number_of_circuits > 0) {
+ smartlist_sort(circuits_for_buffer_stats,
+ _buffer_stats_compare_entries);
+ i = 0;
+ SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats,
+ circ_buffer_stats_t *, stat)
+ {
+ int share = i++ * SHARES / number_of_circuits;
+ processed_cells[share] += stat->processed_cells;
+ queued_cells[share] += stat->mean_num_cells_in_queue;
+ time_in_queue[share] += stat->mean_time_cells_in_queue;
+ circs_in_share[share]++;
+ }
+ SMARTLIST_FOREACH_END(stat);
}
- i = 0;
- SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats,
- circ_buffer_stats_t *, stat)
- {
- int share = i++ * SHARES / number_of_circuits;
- processed_cells[share] += stat->processed_cells;
- queued_cells[share] += stat->mean_num_cells_in_queue;
- time_in_queue[share] += stat->mean_time_cells_in_queue;
- circs_in_share[share]++;
- }
- SMARTLIST_FOREACH_END(stat);
- /* clear buffer stats history */
- SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *,
- stat, tor_free(stat));
- smartlist_clear(circuits_for_buffer_stats);
- /* write to file */
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
- goto done;
- filename = get_datadir_fname2("stats", "buffer-stats");
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT,
- 0600, &open_file);
- if (!out)
- goto done;
- format_iso_time(written, now);
- if (fprintf(out, "cell-stats-end %s (%d s)\n", written,
- (unsigned) (now - start_of_buffer_stats_interval)) < 0)
- goto done;
+
+ /* Write deciles to strings. */
+ processed_cells_strings = smartlist_create();
+ queued_cells_strings = smartlist_create();
+ time_in_queue_strings = smartlist_create();
for (i = 0; i < SHARES; i++) {
tor_asprintf(&buf,"%d", !circs_in_share[i] ? 0 :
processed_cells[i] / circs_in_share[i]);
- smartlist_add(str_build, buf);
+ smartlist_add(processed_cells_strings, buf);
}
- str = smartlist_join_strings(str_build, ",", 0, NULL);
- if (fprintf(out, "cell-processed-cells %s\n", str) < 0)
- goto done;
- tor_free(str);
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_clear(str_build);
for (i = 0; i < SHARES; i++) {
tor_asprintf(&buf, "%.2f", circs_in_share[i] == 0 ? 0.0 :
queued_cells[i] / (double) circs_in_share[i]);
- smartlist_add(str_build, buf);
+ smartlist_add(queued_cells_strings, buf);
}
- str = smartlist_join_strings(str_build, ",", 0, NULL);
- if (fprintf(out, "cell-queued-cells %s\n", str) < 0)
- goto done;
- tor_free(str);
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_clear(str_build);
for (i = 0; i < SHARES; i++) {
tor_asprintf(&buf, "%.0f", circs_in_share[i] == 0 ? 0.0 :
time_in_queue[i] / (double) circs_in_share[i]);
- smartlist_add(str_build, buf);
+ smartlist_add(time_in_queue_strings, buf);
}
- str = smartlist_join_strings(str_build, ",", 0, NULL);
- if (fprintf(out, "cell-time-in-queue %s\n", str) < 0)
- goto done;
- tor_free(str);
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_free(str_build);
- str_build = NULL;
- if (fprintf(out, "cell-circuits-per-decile %d\n",
- (number_of_circuits + SHARES - 1) / SHARES) < 0)
+
+ /* Join all observations in single strings. */
+ processed_cells_string = smartlist_join_strings(processed_cells_strings,
+ ",", 0, NULL);
+ queued_cells_string = smartlist_join_strings(queued_cells_strings,
+ ",", 0, NULL);
+ time_in_queue_string = smartlist_join_strings(time_in_queue_strings,
+ ",", 0, NULL);
+ SMARTLIST_FOREACH(processed_cells_strings, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(queued_cells_strings, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(time_in_queue_strings, char *, cp, tor_free(cp));
+ smartlist_free(processed_cells_strings);
+ smartlist_free(queued_cells_strings);
+ smartlist_free(time_in_queue_strings);
+
+ /* Put everything together. */
+ format_iso_time(t, now);
+ tor_asprintf(&result, "cell-stats-end %s (%d s)\n"
+ "cell-processed-cells %s\n"
+ "cell-queued-cells %s\n"
+ "cell-time-in-queue %s\n"
+ "cell-circuits-per-decile %d\n",
+ t, (unsigned) (now - start_of_buffer_stats_interval),
+ processed_cells_string,
+ queued_cells_string,
+ time_in_queue_string,
+ (number_of_circuits + SHARES - 1) / SHARES);
+ tor_free(processed_cells_string);
+ tor_free(queued_cells_string);
+ tor_free(time_in_queue_string);
+ return result;
+#undef SHARES
+}
+
+/** If 24 hours have passed since the beginning of the current buffer
+ * stats period, write buffer stats to $DATADIR/stats/buffer-stats
+ * (possibly overwriting an existing file) and reset counters. Return
+ * when we would next want to write buffer stats or 0 if we never want to
+ * write. */
+time_t
+rep_hist_buffer_stats_write(time_t now)
+{
+ circuit_t *circ;
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_buffer_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write */
+
+ /* Add open circuits to the history. */
+ for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
+ rep_hist_buffer_stats_add_circ(circ, now);
+ }
+
+ /* Generate history string. */
+ str = rep_hist_format_buffer_stats(now);
+
+ /* Reset both buffer history and counters of open circuits. */
+ rep_hist_reset_buffer_stats(now);
+
+ /* Try to write to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
goto done;
- finish_writing_to_file(open_file);
- open_file = NULL;
- start_of_buffer_stats_interval = now;
+ }
+ filename = get_datadir_fname2("stats", "buffer-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write buffer stats to disk!");
+
done:
- if (open_file)
- abort_writing_to_file(open_file);
+ tor_free(str);
tor_free(filename);
tor_free(statsdir);
- if (str_build) {
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_free(str_build);
+ return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
+}
+
+/*** Descriptor serving statistics ***/
+
+/** Digestmap to track which descriptors were downloaded this stats
+ * collection interval. It maps descriptor digest to pointers to 1,
+ * effectively turning this into a list. */
+static digestmap_t *served_descs = NULL;
+
+/** Number of how many descriptors were downloaded in total during this
+ * interval. */
+static unsigned long total_descriptor_downloads;
+
+/** Start time of served descs stats or 0 if we're not collecting those. */
+static time_t start_of_served_descs_stats_interval;
+
+/** Initialize descriptor stats. */
+void
+rep_hist_desc_stats_init(time_t now)
+{
+ if (served_descs) {
+ log_warn(LD_BUG, "Called rep_hist_desc_stats_init() when desc stats were "
+ "already initialized. This is probably harmless.");
+ return; // Already initialized
}
+ served_descs = digestmap_new();
+ total_descriptor_downloads = 0;
+ start_of_served_descs_stats_interval = now;
+}
+
+/** Reset served descs stats to empty, starting a new interval <b>now</b>. */
+static void
+rep_hist_reset_desc_stats(time_t now)
+{
+ rep_hist_desc_stats_term();
+ rep_hist_desc_stats_init(now);
+}
+
+/** Stop collecting served descs stats, so that rep_hist_desc_stats_init() is
+ * safe to be called again. */
+void
+rep_hist_desc_stats_term(void)
+{
+ digestmap_free(served_descs, NULL);
+ served_descs = NULL;
+ start_of_served_descs_stats_interval = 0;
+ total_descriptor_downloads = 0;
+}
+
+/** Helper for rep_hist_desc_stats_write(). Return a newly allocated string
+ * containing the served desc statistics until now, or NULL if we're not
+ * collecting served desc stats. Caller must ensure that now is not before
+ * start_of_served_descs_stats_interval. */
+static char *
+rep_hist_format_desc_stats(time_t now)
+{
+ char t[ISO_TIME_LEN+1];
+ char *result;
+
+ digestmap_iter_t *iter;
+ const char *key;
+ void *val;
+ unsigned size;
+ int *vals;
+ int n = 0;
+
+ if (!start_of_served_descs_stats_interval)
+ return NULL;
+
+ size = digestmap_size(served_descs);
+ vals = tor_malloc(size * sizeof(int));
+
+ for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter);
+ iter = digestmap_iter_next(served_descs, iter) ) {
+ uintptr_t count;
+ digestmap_iter_get(iter, &key, &val);
+ count = (uintptr_t)val;
+ vals[n++] = (int)count;
+ (void)key;
+ }
+
+ format_iso_time(t, now);
+
+ tor_asprintf(&result,
+ "served-descs-stats-end %s (%d s) total=%lu unique=%u "
+ "max=%d q3=%d md=%d q1=%d min=%d\n",
+ t,
+ (unsigned) (now - start_of_served_descs_stats_interval),
+ total_descriptor_downloads,
+ size,
+ find_nth_int(vals, size, size-1),
+ find_nth_int(vals, size, (3*size-1)/4),
+ find_nth_int(vals, size, (size-1)/2),
+ find_nth_int(vals, size, (size-1)/4),
+ find_nth_int(vals, size, 0));
+
+ tor_free(vals);
+ return result;
+}
+
+/** If WRITE_STATS_INTERVAL seconds have passed since the beginning of
+ * the current served desc stats interval, write the stats to
+ * $DATADIR/stats/served-desc-stats (possibly appending to an existing file)
+ * and reset the state for the next interval. Return when we would next want
+ * to write served desc stats or 0 if we won't want to write. */
+time_t
+rep_hist_desc_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_served_descs_stats_interval)
+ return 0; /* We're not collecting stats. */
+ if (start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL > now)
+ return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL;
+
+ str = rep_hist_format_desc_stats(now);
+
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
+ goto done;
+ }
+ filename = get_datadir_fname2("stats", "served-desc-stats");
+ if (append_bytes_to_file(filename, str, strlen(str), 0) < 0)
+ log_warn(LD_HIST, "Unable to write served descs statistics to disk!");
+
+ rep_hist_reset_desc_stats(now);
+
+ done:
+ tor_free(statsdir);
+ tor_free(filename);
tor_free(str);
-#undef SHARES
- return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
+ return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL;
+}
+
+void
+rep_hist_note_desc_served(const char * desc)
+{
+ void *val;
+ uintptr_t count;
+ if (!served_descs)
+ return; // We're not collecting stats
+ val = digestmap_get(served_descs, desc);
+ count = (uintptr_t)val;
+ if (count != INT_MAX)
+ ++count;
+ digestmap_set(served_descs, desc, (void*)count);
+ total_descriptor_downloads++;
+}
+
+/*** Connection statistics ***/
+
+/** Start of the current connection stats interval or 0 if we're not
+ * collecting connection statistics. */
+static time_t start_of_conn_stats_interval;
+
+/** Initialize connection stats. */
+void
+rep_hist_conn_stats_init(time_t now)
+{
+ start_of_conn_stats_interval = now;
+}
+
+/* Count connections that we read and wrote less than these many bytes
+ * from/to as below threshold. */
+#define BIDI_THRESHOLD 20480
+
+/* Count connections that we read or wrote at least this factor as many
+ * bytes from/to than we wrote or read to/from as mostly reading or
+ * writing. */
+#define BIDI_FACTOR 10
+
+/* Interval length in seconds for considering read and written bytes for
+ * connection stats. */
+#define BIDI_INTERVAL 10
+
+/* Start of next BIDI_INTERVAL second interval. */
+static time_t bidi_next_interval = 0;
+
+/* Number of connections that we read and wrote less than BIDI_THRESHOLD
+ * bytes from/to in BIDI_INTERVAL seconds. */
+static uint32_t below_threshold = 0;
+
+/* Number of connections that we read at least BIDI_FACTOR times more
+ * bytes from than we wrote to in BIDI_INTERVAL seconds. */
+static uint32_t mostly_read = 0;
+
+/* Number of connections that we wrote at least BIDI_FACTOR times more
+ * bytes to than we read from in BIDI_INTERVAL seconds. */
+static uint32_t mostly_written = 0;
+
+/* Number of connections that we read and wrote at least BIDI_THRESHOLD
+ * bytes from/to, but not BIDI_FACTOR times more in either direction in
+ * BIDI_INTERVAL seconds. */
+static uint32_t both_read_and_written = 0;
+
+/* Entry in a map from connection ID to the number of read and written
+ * bytes on this connection in a BIDI_INTERVAL second interval. */
+typedef struct bidi_map_entry_t {
+ HT_ENTRY(bidi_map_entry_t) node;
+ uint64_t conn_id; /**< Connection ID */
+ size_t read; /**< Number of read bytes */
+ size_t written; /**< Number of written bytes */
+} bidi_map_entry_t;
+
+/** Map of OR connections together with the number of read and written
+ * bytes in the current BIDI_INTERVAL second interval. */
+static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map =
+ HT_INITIALIZER();
+
+static int
+bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b)
+{
+ return a->conn_id == b->conn_id;
+}
+
+static unsigned
+bidi_map_ent_hash(const bidi_map_entry_t *entry)
+{
+ return (unsigned) entry->conn_id;
+}
+
+HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq);
+HT_GENERATE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq, 0.6, malloc, realloc, free);
+
+static void
+bidi_map_free(void)
+{
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ HT_CLEAR(bidimap, &bidi_map);
+}
+
+/** Reset counters for conn statistics. */
+void
+rep_hist_reset_conn_stats(time_t now)
+{
+ start_of_conn_stats_interval = now;
+ below_threshold = 0;
+ mostly_read = 0;
+ mostly_written = 0;
+ both_read_and_written = 0;
+ bidi_map_free();
+}
+
+/** Stop collecting connection stats in a way that we can re-start doing
+ * so in rep_hist_conn_stats_init(). */
+void
+rep_hist_conn_stats_term(void)
+{
+ rep_hist_reset_conn_stats(0);
+}
+
+/** We read <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
+ * connection <b>conn_id</b> in second <b>when</b>. If this is the first
+ * observation in a new interval, sum up the last observations. Add bytes
+ * for this connection. */
+void
+rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when)
+{
+ if (!start_of_conn_stats_interval)
+ return;
+ /* Initialize */
+ if (bidi_next_interval == 0)
+ bidi_next_interval = when + BIDI_INTERVAL;
+ /* Sum up last period's statistics */
+ if (when >= bidi_next_interval) {
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ if (ent->read + ent->written < BIDI_THRESHOLD)
+ below_threshold++;
+ else if (ent->read >= ent->written * BIDI_FACTOR)
+ mostly_read++;
+ else if (ent->written >= ent->read * BIDI_FACTOR)
+ mostly_written++;
+ else
+ both_read_and_written++;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ while (when >= bidi_next_interval)
+ bidi_next_interval += BIDI_INTERVAL;
+ log_info(LD_GENERAL, "%d below threshold, %d mostly read, "
+ "%d mostly written, %d both read and written.",
+ below_threshold, mostly_read, mostly_written,
+ both_read_and_written);
+ }
+ /* Add this connection's bytes. */
+ if (num_read > 0 || num_written > 0) {
+ bidi_map_entry_t *entry, lookup;
+ lookup.conn_id = conn_id;
+ entry = HT_FIND(bidimap, &bidi_map, &lookup);
+ if (entry) {
+ entry->written += num_written;
+ entry->read += num_read;
+ } else {
+ entry = tor_malloc_zero(sizeof(bidi_map_entry_t));
+ entry->conn_id = conn_id;
+ entry->written = num_written;
+ entry->read = num_read;
+ HT_INSERT(bidimap, &bidi_map, entry);
+ }
+ }
+}
+
+/** Return a newly allocated string containing the connection statistics
+ * until <b>now</b>, or NULL if we're not collecting conn stats. Caller must
+ * ensure start_of_conn_stats_interval is in the past. */
+char *
+rep_hist_format_conn_stats(time_t now)
+{
+ char *result, written[ISO_TIME_LEN+1];
+
+ if (!start_of_conn_stats_interval)
+ return NULL; /* Not initialized. */
+
+ tor_assert(now >= start_of_conn_stats_interval);
+
+ format_iso_time(written, now);
+ tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n",
+ written,
+ (unsigned) (now - start_of_conn_stats_interval),
+ below_threshold,
+ mostly_read,
+ mostly_written,
+ both_read_and_written);
+ return result;
+}
+
+/** If 24 hours have passed since the beginning of the current conn stats
+ * period, write conn stats to $DATADIR/stats/conn-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write conn stats or 0 if we never want to write. */
+time_t
+rep_hist_conn_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_conn_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write */
+
+ /* Generate history string. */
+ str = rep_hist_format_conn_stats(now);
+
+ /* Reset counters. */
+ rep_hist_reset_conn_stats(now);
+
+ /* Try to write to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
+ goto done;
+ }
+ filename = get_datadir_fname2("stats", "conn-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write conn stats to disk!");
+
+ done:
+ tor_free(str);
+ tor_free(filename);
+ tor_free(statsdir);
+ return start_of_conn_stats_interval + WRITE_STATS_INTERVAL;
}
/** Free all storage held by the OR/link history caches, by the
@@ -2576,11 +2988,15 @@ rep_hist_free_all(void)
tor_free(exit_streams);
built_last_stability_doc_at = 0;
predicted_ports_free();
+ bidi_map_free();
+
if (circuits_for_buffer_stats) {
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, s,
tor_free(s));
smartlist_free(circuits_for_buffer_stats);
circuits_for_buffer_stats = NULL;
}
+ rep_hist_desc_stats_term();
+ total_descriptor_downloads = 0;
}
diff --git a/src/or/rephist.h b/src/or/rephist.h
index b06a39ed59..0a3e46ae1a 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -77,6 +77,23 @@ void rep_hist_buffer_stats_add_circ(circuit_t *circ,
time_t end_of_interval);
time_t rep_hist_buffer_stats_write(time_t now);
void rep_hist_buffer_stats_term(void);
+void rep_hist_add_buffer_stats(double mean_num_cells_in_queue,
+ double mean_time_cells_in_queue, uint32_t processed_cells);
+char *rep_hist_format_buffer_stats(time_t now);
+void rep_hist_reset_buffer_stats(time_t now);
+
+void rep_hist_desc_stats_init(time_t now);
+void rep_hist_note_desc_served(const char * desc);
+void rep_hist_desc_stats_term(void);
+time_t rep_hist_desc_stats_write(time_t now);
+
+void rep_hist_conn_stats_init(time_t now);
+void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when);
+void rep_hist_reset_conn_stats(time_t now);
+char *rep_hist_format_conn_stats(time_t now);
+time_t rep_hist_conn_stats_write(time_t now);
+void rep_hist_conn_stats_term(void);
#endif
diff --git a/src/or/router.c b/src/or/router.c
index 365e888af9..8fe45dd6f8 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -7,6 +7,7 @@
#define ROUTER_PRIVATE
#include "or.h"
+#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
#include "config.h"
@@ -19,6 +20,7 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "relay.h"
#include "rephist.h"
@@ -82,6 +84,11 @@ static authority_cert_t *legacy_key_certificate = NULL;
static void
set_onion_key(crypto_pk_env_t *k)
{
+ if (onionkey && !crypto_pk_cmp_keys(onionkey, k)) {
+ /* k is already our onion key; free it and return */
+ crypto_free_pk_env(k);
+ return;
+ }
tor_mutex_acquire(key_lock);
crypto_free_pk_env(onionkey);
onionkey = k;
@@ -149,8 +156,8 @@ assert_identity_keys_ok(void)
} else {
/* assert that we have set the client and server keys to be unequal */
if (server_identitykey)
- tor_assert(0!=crypto_pk_cmp_keys(client_identitykey,
- server_identitykey));
+ tor_assert(0!=crypto_pk_cmp_keys(client_identitykey,
+ server_identitykey));
}
}
@@ -477,6 +484,16 @@ v3_authority_check_key_expiry(void)
last_warned = now;
}
+int
+router_initialize_tls_context(void)
+{
+ return tor_tls_context_init(public_server_mode(get_options()),
+ get_tlsclient_identity_key(),
+ server_mode(get_options()) ?
+ get_server_identity_key() : NULL,
+ MAX_SSL_KEY_LIFETIME_ADVERTISED);
+}
+
/** Initialize all OR private keys, and the TLS context, as necessary.
* On OPs, this only initializes the tls context. Return 0 on success,
* or -1 if Tor should die.
@@ -493,8 +510,8 @@ init_keys(void)
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
char *cp;
- or_options_t *options = get_options();
- authority_type_t type;
+ const or_options_t *options = get_options();
+ dirinfo_type_t type;
time_t now = time(NULL);
trusted_dir_server_t *ds;
int v3_digest_set = 0;
@@ -523,10 +540,7 @@ init_keys(void)
}
set_client_identity_key(prkey);
/* Create a TLS context. */
- if (tor_tls_context_init(0,
- get_tlsclient_identity_key(),
- NULL,
- MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
+ if (router_initialize_tls_context() < 0) {
log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
return -1;
}
@@ -619,13 +633,11 @@ init_keys(void)
tor_free(keydir);
/* 3. Initialize link key and TLS context. */
- if (tor_tls_context_init(public_server_mode(options),
- get_tlsclient_identity_key(),
- get_server_identity_key(),
- MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
+ if (router_initialize_tls_context() < 0) {
log_err(LD_GENERAL,"Error initializing TLS context");
return -1;
}
+
/* 4. Build our router descriptor. */
/* Must be called after keys are initialized. */
mydesc = router_get_my_descriptor();
@@ -695,11 +707,12 @@ init_keys(void)
}
/* 6b. [authdirserver only] add own key to approved directories. */
crypto_pk_get_digest(get_server_identity_key(), digest);
- type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) |
- (options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) |
- (options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) |
- (options->BridgeAuthoritativeDir ? BRIDGE_AUTHORITY : NO_AUTHORITY) |
- (options->HSAuthoritativeDir ? HIDSERV_AUTHORITY : NO_AUTHORITY));
+ type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
+ (options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
+ (options->V3AuthoritativeDir ?
+ (V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
+ (options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) |
+ (options->HSAuthoritativeDir ? HIDSERV_DIRINFO : NO_DIRINFO));
ds = router_get_trusteddirserver_by_digest(digest);
if (!ds) {
@@ -721,7 +734,7 @@ init_keys(void)
type, ds->type);
ds->type = type;
}
- if (v3_digest_set && (ds->type & V3_AUTHORITY) &&
+ if (v3_digest_set && (ds->type & V3_DIRINFO) &&
tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
log_warn(LD_DIR, "V3 identity key does not match identity declared in "
"DirServer line. Adjusting.");
@@ -760,7 +773,7 @@ router_reset_reachability(void)
int
check_whether_orport_reachable(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return options->AssumeReachable ||
can_reach_or_port;
}
@@ -769,10 +782,10 @@ check_whether_orport_reachable(void)
int
check_whether_dirport_reachable(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return !options->DirPort ||
options->AssumeReachable ||
- we_are_hibernating() ||
+ net_is_disabled() ||
can_reach_dir_port;
}
@@ -784,7 +797,7 @@ check_whether_dirport_reachable(void)
* a DirPort.
*/
static int
-decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
+decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
{
static int advertising=1; /* start out assuming we will advertise */
int new_choice=1;
@@ -798,7 +811,7 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
return 0;
if (authdir_mode(options)) /* always publish */
return dir_port;
- if (we_are_hibernating())
+ if (net_is_disabled())
return 0;
if (!check_whether_dirport_reachable())
return 0;
@@ -849,14 +862,14 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
void
consider_testing_reachability(int test_or, int test_dir)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
int orport_reachable = check_whether_orport_reachable();
tor_addr_t addr;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!me)
return;
- if (routerset_contains_router(options->ExcludeNodes, me) &&
+ if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
options->StrictNodes) {
/* If we've excluded ourself, and StrictNodes is set, we can't test
* ourself. */
@@ -876,11 +889,14 @@ consider_testing_reachability(int test_or, int test_dir)
}
if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
+ extend_info_t *ei;
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port);
- circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
- CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ ei = extend_info_from_router(me);
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ extend_info_free(ei);
}
tor_addr_from_ipv4h(&addr, me->addr);
@@ -903,11 +919,11 @@ consider_testing_reachability(int test_or, int test_dir)
void
router_orport_found_reachable(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_or_port && me) {
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
- get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
+ get_options()->_PublishServerDescriptor != NO_DIRINFO ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty("ORPort found reachable");
@@ -921,7 +937,7 @@ router_orport_found_reachable(void)
void
router_dirport_found_reachable(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_dir_port && me) {
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.");
@@ -963,11 +979,19 @@ router_perform_bandwidth_test(int num_circs, time_t now)
}
}
+/** Return true iff our network is in some sense disabled: either we're
+ * hibernating, entering hibernation, or */
+int
+net_is_disabled(void)
+{
+ return get_options()->DisableNetwork || we_are_hibernating();
+}
+
/** Return true iff we believe ourselves to be an authoritative
* directory server.
*/
int
-authdir_mode(or_options_t *options)
+authdir_mode(const or_options_t *options)
{
return options->AuthoritativeDir != 0;
}
@@ -975,7 +999,7 @@ authdir_mode(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v1(or_options_t *options)
+authdir_mode_v1(const or_options_t *options)
{
return authdir_mode(options) && options->V1AuthoritativeDir != 0;
}
@@ -983,7 +1007,7 @@ authdir_mode_v1(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v2(or_options_t *options)
+authdir_mode_v2(const or_options_t *options)
{
return authdir_mode(options) && options->V2AuthoritativeDir != 0;
}
@@ -991,13 +1015,13 @@ authdir_mode_v2(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v3(or_options_t *options)
+authdir_mode_v3(const or_options_t *options)
{
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
/** Return true iff we are a v1, v2, or v3 directory authority. */
int
-authdir_mode_any_main(or_options_t *options)
+authdir_mode_any_main(const or_options_t *options)
{
return options->V1AuthoritativeDir ||
options->V2AuthoritativeDir ||
@@ -1006,16 +1030,16 @@ authdir_mode_any_main(or_options_t *options)
/** Return true if we believe ourselves to be any kind of
* authoritative directory beyond just a hidserv authority. */
int
-authdir_mode_any_nonhidserv(or_options_t *options)
+authdir_mode_any_nonhidserv(const or_options_t *options)
{
return options->BridgeAuthoritativeDir ||
authdir_mode_any_main(options);
}
/** Return true iff we are an authoritative directory server that is
* authoritative about receiving and serving descriptors of type
- * <b>purpose</b> its dirport. Use -1 for "any purpose". */
+ * <b>purpose</b> on its dirport. Use -1 for "any purpose". */
int
-authdir_mode_handles_descs(or_options_t *options, int purpose)
+authdir_mode_handles_descs(const or_options_t *options, int purpose)
{
if (purpose < 0)
return authdir_mode_any_nonhidserv(options);
@@ -1030,7 +1054,7 @@ authdir_mode_handles_descs(or_options_t *options, int purpose)
* publishes its own network statuses.
*/
int
-authdir_mode_publishes_statuses(or_options_t *options)
+authdir_mode_publishes_statuses(const or_options_t *options)
{
if (authdir_mode_bridge(options))
return 0;
@@ -1040,7 +1064,7 @@ authdir_mode_publishes_statuses(or_options_t *options)
* tests reachability of the descriptors it learns about.
*/
int
-authdir_mode_tests_reachability(or_options_t *options)
+authdir_mode_tests_reachability(const or_options_t *options)
{
return authdir_mode_handles_descs(options, -1);
}
@@ -1048,7 +1072,7 @@ authdir_mode_tests_reachability(or_options_t *options)
* directory server.
*/
int
-authdir_mode_bridge(or_options_t *options)
+authdir_mode_bridge(const or_options_t *options)
{
return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
}
@@ -1056,7 +1080,7 @@ authdir_mode_bridge(or_options_t *options)
/** Return true iff we are trying to be a server.
*/
int
-server_mode(or_options_t *options)
+server_mode(const or_options_t *options)
{
if (options->ClientOnly) return 0;
return (options->ORPort != 0 || options->ORListenAddress);
@@ -1065,7 +1089,7 @@ server_mode(or_options_t *options)
/** Return true iff we are trying to be a non-bridge server.
*/
int
-public_server_mode(or_options_t *options)
+public_server_mode(const or_options_t *options)
{
if (!server_mode(options)) return 0;
return (!options->BridgeRelay);
@@ -1075,10 +1099,10 @@ public_server_mode(or_options_t *options)
* in the consensus mean that we don't want to allow exits from circuits
* we got from addresses not known to be servers. */
int
-should_refuse_unknown_exits(or_options_t *options)
+should_refuse_unknown_exits(const or_options_t *options)
{
- if (options->RefuseUnknownExits_ != -1) {
- return options->RefuseUnknownExits_;
+ if (options->RefuseUnknownExits != -1) {
+ return options->RefuseUnknownExits;
} else {
return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1);
}
@@ -1105,14 +1129,12 @@ set_server_advertised(int s)
server_is_advertised = s;
}
-/** Return true iff we are trying to be a socks proxy. */
+/** Return true iff we are trying to proxy client connections. */
int
-proxy_mode(or_options_t *options)
+proxy_mode(const or_options_t *options)
{
- return (options->SocksPort != 0 ||
- options->TransPort != 0 ||
- options->NATDPort != 0 ||
- options->DNSPort != 0);
+ (void)options;
+ return smartlist_len(get_configured_client_ports()) > 0;
}
/** Decide if we're a publishable server. We are a publishable server if:
@@ -1128,11 +1150,11 @@ proxy_mode(or_options_t *options)
static int
decide_if_publishable_server(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ClientOnly)
return 0;
- if (options->_PublishServerDescriptor == NO_AUTHORITY)
+ if (options->_PublishServerDescriptor == NO_DIRINFO)
return 0;
if (!server_mode(options))
return 0;
@@ -1173,7 +1195,7 @@ consider_publishable_server(int force)
* the one configured in the ORPort option, or the one we actually bound to
* if ORPort is "auto". */
uint16_t
-router_get_advertised_or_port(or_options_t *options)
+router_get_advertised_or_port(const or_options_t *options)
{
if (options->ORPort == CFG_AUTO_PORT) {
connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER);
@@ -1190,7 +1212,7 @@ router_get_advertised_or_port(or_options_t *options)
* the one configured in the DirPort option,
* or the one we actually bound to if DirPort is "auto". */
uint16_t
-router_get_advertised_dir_port(or_options_t *options, uint16_t dirport)
+router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
{
if (!options->DirPort)
return dirport;
@@ -1211,9 +1233,14 @@ router_get_advertised_dir_port(or_options_t *options, uint16_t dirport)
static routerinfo_t *desc_routerinfo = NULL;
/** My extrainfo */
static extrainfo_t *desc_extrainfo = NULL;
+/** Why did we most recently decide to regenerate our descriptor? Used to
+ * tell the authorities why we're sending it to them. */
+static const char *desc_gen_reason = NULL;
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it
* now. */
static time_t desc_clean_since = 0;
+/** Why did we mark the descriptor dirty? */
+static const char *desc_dirty_reason = NULL;
/** Boolean: do we need to regenerate the above? */
static int desc_needs_upload = 0;
@@ -1224,11 +1251,11 @@ static int desc_needs_upload = 0;
void
router_upload_dir_desc_to_dirservers(int force)
{
- routerinfo_t *ri;
+ const routerinfo_t *ri;
extrainfo_t *ei;
char *msg;
size_t desc_len, extra_len = 0, total_len;
- authority_type_t auth = get_options()->_PublishServerDescriptor;
+ dirinfo_type_t auth = get_options()->_PublishServerDescriptor;
ri = router_get_my_routerinfo();
if (!ri) {
@@ -1236,7 +1263,7 @@ router_upload_dir_desc_to_dirservers(int force)
return;
}
ei = router_get_my_extrainfo();
- if (auth == NO_AUTHORITY)
+ if (auth == NO_DIRINFO)
return;
if (!force && !desc_needs_upload)
return;
@@ -1257,7 +1284,7 @@ router_upload_dir_desc_to_dirservers(int force)
msg[desc_len+extra_len] = 0;
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
- (auth & BRIDGE_AUTHORITY) ?
+ (auth & BRIDGE_DIRINFO) ?
ROUTER_PURPOSE_BRIDGE :
ROUTER_PURPOSE_GENERAL,
auth, msg, desc_len, extra_len);
@@ -1322,7 +1349,7 @@ router_extrainfo_digest_is_me(const char *digest)
/** A wrapper around router_digest_is_me(). */
int
-router_is_me(routerinfo_t *router)
+router_is_me(const routerinfo_t *router)
{
return router_digest_is_me(router->cache_info.identity_digest);
}
@@ -1341,7 +1368,7 @@ router_fingerprint_is_me(const char *fp)
/** Return a routerinfo for this OR, rebuilding a fresh one if
* necessary. Return NULL on error, or if called on an OP. */
-routerinfo_t *
+const routerinfo_t *
router_get_my_routerinfo(void)
{
if (!server_mode(get_options()))
@@ -1380,6 +1407,14 @@ router_get_my_extrainfo(void)
return desc_extrainfo;
}
+/** Return a human-readable string describing what triggered us to generate
+ * our current descriptor, or NULL if we don't know. */
+const char *
+router_get_descriptor_gen_reason(void)
+{
+ return desc_gen_reason;
+}
+
/** A list of nicknames that we've warned about including in our family
* declaration verbatim rather than as digests. */
static smartlist_t *warned_nonexistent_family = NULL;
@@ -1391,10 +1426,8 @@ static int router_guess_address_from_dir_headers(uint32_t *guess);
* dirserver headers. Place the answer in *<b>addr</b> and return
* 0 on success, else return -1 if we have no guess. */
int
-router_pick_published_address(or_options_t *options, uint32_t *addr)
+router_pick_published_address(const or_options_t *options, uint32_t *addr)
{
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
log_info(LD_CONFIG, "Could not determine our address locally. "
"Checking if directory headers provide any hints.");
@@ -1404,9 +1437,7 @@ router_pick_published_address(or_options_t *options, uint32_t *addr)
return -1;
}
}
- a.s_addr = htonl(*addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_CONFIG,"Success: chose address '%s'.", buf);
+ log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
return 0;
}
@@ -1422,7 +1453,7 @@ router_rebuild_descriptor(int force)
uint32_t addr;
char platform[256];
int hibernating = we_are_hibernating();
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (desc_clean_since && !force)
return 0;
@@ -1476,13 +1507,12 @@ router_rebuild_descriptor(int force)
ri->policy_is_reject_star =
policy_is_reject_star(ri->exit_policy);
- if (desc_routerinfo) { /* inherit values */
- ri->is_valid = desc_routerinfo->is_valid;
- ri->is_running = desc_routerinfo->is_running;
- ri->is_named = desc_routerinfo->is_named;
- }
+#if 0
+ /* XXXX NM NM I belive this is safe to remove */
if (authdir_mode(options))
ri->is_valid = ri->is_named = 1; /* believe in yourself */
+#endif
+
if (options->MyFamily) {
smartlist_t *family;
if (!warned_nonexistent_family)
@@ -1491,13 +1521,12 @@ router_rebuild_descriptor(int force)
ri->declared_family = smartlist_create();
smartlist_split_string(family, options->MyFamily, ",",
SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH(family, char *, name,
- {
- routerinfo_t *member;
+ SMARTLIST_FOREACH_BEGIN(family, char *, name) {
+ const node_t *member;
if (!strcasecmp(name, options->Nickname))
- member = ri;
+ goto skip; /* Don't list ourself, that's redundant */
else
- member = router_get_by_nickname(name, 1);
+ member = node_get_by_nickname(name, 1);
if (!member) {
int is_legal = is_legal_nickname_or_hexdigest(name);
if (!smartlist_string_isin(warned_nonexistent_family, name) &&
@@ -1517,19 +1546,21 @@ router_rebuild_descriptor(int force)
smartlist_add(ri->declared_family, name);
name = NULL;
}
- } else if (router_is_me(member)) {
+ } else if (router_digest_is_me(member->identity)) {
/* Don't list ourself in our own family; that's redundant */
+ /* XXX shouldn't be possible */
} else {
char *fp = tor_malloc(HEX_DIGEST_LEN+2);
fp[0] = '$';
base16_encode(fp+1,HEX_DIGEST_LEN+1,
- member->cache_info.identity_digest, DIGEST_LEN);
+ member->identity, DIGEST_LEN);
smartlist_add(ri->declared_family, fp);
if (smartlist_string_isin(warned_nonexistent_family, name))
smartlist_string_remove(warned_nonexistent_family, name);
}
+ skip:
tor_free(name);
- });
+ } SMARTLIST_FOREACH_END(name);
/* remove duplicates from the list */
smartlist_sort_strings(ri->declared_family);
@@ -1590,8 +1621,6 @@ router_rebuild_descriptor(int force)
strlen(ri->cache_info.signed_descriptor_body),
ri->cache_info.signed_descriptor_digest);
- routerinfo_set_country(ri);
-
if (ei) {
tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
}
@@ -1603,16 +1632,56 @@ router_rebuild_descriptor(int force)
desc_clean_since = time(NULL);
desc_needs_upload = 1;
+ desc_gen_reason = desc_dirty_reason;
+ desc_dirty_reason = NULL;
control_event_my_descriptor_changed();
return 0;
}
-/** Mark descriptor out of date if it's older than <b>when</b> */
+/** If our router descriptor ever goes this long without being regenerated
+ * because something changed, we force an immediate regenerate-and-upload. */
+#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
+
+/** If our router descriptor seems to be missing or unacceptable according
+ * to the authorities, regenerate and reupload it _this_ often. */
+#define FAST_RETRY_DESCRIPTOR_INTERVAL (90*60)
+
+/** Mark descriptor out of date if it's been "too long" since we last tried
+ * to upload one. */
void
-mark_my_descriptor_dirty_if_older_than(time_t when)
+mark_my_descriptor_dirty_if_too_old(time_t now)
{
- if (desc_clean_since < when)
+ networkstatus_t *ns;
+ const routerstatus_t *rs;
+ const char *retry_fast_reason = NULL; /* Set if we should retry frequently */
+ const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL;
+ const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL;
+
+ /* If it's already dirty, don't mark it. */
+ if (! desc_clean_since)
+ return;
+
+ /* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always
+ * time to rebuild it. */
+ if (desc_clean_since < slow_cutoff) {
mark_my_descriptor_dirty("time for new descriptor");
+ return;
+ }
+ /* Now we see whether we want to be retrying frequently or no. The
+ * rule here is that we'll retry frequently if we aren't listed in the
+ * live consensus we have, or if the publication time of the
+ * descriptor listed for us in the consensus is very old. */
+ ns = networkstatus_get_live_consensus(now);
+ if (ns) {
+ rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
+ if (rs == NULL)
+ retry_fast_reason = "not listed in consensus";
+ else if (rs->published_on < slow_cutoff)
+ retry_fast_reason = "version listed in consensus is quite old";
+ }
+
+ if (retry_fast_reason && desc_clean_since < fast_cutoff)
+ mark_my_descriptor_dirty(retry_fast_reason);
}
/** Call when the current descriptor is out of date. */
@@ -1621,6 +1690,8 @@ mark_my_descriptor_dirty(const char *reason)
{
desc_clean_since = 0;
log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
+ if (!desc_dirty_reason)
+ desc_dirty_reason = reason;
}
/** How frequently will we republish our descriptor because of large (factor
@@ -1686,7 +1757,7 @@ void
check_descriptor_ipaddress_changed(time_t now)
{
uint32_t prev, cur;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
(void) now;
if (!desc_routerinfo)
@@ -1718,7 +1789,7 @@ router_new_address_suggestion(const char *suggestion,
{
uint32_t addr, cur = 0;
struct in_addr in;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* first, learn what the IP address actually is */
if (!tor_inet_aton(suggestion, &in)) {
@@ -1817,7 +1888,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
int result=0;
addr_policy_t *tmpe;
char *family_line;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* Make sure the identity key matches the one in the routerinfo. */
if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
@@ -2059,7 +2130,7 @@ int
extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
crypto_pk_env_t *ident_key)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char identity[HEX_DIGEST_LEN+1];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
@@ -2083,6 +2154,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
tor_free(bandwidth_usage);
smartlist_add(chunks, pre);
+ if (geoip_is_loaded()) {
+ char *chunk=NULL;
+ tor_asprintf(&chunk, "geoip-db-digest %s\n", geoip_db_digest());
+ smartlist_add(chunks, chunk);
+ }
+
if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
if (options->DirReqStatistics &&
@@ -2105,6 +2182,11 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
"exit-stats-end", now, &contents) > 0) {
smartlist_add(chunks, contents);
}
+ if (options->ConnDirectionStatistics &&
+ load_stats_file("stats"PATH_SEPARATOR"conn-stats",
+ "conn-bi-direct", now, &contents) > 0) {
+ smartlist_add(chunks, contents);
+ }
}
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
@@ -2291,13 +2373,45 @@ router_get_description(char *buf, const routerinfo_t *ri)
return "<null>";
return format_node_description(buf,
ri->cache_info.identity_digest,
- ri->is_named,
+ router_is_named(ri),
ri->nickname,
NULL,
ri->addr);
}
/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of <b>node</b>.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+node_get_description(char *buf, const node_t *node)
+{
+ const char *nickname = NULL;
+ uint32_t addr32h = 0;
+ int is_named = 0;
+
+ if (!node)
+ return "<null>";
+
+ if (node->rs) {
+ nickname = node->rs->nickname;
+ is_named = node->rs->is_named;
+ addr32h = node->rs->addr;
+ } else if (node->ri) {
+ nickname = node->ri->nickname;
+ addr32h = node->ri->addr;
+ }
+
+ return format_node_description(buf,
+ node->identity,
+ is_named,
+ nickname,
+ NULL,
+ addr32h);
+}
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
* hold a human-readable description of <b>rs</b>.
*
* Return a pointer to the front of <b>buf</b>.
@@ -2345,6 +2459,18 @@ router_describe(const routerinfo_t *ri)
return router_get_description(buf, ri);
}
+/** Return a human-readable description of the node_t <b>node</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+node_describe(const node_t *node)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ return node_get_description(buf, node);
+}
+
/** Return a human-readable description of the routerstatus_t <b>rs</b>.
*
* This function is not thread-safe. Each call to this function invalidates
@@ -2379,10 +2505,15 @@ extend_info_describe(const extend_info_t *ei)
void
router_get_verbose_nickname(char *buf, const routerinfo_t *router)
{
+ const char *good_digest = networkstatus_get_router_digest_by_nickname(
+ router->nickname);
+ int is_named = good_digest && tor_memeq(good_digest,
+ router->cache_info.identity_digest,
+ DIGEST_LEN);
buf[0] = '$';
base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
+ buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}
diff --git a/src/or/router.h b/src/or/router.h
index 3733099f93..6a9851cdbd 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -30,6 +30,7 @@ crypto_pk_env_t *init_key_from_file(const char *fname, int generate,
int severity);
void v3_authority_check_key_expiry(void);
+int router_initialize_tls_context(void);
int init_keys(void);
int check_whether_orport_reachable(void);
@@ -39,30 +40,32 @@ void router_orport_found_reachable(void);
void router_dirport_found_reachable(void);
void router_perform_bandwidth_test(int num_circs, time_t now);
-int authdir_mode(or_options_t *options);
-int authdir_mode_v1(or_options_t *options);
-int authdir_mode_v2(or_options_t *options);
-int authdir_mode_v3(or_options_t *options);
-int authdir_mode_any_main(or_options_t *options);
-int authdir_mode_any_nonhidserv(or_options_t *options);
-int authdir_mode_handles_descs(or_options_t *options, int purpose);
-int authdir_mode_publishes_statuses(or_options_t *options);
-int authdir_mode_tests_reachability(or_options_t *options);
-int authdir_mode_bridge(or_options_t *options);
-
-uint16_t router_get_advertised_or_port(or_options_t *options);
-uint16_t router_get_advertised_dir_port(or_options_t *options,
+int net_is_disabled(void);
+
+int authdir_mode(const or_options_t *options);
+int authdir_mode_v1(const or_options_t *options);
+int authdir_mode_v2(const or_options_t *options);
+int authdir_mode_v3(const or_options_t *options);
+int authdir_mode_any_main(const or_options_t *options);
+int authdir_mode_any_nonhidserv(const or_options_t *options);
+int authdir_mode_handles_descs(const or_options_t *options, int purpose);
+int authdir_mode_publishes_statuses(const or_options_t *options);
+int authdir_mode_tests_reachability(const or_options_t *options);
+int authdir_mode_bridge(const or_options_t *options);
+
+uint16_t router_get_advertised_or_port(const or_options_t *options);
+uint16_t router_get_advertised_dir_port(const or_options_t *options,
uint16_t dirport);
-int server_mode(or_options_t *options);
-int public_server_mode(or_options_t *options);
+int server_mode(const or_options_t *options);
+int public_server_mode(const or_options_t *options);
int advertised_server_mode(void);
-int proxy_mode(or_options_t *options);
+int proxy_mode(const or_options_t *options);
void consider_publishable_server(int force);
-int should_refuse_unknown_exits(or_options_t *options);
+int should_refuse_unknown_exits(const or_options_t *options);
void router_upload_dir_desc_to_dirservers(int force);
-void mark_my_descriptor_dirty_if_older_than(time_t when);
+void mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
@@ -70,14 +73,15 @@ void router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn);
int router_compare_to_my_exit_policy(edge_connection_t *conn);
int router_my_exit_policy_is_reject_star(void);
-routerinfo_t *router_get_my_routerinfo(void);
+const routerinfo_t *router_get_my_routerinfo(void);
extrainfo_t *router_get_my_extrainfo(void);
const char *router_get_my_descriptor(void);
+const char *router_get_descriptor_gen_reason(void);
int router_digest_is_me(const char *digest);
int router_extrainfo_digest_is_me(const char *digest);
-int router_is_me(routerinfo_t *router);
+int router_is_me(const routerinfo_t *router);
int router_fingerprint_is_me(const char *fp);
-int router_pick_published_address(or_options_t *options, uint32_t *addr);
+int router_pick_published_address(const or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);
@@ -102,9 +106,11 @@ const char *format_node_description(char *buf,
const tor_addr_t *addr,
uint32_t addr32h);
const char *router_get_description(char *buf, const routerinfo_t *ri);
+const char *node_get_description(char *buf, const node_t *node);
const char *routerstatus_get_description(char *buf, const routerstatus_t *rs);
const char *extend_info_get_description(char *buf, const extend_info_t *ei);
const char *router_describe(const routerinfo_t *ri);
+const char *node_describe(const node_t *node);
const char *routerstatus_describe(const routerstatus_t *ri);
const char *extend_info_describe(const extend_info_t *ei);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index f8df089a8f..689df99c57 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -22,7 +22,9 @@
#include "geoip.h"
#include "hibernate.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "rendcommon.h"
@@ -37,22 +39,25 @@
/****************************************************************************/
/* static function prototypes */
-static routerstatus_t *router_pick_directory_server_impl(
- authority_type_t auth, int flags);
-static routerstatus_t *router_pick_trusteddirserver_impl(
- authority_type_t auth, int flags, int *n_busy_out);
+static const routerstatus_t *router_pick_directory_server_impl(
+ dirinfo_type_t auth, int flags);
+static const routerstatus_t *router_pick_trusteddirserver_impl(
+ dirinfo_type_t auth, int flags, int *n_busy_out);
static void mark_all_trusteddirservers_up(void);
-static int router_nickname_matches(routerinfo_t *router, const char *nickname);
+static int router_nickname_matches(const routerinfo_t *router,
+ const char *nickname);
+static int node_nickname_matches(const node_t *router,
+ const char *nickname);
static void trusted_dir_server_free(trusted_dir_server_t *ds);
-static void launch_router_descriptor_downloads(smartlist_t *downloadable,
- routerstatus_t *source,
- time_t now);
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static void update_router_have_minimum_dir_info(void);
-static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc,
- int with_annotations);
+static const char *signed_descriptor_get_body_impl(
+ const signed_descriptor_t *desc,
+ int with_annotations);
static void list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix);
+static void launch_dummy_descriptor_download_as_needed(time_t now,
+ const or_options_t *options);
DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t)
DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t)
@@ -94,7 +99,7 @@ static smartlist_t *warned_nicknames = NULL;
/** The last time we tried to download any routerdesc, or 0 for "never". We
* use this to rate-limit download attempts when the number of routerdescs to
* download is low. */
-static time_t last_routerdesc_download_attempted = 0;
+static time_t last_descriptor_download_attempted = 0;
/** When we last computed the weights to use for bandwidths on directory
* requests, what were the total weighted bandwidth, and our share of that
@@ -106,7 +111,7 @@ static uint64_t sl_last_total_weighted_bw = 0,
/** Return the number of directory authorities whose type matches some bit set
* in <b>type</b> */
int
-get_n_authorities(authority_type_t type)
+get_n_authorities(dirinfo_type_t type)
{
int n = 0;
if (!trusted_dir_servers)
@@ -117,7 +122,7 @@ get_n_authorities(authority_type_t type)
return n;
}
-#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY)
+#define get_n_v2_authorities() get_n_authorities(V2_DIRINFO)
/** Helper: Return the cert_list_t for an authority whose authority ID is
* <b>id_digest</b>, allocating a new list if necessary. */
@@ -312,6 +317,7 @@ trusted_dirs_remove_old_certs(void)
time_t now = time(NULL);
#define DEAD_CERT_LIFETIME (2*24*60*60)
#define OLD_CERT_LIFETIME (7*24*60*60)
+#define CERT_EXPIRY_SKEW (60*60)
if (!trusted_dir_certs)
return;
@@ -514,7 +520,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
}
SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) {
int found = 0;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
continue;
@@ -600,7 +606,7 @@ router_should_rebuild_store(desc_store_t *store)
/** Return the desc_store_t in <b>rl</b> that should be used to store
* <b>sd</b>. */
static INLINE desc_store_t *
-desc_get_store(routerlist_t *rl, signed_descriptor_t *sd)
+desc_get_store(routerlist_t *rl, const signed_descriptor_t *sd)
{
if (sd->is_extrainfo)
return &rl->extrainfo_store;
@@ -926,10 +932,10 @@ router_get_trusted_dir_servers(void)
* Don't pick an authority if any non-authority is viable; try to avoid using
* servers that have returned 503 recently.
*/
-routerstatus_t *
-router_pick_directory_server(authority_type_t type, int flags)
+const routerstatus_t *
+router_pick_directory_server(dirinfo_type_t type, int flags)
{
- routerstatus_t *choice;
+ const routerstatus_t *choice;
if (get_options()->PreferTunneledDirConns)
flags |= _PDS_PREFER_TUNNELED_DIR_CONNS;
@@ -958,8 +964,8 @@ int
router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out)
{
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *rs;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *rs;
const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL;
*v2_share_out = *v3_share_out = 0.0;
if (!me)
@@ -972,7 +978,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
/* XXXX This is a bit of a kludge */
if (rs->is_v2_dir) {
sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V2_AUTHORITY, pds_flags);
+ router_pick_directory_server(V2_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v2_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@@ -981,7 +987,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
if (rs->version_supports_v3_dir) {
sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V3_AUTHORITY, pds_flags);
+ router_pick_directory_server(V3_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v3_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@@ -1022,7 +1028,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
{
if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) &&
- (ds->type & V3_AUTHORITY))
+ (ds->type & V3_DIRINFO))
return ds;
});
@@ -1032,10 +1038,10 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
/** Try to find a running trusted dirserver. Flags are as for
* router_pick_directory_server.
*/
-routerstatus_t *
-router_pick_trusteddirserver(authority_type_t type, int flags)
+const routerstatus_t *
+router_pick_trusteddirserver(dirinfo_type_t type, int flags)
{
- routerstatus_t *choice;
+ const routerstatus_t *choice;
int busy = 0;
if (get_options()->PreferTunneledDirConns)
flags |= _PDS_PREFER_TUNNELED_DIR_CONNS;
@@ -1047,7 +1053,8 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
/* If the reason that we got no server is that servers are "busy",
* we must be excluding good servers because we already have serverdesc
* fetches with them. Do not mark down servers up because of this. */
- tor_assert((flags & PDS_NO_EXISTING_SERVERDESC_FETCH));
+ tor_assert((flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH)));
return NULL;
}
@@ -1067,11 +1074,11 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
* If the _PDS_PREFER_TUNNELED_DIR_CONNS flag is set, prefer directory servers
* that we can use with BEGINDIR.
*/
-static routerstatus_t *
-router_pick_directory_server_impl(authority_type_t type, int flags)
+static const routerstatus_t *
+router_pick_directory_server_impl(dirinfo_type_t type, int flags)
{
- or_options_t *options = get_options();
- routerstatus_t *result;
+ const or_options_t *options = get_options();
+ const node_t *result;
smartlist_t *direct, *tunnel;
smartlist_t *trusted_direct, *trusted_tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
@@ -1095,54 +1102,64 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
overloaded_tunnel = smartlist_create();
/* Find all the running dirservers we know about. */
- SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *,
- status) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
int is_trusted;
- int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
+ int is_overloaded;
tor_addr_t addr;
- if (!status->is_running || !status->dir_port || !status->is_valid)
+ const routerstatus_t *status = node->rs;
+ const country_t country = node->country;
+ if (!status)
continue;
- if (status->is_bad_directory)
+
+ if (!node->is_running || !status->dir_port || !node->is_valid)
+ continue;
+ if (node->is_bad_directory)
continue;
- if (requireother && router_digest_is_me(status->identity_digest))
+ if (requireother && router_digest_is_me(node->identity))
continue;
- if (type & V3_AUTHORITY) {
+ if (type & V3_DIRINFO) {
if (!(status->version_supports_v3_dir ||
- router_digest_is_trusted_dir_type(status->identity_digest,
- V3_AUTHORITY)))
+ router_digest_is_trusted_dir_type(node->identity,
+ V3_DIRINFO)))
continue;
}
- is_trusted = router_digest_is_trusted_dir(status->identity_digest);
- if ((type & V2_AUTHORITY) && !(status->is_v2_dir || is_trusted))
+ is_trusted = router_digest_is_trusted_dir(node->identity);
+ if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted))
+ continue;
+ if ((type & EXTRAINFO_DIRINFO) &&
+ !router_supports_extrainfo(node->identity, 0))
continue;
- if ((type & EXTRAINFO_CACHE) &&
- !router_supports_extrainfo(status->identity_digest, 0))
+ if ((type & MICRODESC_DIRINFO) && !is_trusted &&
+ !node->rs->version_supports_microdesc_cache)
continue;
- if (try_excluding && options->ExcludeNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
+ if (try_excluding &&
+ routerset_contains_routerstatus(options->ExcludeNodes, status,
+ country)) {
++n_excluded;
continue;
}
/* XXXX IP6 proposal 118 */
- tor_addr_from_ipv4h(&addr, status->addr);
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+
+ is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
if (prefer_tunnel &&
status->version_supports_begindir &&
(!fascistfirewall ||
fascist_firewall_allows_address_or(&addr, status->or_port)))
smartlist_add(is_trusted ? trusted_tunnel :
- is_overloaded ? overloaded_tunnel : tunnel, status);
+ is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
else if (!fascistfirewall ||
fascist_firewall_allows_address_dir(&addr, status->dir_port))
smartlist_add(is_trusted ? trusted_direct :
- is_overloaded ? overloaded_direct : direct, status);
- } SMARTLIST_FOREACH_END(status);
+ is_overloaded ? overloaded_direct : direct, (void*)node);
+ } SMARTLIST_FOREACH_END(node);
if (smartlist_len(tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_tunnel,
+ result = node_sl_choose_by_bandwidth(overloaded_tunnel,
WEIGHT_FOR_DIR);
} else if (smartlist_len(trusted_tunnel)) {
/* FFFF We don't distinguish between trusteds and overloaded trusteds
@@ -1151,10 +1168,10 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
* is a feature, but it could easily be a bug. -RD */
result = smartlist_choose(trusted_tunnel);
} else if (smartlist_len(direct)) {
- result = routerstatus_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_direct)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_direct,
- WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(overloaded_direct,
+ WEIGHT_FOR_DIR);
} else {
result = smartlist_choose(trusted_direct);
}
@@ -1173,26 +1190,27 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
goto retry_without_exclude;
}
- return result;
+ return result ? result->rs : NULL;
}
/** Choose randomly from among the trusted dirservers that are up. Flags
* are as for router_pick_directory_server_impl().
*/
-static routerstatus_t *
-router_pick_trusteddirserver_impl(authority_type_t type, int flags,
+static const routerstatus_t *
+router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags,
int *n_busy_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *direct, *tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *result;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *result;
time_t now = time(NULL);
const int requireother = ! (flags & PDS_ALLOW_SELF);
const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
const int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS);
const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH);
+ const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH);
int n_busy = 0;
int try_excluding = 1, n_excluded = 0;
@@ -1214,14 +1232,14 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
if (!d->is_running) continue;
if ((type & d->type) == 0)
continue;
- if ((type & EXTRAINFO_CACHE) &&
+ if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(d->digest, 1))
continue;
if (requireother && me && router_digest_is_me(d->digest))
continue;
- if (try_excluding && options->ExcludeNodes &&
+ if (try_excluding &&
routerset_contains_routerstatus(options->ExcludeNodes,
- &d->fake_status)) {
+ &d->fake_status, -1)) {
++n_excluded;
continue;
}
@@ -1240,6 +1258,13 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
continue;
}
}
+ if (no_microdesc_fetching) {
+ if (connection_get_by_type_addr_port_purpose(
+ CONN_TYPE_DIR, &addr, d->dir_port, DIR_PURPOSE_FETCH_MICRODESC)) {
+ ++n_busy;
+ continue;
+ }
+ }
if (prefer_tunnel &&
d->or_port &&
@@ -1287,22 +1312,18 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
static void
mark_all_trusteddirservers_up(void)
{
- if (routerlist) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- if (router_digest_is_trusted_dir(router->cache_info.identity_digest) &&
- router->dir_port > 0) {
- router->is_running = 1;
- });
- }
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, {
+ if (router_digest_is_trusted_dir(node->identity))
+ node->is_running = 1;
+ });
if (trusted_dir_servers) {
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
{
routerstatus_t *rs;
dir->is_running = 1;
download_status_reset(&dir->v2_ns_dl_status);
- rs = router_get_consensus_status_by_id(dir->digest);
- if (rs && !rs->is_running) {
- rs->is_running = 1;
+ rs = router_get_mutable_consensus_status_by_id(dir->digest);
+ if (rs) {
rs->last_dir_503_at = 0;
control_event_networkstatus_changed_single(rs);
}
@@ -1326,148 +1347,160 @@ router_reset_status_download_failures(void)
mark_all_trusteddirservers_up();
}
-/** Return true iff router1 and router2 have the same /16 network. */
+/** Return true iff router1 and router2 have similar enough network addresses
+ * that we should treat them as being in the same family */
static INLINE int
-routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2)
+addrs_in_same_network_family(const tor_addr_t *a1,
+ const tor_addr_t *a2)
{
- return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000);
+ /* XXXX MOVE ? */
+ return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC);
}
-/** Look through the routerlist and identify routers that
- * advertise the same /16 network address as <b>router</b>.
- * Add each of them to <b>sl</b>.
+/**
+ * Add all the family of <b>node</b>, including <b>node</b> itself, to
+ * the smartlist <b>sl</b>.
+ *
+ * This is used to make sure we don't pick siblings in a single path, or
+ * pick more than one relay from a family for our entry guard list.
+ * Note that a node may be added to <b>sl</b> more than once if it is
+ * part of <b>node</b>'s family for more than one reason.
*/
-static void
-routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router)
+void
+nodelist_add_node_and_family(smartlist_t *sl, const node_t *node)
{
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
+ /* XXXX MOVE */
+ const smartlist_t *all_nodes = nodelist_get_list();
+ const smartlist_t *declared_family;
+ const or_options_t *options = get_options();
+
+ tor_assert(node);
+
+ declared_family = node_get_declared_family(node);
+
+ /* Let's make sure that we have the node itself, if it's a real node. */
{
- if (router != r && routers_in_same_network_family(router, r))
- smartlist_add(sl, r);
- });
-}
+ const node_t *real_node = node_get_by_id(node->identity);
+ if (real_node)
+ smartlist_add(sl, (node_t*)real_node);
+ }
-/** Add all the family of <b>router</b> to the smartlist <b>sl</b>.
- * This is used to make sure we don't pick siblings in a single path,
- * or pick more than one relay from a family for our entry guard list.
- */
-void
-routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
-{
- routerinfo_t *r;
- config_line_t *cl;
- or_options_t *options = get_options();
+ /* First, add any nodes with similar network addresses. */
+ if (options->EnforceDistinctSubnets) {
+ tor_addr_t node_addr;
+ node_get_addr(node, &node_addr);
- /* First, add any routers with similar network addresses. */
- if (options->EnforceDistinctSubnets)
- routerlist_add_network_family(sl, router);
+ SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) {
+ tor_addr_t a;
+ node_get_addr(node2, &a);
+ if (addrs_in_same_network_family(&a, &node_addr))
+ smartlist_add(sl, (void*)node2);
+ } SMARTLIST_FOREACH_END(node2);
+ }
- if (router->declared_family) {
- /* Add every r such that router declares familyness with r, and r
+ /* Now, add all nodes in the declared_family of this node, if they
+ * also declare this node to be in their family. */
+ if (declared_family) {
+ /* Add every r such that router declares familyness with node, and node
* declares familyhood with router. */
- SMARTLIST_FOREACH(router->declared_family, const char *, n,
- {
- if (!(r = router_get_by_nickname(n, 0)))
- continue;
- if (!r->declared_family)
- continue;
- SMARTLIST_FOREACH(r->declared_family, const char *, n2,
- {
- if (router_nickname_matches(router, n2))
- smartlist_add(sl, r);
- });
- });
+ SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) {
+ const node_t *node2;
+ const smartlist_t *family2;
+ if (!(node2 = node_get_by_nickname(name, 0)))
+ continue;
+ if (!(family2 = node_get_declared_family(node2)))
+ continue;
+ SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) {
+ if (node_nickname_matches(node, name2)) {
+ smartlist_add(sl, (void*)node2);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(name2);
+ } SMARTLIST_FOREACH_END(name);
}
/* If the user declared any families locally, honor those too. */
- for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (router_nickname_is_in_list(router, cl->value)) {
- add_nickname_list_to_smartlist(sl, cl->value, 0);
- }
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
+ if (routerset_contains_node(rs, node)) {
+ routerset_get_all_nodes(sl, rs, NULL, 0);
+ }
+ });
}
}
-/** Return true iff r is named by some nickname in <b>lst</b>. */
+/** Given a <b>router</b>, add every node_t in its family (including the
+ * node itself</b>) to <b>sl</b>.
+ *
+ * Note the type mismatch: This function takes a routerinfo, but adds nodes
+ * to the smartlist!
+ */
+static void
+routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
+{
+ /* XXXX MOVE ? */
+ node_t fake_node;
+ const node_t *node = node_get_by_id(router->cache_info.identity_digest);;
+ if (node == NULL) {
+ memset(&fake_node, 0, sizeof(fake_node));
+ fake_node.ri = (routerinfo_t *)router;
+ memcpy(fake_node.identity, router->cache_info.identity_digest, DIGEST_LEN);
+ node = &fake_node;
+ }
+ nodelist_add_node_and_family(sl, node);
+}
+
+/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */
static INLINE int
-router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r)
+node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node)
{
+ /* XXXX MOVE */
if (!lst) return 0;
- SMARTLIST_FOREACH(lst, const char *, name,
- if (router_nickname_matches(r, name))
- return 1;);
+ SMARTLIST_FOREACH(lst, const char *, name, {
+ if (node_nickname_matches(node, name))
+ return 1;
+ });
return 0;
}
/** Return true iff r1 and r2 are in the same family, but not the same
* router. */
int
-routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2)
+nodes_in_same_family(const node_t *node1, const node_t *node2)
{
- or_options_t *options = get_options();
- config_line_t *cl;
-
- if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2))
- return 1;
+ /* XXXX MOVE */
+ const or_options_t *options = get_options();
- if (router_in_nickname_smartlist(r1->declared_family, r2) &&
- router_in_nickname_smartlist(r2->declared_family, r1))
- return 1;
-
- for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (router_nickname_is_in_list(r1, cl->value) &&
- router_nickname_is_in_list(r2, cl->value))
+ /* Are they in the same family because of their addresses? */
+ if (options->EnforceDistinctSubnets) {
+ tor_addr_t a1, a2;
+ node_get_addr(node1, &a1);
+ node_get_addr(node2, &a2);
+ if (addrs_in_same_network_family(&a1, &a2))
return 1;
}
- return 0;
-}
-
-/** Given a (possibly NULL) comma-and-whitespace separated list of nicknames,
- * see which nicknames in <b>list</b> name routers in our routerlist, and add
- * the routerinfos for those routers to <b>sl</b>. If <b>must_be_running</b>,
- * only include routers that we think are running.
- * Warn if any non-Named routers are specified by nickname.
- */
-void
-add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running)
-{
- routerinfo_t *router;
- smartlist_t *nickname_list;
- int have_dir_info = router_have_minimum_dir_info();
- if (!list)
- return; /* nothing to do */
- tor_assert(sl);
-
- nickname_list = smartlist_create();
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
+ /* Are they in the same family because the agree they are? */
+ {
+ const smartlist_t *f1, *f2;
+ f1 = node_get_declared_family(node1);
+ f2 = node_get_declared_family(node2);
+ if (f1 && f2 &&
+ node_in_nickname_smartlist(f1, node2) &&
+ node_in_nickname_smartlist(f2, node1))
+ return 1;
+ }
- smartlist_split_string(nickname_list, list, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ /* Are they in the same option because the user says they are? */
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
+ if (routerset_contains_node(rs, node1) &&
+ routerset_contains_node(rs, node2))
+ return 1;
+ });
+ }
- SMARTLIST_FOREACH(nickname_list, const char *, nick, {
- int warned;
- if (!is_legal_nickname_or_hexdigest(nick)) {
- log_warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick);
- continue;
- }
- router = router_get_by_nickname(nick, 1);
- warned = smartlist_string_isin(warned_nicknames, nick);
- if (router) {
- if (!must_be_running || router->is_running) {
- smartlist_add(sl,router);
- }
- } else if (!router_get_consensus_status_by_nickname(nick,1)) {
- if (!warned) {
- log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG,
- "Nickname list includes '%s' which isn't a known router.",nick);
- smartlist_add(warned_nicknames, tor_strdup(nick));
- }
- }
- });
- SMARTLIST_FOREACH(nickname_list, char *, nick, tor_free(nick));
- smartlist_free(nickname_list);
+ return 0;
}
/** Return 1 iff any member of the (possibly NULL) comma-separated list
@@ -1475,7 +1508,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
* return 0.
*/
int
-router_nickname_is_in_list(routerinfo_t *router, const char *list)
+router_nickname_is_in_list(const routerinfo_t *router, const char *list)
{
smartlist_t *nickname_list;
int v = 0;
@@ -1494,34 +1527,32 @@ router_nickname_is_in_list(routerinfo_t *router, const char *list)
return v;
}
-/** Add every suitable router from our routerlist to <b>sl</b>, so that
+/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
static void
-router_add_running_routers_to_smartlist(smartlist_t *sl, int allow_invalid,
- int need_uptime, int need_capacity,
- int need_guard)
-{
- if (!routerlist)
- return;
+router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
+ int need_uptime, int need_capacity,
+ int need_guard, int need_desc)
+{ /* XXXX MOVE */
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (!node->is_running ||
+ (!node->is_valid && !allow_invalid))
+ continue;
+ if (need_desc && !(node->ri || (node->rs && node->md)))
+ continue;
+ if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL)
+ continue;
+ if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
+ continue;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- router->purpose == ROUTER_PURPOSE_GENERAL &&
- (router->is_valid || allow_invalid) &&
- !router_is_unreliable(router, need_uptime,
- need_capacity, need_guard)) {
- /* If it's running, and it's suitable according to the
- * other flags we had in mind */
- smartlist_add(sl, router);
- }
- });
+ smartlist_add(sl, (void *)node);
+ } SMARTLIST_FOREACH_END(node);
}
/** Look through the routerlist until we find a router that has my key.
Return it. */
-routerinfo_t *
+const routerinfo_t *
routerlist_find_my_routerinfo(void)
{
if (!routerlist)
@@ -1541,13 +1572,13 @@ routerlist_find_my_routerinfo(void)
* Don't exit enclave to excluded relays -- it wouldn't actually
* hurt anything, but this way there are fewer confused users.
*/
-routerinfo_t *
+const node_t *
router_find_exact_exit_enclave(const char *address, uint16_t port)
-{
+{/*XXXX MOVE*/
uint32_t addr;
struct in_addr in;
tor_addr_t a;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!tor_inet_aton(address, &in))
return NULL; /* it's not an IP already */
@@ -1555,14 +1586,13 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
tor_addr_from_ipv4h(&a, addr);
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->addr == addr &&
- router->is_running &&
- compare_tor_addr_to_addr_policy(&a, port, router->exit_policy) ==
+ SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, {
+ if (node_get_addr_ipv4h(node) == addr &&
+ node->is_running &&
+ compare_tor_addr_to_node_policy(&a, port, node) ==
ADDR_POLICY_ACCEPTED &&
- !routerset_contains_router(options->_ExcludeExitNodesUnion, router))
- return router;
+ !routerset_contains_node(options->_ExcludeExitNodesUnion, node))
+ return node;
});
return NULL;
}
@@ -1574,14 +1604,14 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
* If <b>need_guard</b>, we require that the router is a possible entry guard.
*/
int
-router_is_unreliable(routerinfo_t *router, int need_uptime,
- int need_capacity, int need_guard)
+node_is_unreliable(const node_t *node, int need_uptime,
+ int need_capacity, int need_guard)
{
- if (need_uptime && !router->is_stable)
+ if (need_uptime && !node->is_stable)
return 1;
- if (need_capacity && !router->is_fast)
+ if (need_capacity && !node->is_fast)
return 1;
- if (need_guard && !router->is_possible_guard)
+ if (need_guard && !node->is_possible_guard)
return 1;
return 0;
}
@@ -1589,7 +1619,7 @@ router_is_unreliable(routerinfo_t *router, int need_uptime,
/** Return the smaller of the router's configured BandwidthRate
* and its advertised capacity. */
uint32_t
-router_get_advertised_bandwidth(routerinfo_t *router)
+router_get_advertised_bandwidth(const routerinfo_t *router)
{
if (router->bandwidthcapacity < router->bandwidthrate)
return router->bandwidthcapacity;
@@ -1603,7 +1633,7 @@ router_get_advertised_bandwidth(routerinfo_t *router)
/** Return the smaller of the router's configured BandwidthRate
* and its advertised capacity, capped by max-believe-bw. */
uint32_t
-router_get_advertised_bandwidth_capped(routerinfo_t *router)
+router_get_advertised_bandwidth_capped(const routerinfo_t *router)
{
uint32_t result = router->bandwidthcapacity;
if (result > router->bandwidthrate)
@@ -1645,13 +1675,10 @@ kb_to_bytes(uint32_t bw)
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random element of smartlist <b>sl</b> of nodes, weighted by
* the advertised bandwidth of each element using the consensus
* bandwidth weights.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1661,10 +1688,9 @@ kb_to_bytes(uint32_t bw)
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
- bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
int64_t weight_scale;
int64_t rand_bw;
@@ -1758,15 +1784,14 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
bandwidths = tor_malloc_zero(sizeof(double)*smartlist_len(sl));
// Cycle through smartlist and total the bandwidth.
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0, is_me = 0;
double weight = 1;
- if (statuses) {
- routerstatus_t *status = smartlist_get(sl, i);
- is_exit = status->is_exit && !status->is_bad_exit;
- is_guard = status->is_possible_guard;
- is_dir = (status->dir_port != 0);
- if (!status->has_bandwidth) {
+ is_exit = node->is_exit && ! node->is_bad_exit;
+ is_guard = node->is_possible_guard;
+ is_dir = node_is_dir(node);
+ if (node->rs) {
+ if (!node->rs->has_bandwidth) {
tor_free(bandwidths);
/* This should never happen, unless all the authorites downgrade
* to 0.2.0 or rogue routerstatuses get inserted into our consensus. */
@@ -1775,26 +1800,17 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
"old router selection algorithm.");
return NULL;
}
- this_bw = kb_to_bytes(status->bandwidth);
- if (router_digest_is_me(status->identity_digest))
- is_me = 1;
+ this_bw = kb_to_bytes(node->rs->bandwidth);
+ } else if (node->ri) {
+ /* bridge or other descriptor not in our consensus */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
+ have_unknown = 1;
} else {
- routerstatus_t *rs;
- routerinfo_t *router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- is_exit = router->is_exit && !router->is_bad_exit;
- is_guard = router->is_possible_guard;
- is_dir = (router->dir_port != 0);
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else { /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
- have_unknown = 1;
- }
- if (router_digest_is_me(router->cache_info.identity_digest))
- is_me = 1;
+ /* We can't use this one. */
+ continue;
}
+ is_me = router_digest_is_me(node->identity);
+
if (is_guard && is_exit) {
weight = (is_dir ? Wdb*Wd : Wd);
} else if (is_guard) {
@@ -1805,11 +1821,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
weight = (is_dir ? Wmb*Wm : Wm);
}
- bandwidths[i] = weight*this_bw;
+ bandwidths[node_sl_idx] = weight*this_bw;
weighted_bw += weight*this_bw;
if (is_me)
sl_last_weighted_bw_of_me = weight*this_bw;
- }
+ } SMARTLIST_FOREACH_END(node);
/* XXXX023 this is a kludge to expose these values. */
sl_last_total_weighted_bw = weighted_bw;
@@ -1857,12 +1873,9 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random node_t element of smartlist <b>sl</b>, weighted by
* the advertised bandwidth of each element.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1872,13 +1885,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
- unsigned int i;
- routerinfo_t *router;
- routerstatus_t *status=NULL;
+ unsigned i;
int32_t *bandwidths;
int is_exit;
int is_guard;
@@ -1919,49 +1930,34 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
guard_bits = bitarray_init_zero(smartlist_len(sl));
/* Iterate over all the routerinfo_t or routerstatus_t, and */
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
/* first, learn what bandwidth we think i has */
int is_known = 1;
int32_t flags = 0;
uint32_t this_bw = 0;
- if (statuses) {
- status = smartlist_get(sl, i);
- if (router_digest_is_me(status->identity_digest))
- me_idx = i;
- router = router_get_by_digest(status->identity_digest);
- is_exit = status->is_exit;
- is_guard = status->is_possible_guard;
- if (status->has_bandwidth) {
- this_bw = kb_to_bytes(status->bandwidth);
+ i = node_sl_idx;
+
+ if (router_digest_is_me(node->identity))
+ me_idx = node_sl_idx;
+
+ is_exit = node->is_exit;
+ is_guard = node->is_possible_guard;
+ if (node->rs) {
+ if (node->rs->has_bandwidth) {
+ this_bw = kb_to_bytes(node->rs->bandwidth);
} else { /* guess */
/* XXX023 once consensuses always list bandwidths, we can take
* this guessing business out. -RD */
is_known = 0;
- flags = status->is_fast ? 1 : 0;
+ flags = node->rs->is_fast ? 1 : 0;
flags |= is_exit ? 2 : 0;
flags |= is_guard ? 4 : 0;
}
- } else {
- routerstatus_t *rs;
- router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- if (router_digest_is_me(router->cache_info.identity_digest))
- me_idx = i;
- is_exit = router->is_exit;
- is_guard = router->is_possible_guard;
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else if (rs) { /* guess; don't trust the descriptor */
- /* XXX023 once consensuses always list bandwidths, we can take
- * this guessing business out. -RD */
- is_known = 0;
- flags = router->is_fast ? 1 : 0;
- flags |= is_exit ? 2 : 0;
- flags |= is_guard ? 4 : 0;
- } else /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
+ } else if (node->ri) {
+ /* Must be a bridge if we're willing to use it */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
}
+
if (is_exit)
bitarray_set(exit_bits, i);
if (is_guard)
@@ -1981,9 +1977,9 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
total_nonexit_bw += this_bw;
} else {
++n_unknown;
- bandwidths[i] = -flags;
+ bandwidths[node_sl_idx] = -flags;
}
- }
+ } SMARTLIST_FOREACH_END(node);
/* Now, fill in the unknown values. */
if (n_unknown) {
@@ -2125,40 +2121,23 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
return smartlist_get(sl, i);
}
-/** Choose a random element of router list <b>sl</b>, weighted by
- * the advertised bandwidth of each router.
- */
-routerinfo_t *
-routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- routerinfo_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 0))) {
- return ret;
- } else {
- return smartlist_choose_by_bandwidth(sl, rule, 0);
- }
-}
-
/** Choose a random element of status list <b>sl</b>, weighted by
- * the advertised bandwidth of each status.
- */
-routerstatus_t *
-routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- /* We are choosing neither exit nor guard here. Weight accordingly. */
- routerstatus_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 1))) {
+ * the advertised bandwidth of each node */
+const node_t *
+node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
+{ /*XXXX MOVE */
+ const node_t *ret;
+ if ((ret = smartlist_choose_node_by_bandwidth_weights(sl, rule))) {
return ret;
} else {
- return smartlist_choose_by_bandwidth(sl, rule, 1);
+ return smartlist_choose_node_by_bandwidth(sl, rule);
}
}
-/** Return a random running router from the routerlist. Never
- * pick a node whose routerinfo is in
- * <b>excludedsmartlist</b>, or whose routerinfo matches <b>excludedset</b>,
+/** Return a random running node from the nodelist. Never
+ * pick a node that is in
+ * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>,
* even if they are the only nodes available.
* If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than
* a minimum uptime, return one of those.
@@ -2170,21 +2149,26 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
* If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if
* picking an exit node, otherwise we weight bandwidths for picking a relay
* node (that is, possibly discounting exit nodes).
+ * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that
+ * have a routerinfo or microdescriptor -- that is, enough info to be
+ * used to build a circuit.
*/
-routerinfo_t *
+const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
routerset_t *excludedset,
router_crn_flags_t flags)
-{
+{ /* XXXX MOVE */
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
+ const int need_desc = (flags & CRN_NEED_DESC) != 0;
smartlist_t *sl=smartlist_create(),
- *excludednodes=smartlist_create();
- routerinfo_t *choice = NULL, *r;
+ *excludednodes=smartlist_create();
+ const node_t *choice = NULL;
+ const routerinfo_t *r;
bandwidth_weight_rule_t rule;
tor_assert(!(weight_for_exit && need_guard));
@@ -2194,29 +2178,26 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
/* Exclude relays that allow single hop exit circuits, if the user
* wants to (such relays might be risky) */
if (get_options()->ExcludeSingleHopRelays) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- if (r->allow_single_hop_exits) {
- smartlist_add(excludednodes, r);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ if (node_allows_single_hop_exits(node)) {
+ smartlist_add(excludednodes, node);
});
}
- if ((r = routerlist_find_my_routerinfo())) {
- smartlist_add(excludednodes, r);
- routerlist_add_family(excludednodes, r);
- }
+ if ((r = routerlist_find_my_routerinfo()))
+ routerlist_add_node_and_family(excludednodes, r);
- router_add_running_routers_to_smartlist(sl, allow_invalid,
- need_uptime, need_capacity,
- need_guard);
+ router_add_running_nodes_to_smartlist(sl, allow_invalid,
+ need_uptime, need_capacity,
+ need_guard, need_desc);
smartlist_subtract(sl,excludednodes);
if (excludedsmartlist)
smartlist_subtract(sl,excludedsmartlist);
if (excludedset)
- routerset_subtract_routers(sl,excludedset);
+ routerset_subtract_nodes(sl,excludedset);
// Always weight by bandwidth
- choice = routerlist_sl_choose_by_bandwidth(sl, rule);
+ choice = node_sl_choose_by_bandwidth(sl, rule);
smartlist_free(sl);
if (!choice && (need_uptime || need_capacity || need_guard)) {
@@ -2239,35 +2220,90 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
return choice;
}
-/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
- * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
- * (which is optionally prefixed with a single dollar sign). Return false if
- * <b>hexdigest</b> is malformed, or it doesn't match. */
-static INLINE int
-hex_digest_matches(const char *hexdigest, const char *identity_digest,
- const char *nickname, int is_named)
+/** Helper: given an extended nickname in <b>hexdigest</b> try to decode it.
+ * Return 0 on success, -1 on failure. Store the result into the
+ * DIGEST_LEN-byte buffer at <b>digest_out</b>, the single character at
+ * <b>nickname_qualifier_char_out</b>, and the MAXNICKNAME_LEN+1-byte buffer
+ * at <b>nickname_out</b>.
+ *
+ * The recognized format is:
+ * HexName = Dollar? HexDigest NamePart?
+ * Dollar = '?'
+ * HexDigest = HexChar*20
+ * HexChar = 'a'..'f' | 'A'..'F' | '0'..'9'
+ * NamePart = QualChar Name
+ * QualChar = '=' | '~'
+ * Name = NameChar*(1..MAX_NICKNAME_LEN)
+ * NameChar = Any ASCII alphanumeric character
+ */
+int
+hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_char_out,
+ char *nickname_out)
{
- char digest[DIGEST_LEN];
size_t len;
+
tor_assert(hexdigest);
if (hexdigest[0] == '$')
++hexdigest;
len = strlen(hexdigest);
- if (len < HEX_DIGEST_LEN)
+ if (len < HEX_DIGEST_LEN) {
+ return -1;
+ } else if (len > HEX_DIGEST_LEN && (hexdigest[HEX_DIGEST_LEN] == '=' ||
+ hexdigest[HEX_DIGEST_LEN] == '~') &&
+ len <= HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN) {
+ *nickname_qualifier_char_out = hexdigest[HEX_DIGEST_LEN];
+ strlcpy(nickname_out, hexdigest+HEX_DIGEST_LEN+1 , MAX_NICKNAME_LEN+1);
+ } else if (len == HEX_DIGEST_LEN) {
+ ;
+ } else {
+ return -1;
+ }
+
+ if (base16_decode(digest_out, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
+ return -1;
+ return 0;
+}
+
+/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
+ * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
+ * (which is optionally prefixed with a single dollar sign). Return false if
+ * <b>hexdigest</b> is malformed, or it doesn't match. */
+static int
+hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
+ const char *nickname, int is_named)
+{
+ char digest[DIGEST_LEN];
+ char nn_char='\0';
+ char nn_buf[MAX_NICKNAME_LEN+1];
+
+ if (hex_digest_nickname_decode(hexdigest, digest, &nn_char, nn_buf) == -1)
return 0;
- else if (len > HEX_DIGEST_LEN &&
- (hexdigest[HEX_DIGEST_LEN] == '=' ||
- hexdigest[HEX_DIGEST_LEN] == '~')) {
- if (strcasecmp(hexdigest+HEX_DIGEST_LEN+1, nickname))
+
+ if (nn_char == '=' || nn_char == '~') {
+ if (!nickname)
+ return 0;
+ if (strcasecmp(nn_buf, nickname))
return 0;
- if (hexdigest[HEX_DIGEST_LEN] == '=' && !is_named)
+ if (nn_char == '=' && !is_named)
return 0;
}
- if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
- return 0;
- return (tor_memeq(digest, identity_digest, DIGEST_LEN));
+ return tor_memeq(digest, identity_digest, DIGEST_LEN);
+}
+
+/* Return true iff <b>router</b> is listed as named in the current
+ * consensus. */
+int
+router_is_named(const routerinfo_t *router)
+{
+ const char *digest =
+ networkstatus_get_router_digest_by_nickname(router->nickname);
+
+ return (digest &&
+ tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN));
}
/** Return true iff the digest of <b>router</b>'s identity key,
@@ -2275,10 +2311,12 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest,
* optionally prefixed with a single dollar sign). Return false if
* <b>hexdigest</b> is malformed, or it doesn't match. */
static INLINE int
-router_hex_digest_matches(routerinfo_t *router, const char *hexdigest)
+router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest)
{
- return hex_digest_matches(hexdigest, router->cache_info.identity_digest,
- router->nickname, router->is_named);
+ return hex_digest_nickname_matches(hexdigest,
+ router->cache_info.identity_digest,
+ router->nickname,
+ router_is_named(router));
}
/** Return true if <b>router</b>'s nickname matches <b>nickname</b>
@@ -2286,20 +2324,43 @@ router_hex_digest_matches(routerinfo_t *router, const char *hexdigest)
* matches a hexadecimal value stored in <b>nickname</b>. Return
* false otherwise. */
static int
-router_nickname_matches(routerinfo_t *router, const char *nickname)
+router_nickname_matches(const routerinfo_t *router, const char *nickname)
{
if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname))
return 1;
return router_hex_digest_matches(router, nickname);
}
+/** Return true if <b>node</b>'s nickname matches <b>nickname</b>
+ * (case-insensitive), or if <b>node's</b> identity key digest
+ * matches a hexadecimal value stored in <b>nickname</b>. Return
+ * false otherwise. */
+static int
+node_nickname_matches(const node_t *node, const char *nickname)
+{
+ const char *n = node_get_nickname(node);
+ if (n && nickname[0]!='$' && !strcasecmp(n, nickname))
+ return 1;
+ return hex_digest_nickname_matches(nickname,
+ node->identity,
+ n,
+ node_is_named(node));
+}
+
/** Return the router in our routerlist whose (case-insensitive)
* nickname or (case-sensitive) hexadecimal key digest is
* <b>nickname</b>. Return NULL if no such router is known.
*/
-routerinfo_t *
+const routerinfo_t *
router_get_by_nickname(const char *nickname, int warn_if_unnamed)
{
+#if 1
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->ri;
+ else
+ return NULL;
+#else
int maybedigest;
char digest[DIGEST_LEN];
routerinfo_t *best_match=NULL;
@@ -2345,15 +2406,14 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
if (warn_if_unnamed && n_matches > 1) {
smartlist_t *fps = smartlist_create();
int any_unwarned = 0;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
+ SMARTLIST_FOREACH_BEGIN(routerlist->routers, routerinfo_t *, router) {
routerstatus_t *rs;
char *desc;
size_t dlen;
char fp[HEX_DIGEST_LEN+1];
if (strcasecmp(router->nickname, nickname))
continue;
- rs = router_get_consensus_status_by_id(
+ rs = router_get_mutable_consensus_status_by_id(
router->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
rs->name_lookup_warned = 1;
@@ -2366,7 +2426,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d",
fp, router->address, router->or_port);
smartlist_add(fps, desc);
- });
+ } SMARTLIST_FOREACH_END(router);
if (any_unwarned) {
char *alternatives = smartlist_join_strings(fps, "; ",0,NULL);
log_warn(LD_CONFIG,
@@ -2379,7 +2439,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
smartlist_free(fps);
} else if (warn_if_unnamed) {
- routerstatus_t *rs = router_get_consensus_status_by_id(
+ routerstatus_t *rs = router_get_mutable_consensus_status_by_id(
best_match->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
char fp[HEX_DIGEST_LEN+1];
@@ -2395,27 +2455,15 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
}
return best_match;
}
-
return NULL;
-}
-
-/** Try to find a routerinfo for <b>digest</b>. If we don't have one,
- * return 1. If we do, ask tor_version_as_new_as() for the answer.
- */
-int
-router_digest_version_as_new_as(const char *digest, const char *cutoff)
-{
- routerinfo_t *router = router_get_by_digest(digest);
- if (!router)
- return 1;
- return tor_version_as_new_as(router->platform, cutoff);
+#endif
}
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero, any authority is okay. */
int
-router_digest_is_trusted_dir_type(const char *digest, authority_type_t type)
+router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
{
if (!trusted_dir_servers)
return 0;
@@ -2459,44 +2507,20 @@ hexdigest_to_digest(const char *hexdigest, char *digest)
/** Return the router in our routerlist whose hexadecimal key digest
* is <b>hexdigest</b>. Return NULL if no such router is known. */
-routerinfo_t *
+const routerinfo_t *
router_get_by_hexdigest(const char *hexdigest)
{
- char digest[DIGEST_LEN];
- size_t len;
- routerinfo_t *ri;
-
- tor_assert(hexdigest);
- if (!routerlist)
- return NULL;
- if (hexdigest[0]=='$')
- ++hexdigest;
- len = strlen(hexdigest);
- if (hexdigest_to_digest(hexdigest, digest) < 0)
+ if (is_legal_nickname(hexdigest))
return NULL;
- ri = router_get_by_digest(digest);
-
- if (ri && len > HEX_DIGEST_LEN) {
- if (hexdigest[HEX_DIGEST_LEN] == '=') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1) ||
- !ri->is_named)
- return NULL;
- } else if (hexdigest[HEX_DIGEST_LEN] == '~') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1))
- return NULL;
- } else {
- return NULL;
- }
- }
-
- return ri;
+ /* It's not a legal nickname, so it must be a hexdigest or nothing. */
+ return router_get_by_nickname(hexdigest, 1);
}
-/** Return the router in our routerlist whose 20-byte key digest
- * is <b>digest</b>. Return NULL if no such router is known. */
+/** As router_get_by_id_digest,but return a pointer that you're allowed to
+ * modify */
routerinfo_t *
-router_get_by_digest(const char *digest)
+router_get_mutable_by_digest(const char *digest)
{
tor_assert(digest);
@@ -2507,6 +2531,14 @@ router_get_by_digest(const char *digest)
return rimap_get(routerlist->identity_map, digest);
}
+/** Return the router in our routerlist whose 20-byte key digest
+ * is <b>digest</b>. Return NULL if no such router is known. */
+const routerinfo_t *
+router_get_by_id_digest(const char *digest)
+{
+ return router_get_mutable_by_digest(digest);
+}
+
/** Return the router in our routerlist whose 20-byte descriptor
* is <b>digest</b>. Return NULL if no such router is known. */
signed_descriptor_t *
@@ -2557,7 +2589,7 @@ extrainfo_get_by_descriptor_digest(const char *digest)
* The caller must not free the string returned.
*/
static const char *
-signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+signed_descriptor_get_body_impl(const signed_descriptor_t *desc,
int with_annotations)
{
const char *r = NULL;
@@ -2606,7 +2638,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc,
* The caller must not free the string returned.
*/
const char *
-signed_descriptor_get_body(signed_descriptor_t *desc)
+signed_descriptor_get_body(const signed_descriptor_t *desc)
{
return signed_descriptor_get_body_impl(desc, 0);
}
@@ -2614,7 +2646,7 @@ signed_descriptor_get_body(signed_descriptor_t *desc)
/** As signed_descriptor_get_body(), but points to the beginning of the
* annotations section rather than the beginning of the descriptor. */
const char *
-signed_descriptor_get_annotations(signed_descriptor_t *desc)
+signed_descriptor_get_annotations(const signed_descriptor_t *desc)
{
return signed_descriptor_get_body_impl(desc, 1);
}
@@ -2667,7 +2699,6 @@ routerinfo_free(routerinfo_t *router)
}
addr_policy_list_free(router->exit_policy);
- /* XXXX Remove if this turns out to affect performance. */
memset(router, 77, sizeof(routerinfo_t));
tor_free(router);
@@ -2682,7 +2713,6 @@ extrainfo_free(extrainfo_t *extrainfo)
tor_free(extrainfo->cache_info.signed_descriptor_body);
tor_free(extrainfo->pending_sig);
- /* XXXX remove this if it turns out to slow us down. */
memset(extrainfo, 88, sizeof(extrainfo_t)); /* debug bad memory usage */
tor_free(extrainfo);
}
@@ -2696,7 +2726,6 @@ signed_descriptor_free(signed_descriptor_t *sd)
tor_free(sd->signed_descriptor_body);
- /* XXXX remove this once more bugs go away. */
memset(sd, 99, sizeof(signed_descriptor_t)); /* Debug bad mem usage */
tor_free(sd);
}
@@ -2802,8 +2831,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
routerinfo_t *ri_old;
signed_descriptor_t *sd_old;
{
- /* XXXX Remove if this slows us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri);
}
tor_assert(ri->cache_info.routerlist_index == -1);
@@ -2825,6 +2853,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
&ri->cache_info);
smartlist_add(rl->routers, ri);
ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1;
+ nodelist_add_routerinfo(ri);
router_dir_info_changed();
#ifdef DEBUG_ROUTERLIST
routerlist_assert_ok(rl);
@@ -2845,7 +2874,6 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
extrainfo_t *ei_tmp;
{
- /* XXXX remove this code if it slows us down. */
extrainfo_t *ei_generated = router_get_my_extrainfo();
tor_assert(ei_generated != ei);
}
@@ -2891,8 +2919,7 @@ static void
routerlist_insert_old(routerlist_t *rl, routerinfo_t *ri)
{
{
- /* XXXX remove this code if it slows us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri);
}
tor_assert(ri->cache_info.routerlist_index == -1);
@@ -2932,6 +2959,8 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, time_t now)
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri);
+ nodelist_remove_routerinfo(ri);
+
/* make sure the rephist module knows that it's not running */
rep_hist_note_router_unreachable(ri->cache_info.identity_digest, now);
@@ -3043,8 +3072,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
routerinfo_t *ri_tmp;
extrainfo_t *ei_tmp;
{
- /* XXXX Remove this if it turns out to slow us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri_new);
}
tor_assert(ri_old != ri_new);
@@ -3054,6 +3082,9 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri_old);
+ nodelist_remove_routerinfo(ri_old);
+ nodelist_add_routerinfo(ri_new);
+
router_dir_info_changed();
if (idx >= 0) {
smartlist_set(rl->routers, idx, ri_new);
@@ -3200,28 +3231,25 @@ routerlist_reset_warnings(void)
void
router_set_status(const char *digest, int up)
{
- routerinfo_t *router;
- routerstatus_t *status;
+ node_t *node;
tor_assert(digest);
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
if (tor_memeq(d->digest, digest, DIGEST_LEN))
d->is_running = up);
- router = router_get_by_digest(digest);
- if (router) {
+ node = node_get_mutable_by_id(digest);
+ if (node) {
+#if 0
log_debug(LD_DIR,"Marking router %s as %s.",
- router_describe(router), up ? "up" : "down");
- if (!up && router_is_me(router) && !we_are_hibernating())
+ node_describe(node), up ? "up" : "down");
+#endif
+ if (!up && node_is_me(node) && !net_is_disabled())
log_warn(LD_NET, "We just marked ourself as down. Are your external "
"addresses reachable?");
- router->is_running = up;
- }
- status = router_get_consensus_status_by_id(digest);
- if (status && status->is_running != up) {
- status->is_running = up;
- control_event_networkstatus_changed_single(status);
+ node->is_running = up;
}
+
router_dir_info_changed();
}
@@ -3250,11 +3278,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
int from_cache, int from_fetch)
{
const char *id_digest;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authdir = authdir_mode_handles_descs(options, router->purpose);
int authdir_believes_valid = 0;
routerinfo_t *old_router;
- networkstatus_t *consensus = networkstatus_get_latest_consensus();
+ networkstatus_t *consensus =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_NS);
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
int in_consensus = 0;
@@ -3265,7 +3294,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
id_digest = router->cache_info.identity_digest;
- old_router = router_get_by_digest(id_digest);
+ old_router = router_get_mutable_by_digest(id_digest);
/* Make sure that we haven't already got this exact descriptor. */
if (sdmap_get(routerlist->desc_digest_map,
@@ -3297,12 +3326,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (authdir) {
if (authdir_wants_to_reject_router(router, msg,
- !from_cache && !from_fetch)) {
+ !from_cache && !from_fetch,
+ &authdir_believes_valid)) {
tor_assert(*msg);
routerinfo_free(router);
return ROUTER_AUTHDIR_REJECTS;
}
- authdir_believes_valid = router->is_valid;
} else if (from_fetch) {
/* Only check the descriptor digest against the network statuses when
* we are receiving in response to a fetch. */
@@ -3329,14 +3358,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
routerstatus_t *rs =
- networkstatus_v2_find_entry(ns, id_digest);
+ networkstatus_v2_find_mutable_entry(ns, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN))
rs->need_to_mirror = 0;
});
if (consensus) {
- routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest);
+ routerstatus_t *rs = networkstatus_vote_find_mutable_entry(
+ consensus, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN)) {
@@ -3950,7 +3980,7 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
static int
signed_desc_digest_is_recognized(signed_descriptor_t *desc)
{
- routerstatus_t *rs;
+ const routerstatus_t *rs;
networkstatus_t *consensus = networkstatus_get_latest_consensus();
int caches = directory_caches_dir_info(get_options());
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
@@ -3974,6 +4004,18 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
return 0;
}
+/** Update downloads for router descriptors and/or microdescriptors as
+ * appropriate. */
+void
+update_all_descriptor_downloads(time_t now)
+{
+ if (get_options()->DisableNetwork)
+ return;
+ update_router_descriptor_downloads(now);
+ update_microdesc_downloads(now);
+ launch_dummy_descriptor_download_as_needed(now, get_options());
+}
+
/** Clear all our timeouts for fetching v2 and v3 directory stuff, and then
* give it all a try again. */
void
@@ -3981,35 +4023,37 @@ routerlist_retry_directory_downloads(time_t now)
{
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
+ if (get_options()->DisableNetwork)
+ return;
update_networkstatus_downloads(now);
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
}
-/** Return 1 if all running sufficiently-stable routers will reject
+/** Return 1 if all running sufficiently-stable routers we can use will reject
* addr:port, return 0 if any might accept it. */
int
-router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime)
-{
+router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
+ int need_uptime)
+{ /* XXXX MOVE */
addr_policy_result_t r;
- if (!routerlist) return 1;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- !router_is_unreliable(router, need_uptime, 0, 0)) {
- r = compare_addr_to_addr_policy(addr, port, router->exit_policy);
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (node->is_running &&
+ !node_is_unreliable(node, need_uptime, 0, 0)) {
+
+ r = compare_tor_addr_to_node_policy(addr, port, node);
+
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 0; /* this one could be ok. good enough. */
}
- });
+ } SMARTLIST_FOREACH_END(node);
return 1; /* all will reject. */
}
/** Return true iff <b>router</b> does not permit exit streams.
*/
int
-router_exit_policy_rejects_all(routerinfo_t *router)
+router_exit_policy_rejects_all(const routerinfo_t *router)
{
return router->policy_is_reject_star;
}
@@ -4022,7 +4066,7 @@ trusted_dir_server_t *
add_trusted_dir_server(const char *nickname, const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
- authority_type_t type)
+ dirinfo_type_t type)
{
trusted_dir_server_t *ent;
uint32_t a;
@@ -4057,7 +4101,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
ent->is_running = 1;
ent->type = type;
memcpy(ent->digest, digest, DIGEST_LEN);
- if (v3_auth_digest && (type & V3_AUTHORITY))
+ if (v3_auth_digest && (type & V3_DIRINFO))
memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@@ -4136,7 +4180,7 @@ int
any_trusted_dir_is_v1_authority(void)
{
if (trusted_dir_servers)
- return get_n_authorities(V1_AUTHORITY) > 0;
+ return get_n_authorities(V1_DIRINFO) > 0;
return 0;
}
@@ -4144,7 +4188,9 @@ any_trusted_dir_is_v1_authority(void)
/** For every current directory connection whose purpose is <b>purpose</b>,
* and where the resource being downloaded begins with <b>prefix</b>, split
* rest of the resource into base16 fingerprints, decode them, and set the
- * corresponding elements of <b>result</b> to a nonzero value. */
+ * corresponding elements of <b>result</b> to a nonzero value.
+ * DOCDOC purpose==microdesc
+ */
static void
list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix)
@@ -4152,20 +4198,23 @@ list_pending_downloads(digestmap_t *result,
const size_t p_len = strlen(prefix);
smartlist_t *tmp = smartlist_create();
smartlist_t *conns = get_connection_array();
+ int flags = DSR_HEX;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC)
+ flags = DSR_DIGEST256|DSR_BASE64;
tor_assert(result);
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
conn->purpose == purpose &&
!conn->marked_for_close) {
const char *resource = TO_DIR_CONN(conn)->requested_resource;
if (!strcmpstart(resource, prefix))
dir_split_resource_into_fingerprints(resource + p_len,
- tmp, NULL, DSR_HEX);
+ tmp, NULL, flags);
}
- });
+ } SMARTLIST_FOREACH_END(conn);
+
SMARTLIST_FOREACH(tmp, char *, d,
{
digestmap_set(result, d, (void*)1);
@@ -4185,13 +4234,21 @@ list_pending_descriptor_downloads(digestmap_t *result, int extrainfo)
list_pending_downloads(result, purpose, "d/");
}
-/** Launch downloads for all the descriptors whose digests are listed
- * as digests[i] for lo <= i < hi. (Lo and hi may be out of range.)
- * If <b>source</b> is given, download from <b>source</b>; otherwise,
- * download from an appropriate random directory server.
+/** DOCDOC */
+/*XXXX NM should use digest256, if one comes into being. */
+void
+list_pending_microdesc_downloads(digestmap_t *result)
+{
+ list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/");
+}
+
+/** Launch downloads for all the descriptors whose digests or digests256
+ * are listed as digests[i] for lo <= i < hi. (Lo and hi may be out of
+ * range.) If <b>source</b> is given, download from <b>source</b>;
+ * otherwise, download from an appropriate random directory server.
*/
static void
-initiate_descriptor_downloads(routerstatus_t *source,
+initiate_descriptor_downloads(const routerstatus_t *source,
int purpose,
smartlist_t *digests,
int lo, int hi, int pds_flags)
@@ -4199,6 +4256,20 @@ initiate_descriptor_downloads(routerstatus_t *source,
int i, n = hi-lo;
char *resource, *cp;
size_t r_len;
+
+ int digest_len = DIGEST_LEN, enc_digest_len = HEX_DIGEST_LEN;
+ char sep = '+';
+ int b64_256 = 0;
+
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ /* Microdescriptors are downloaded by "-"-separated base64-encoded
+ * 256-bit digests. */
+ digest_len = DIGEST256_LEN;
+ enc_digest_len = BASE64_DIGEST256_LEN;
+ sep = '-';
+ b64_256 = 1;
+ }
+
if (n <= 0)
return;
if (lo < 0)
@@ -4206,15 +4277,19 @@ initiate_descriptor_downloads(routerstatus_t *source,
if (hi > smartlist_len(digests))
hi = smartlist_len(digests);
- r_len = 8 + (HEX_DIGEST_LEN+1)*n;
+ r_len = 8 + (enc_digest_len+1)*n;
cp = resource = tor_malloc(r_len);
memcpy(cp, "d/", 2);
cp += 2;
for (i = lo; i < hi; ++i) {
- base16_encode(cp, r_len-(cp-resource),
- smartlist_get(digests,i), DIGEST_LEN);
- cp += HEX_DIGEST_LEN;
- *cp++ = '+';
+ if (b64_256) {
+ digest256_to_base64(cp, smartlist_get(digests, i));
+ } else {
+ base16_encode(cp, r_len-(cp-resource),
+ smartlist_get(digests,i), digest_len);
+ }
+ cp += enc_digest_len;
+ *cp++ = sep;
}
memcpy(cp-1, ".z", 3);
@@ -4235,9 +4310,10 @@ initiate_descriptor_downloads(routerstatus_t *source,
* running, or otherwise not a descriptor that we would make any
* use of even if we had it. Else return 1. */
static INLINE int
-client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
+client_would_use_router(const routerstatus_t *rs, time_t now,
+ const or_options_t *options)
{
- if (!rs->is_running && !options->FetchUselessDescriptors) {
+ if (!rs->is_flagged_running && !options->FetchUselessDescriptors) {
/* If we had this router descriptor, we wouldn't even bother using it.
* But, if we want to have a complete list, fetch it anyway. */
return 0;
@@ -4261,6 +4337,7 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
* So use 96 because it's a nice number.
*/
#define MAX_DL_PER_REQUEST 96
+#define MAX_MICRODESC_DL_PER_REQUEST 92
/** Don't split our requests so finely that we are requesting fewer than
* this number per server. */
#define MIN_DL_PER_REQUEST 4
@@ -4275,35 +4352,49 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
* them until they have more, or until this amount of time has passed. */
#define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
-/** Given a list of router descriptor digests in <b>downloadable</b>, decide
- * whether to delay fetching until we have more. If we don't want to delay,
- * launch one or more requests to the appropriate directory authorities. */
-static void
-launch_router_descriptor_downloads(smartlist_t *downloadable,
- routerstatus_t *source, time_t now)
+/** Given a <b>purpose</b> (FETCH_MICRODESC or FETCH_SERVERDESC) and a list of
+ * router descriptor digests or microdescriptor digest256s in
+ * <b>downloadable</b>, decide whether to delay fetching until we have more.
+ * If we don't want to delay, launch one or more requests to the appropriate
+ * directory authorities.
+ */
+void
+launch_descriptor_downloads(int purpose,
+ smartlist_t *downloadable,
+ const routerstatus_t *source, time_t now)
{
int should_delay = 0, n_downloadable;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ const char *descname;
+
+ tor_assert(purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
+ purpose == DIR_PURPOSE_FETCH_MICRODESC);
+
+ descname = (purpose == DIR_PURPOSE_FETCH_SERVERDESC) ?
+ "routerdesc" : "microdesc";
n_downloadable = smartlist_len(downloadable);
if (!directory_fetches_dir_info_early(options)) {
if (n_downloadable >= MAX_DL_TO_DELAY) {
log_debug(LD_DIR,
- "There are enough downloadable routerdescs to launch requests.");
+ "There are enough downloadable %ss to launch requests.",
+ descname);
should_delay = 0;
} else {
- should_delay = (last_routerdesc_download_attempted +
+ should_delay = (last_descriptor_download_attempted +
MAX_CLIENT_INTERVAL_WITHOUT_REQUEST) > now;
if (!should_delay && n_downloadable) {
- if (last_routerdesc_download_attempted) {
+ if (last_descriptor_download_attempted) {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we've "
+ "There are not many downloadable %ss, but we've "
"been waiting long enough (%d seconds). Downloading.",
- (int)(now-last_routerdesc_download_attempted));
+ descname,
+ (int)(now-last_descriptor_download_attempted));
} else {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we haven't "
- "tried downloading descriptors recently. Downloading.");
+ "There are not many downloadable %ss, but we haven't "
+ "tried downloading descriptors recently. Downloading.",
+ descname);
}
}
}
@@ -4330,12 +4421,19 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
* update_router_descriptor_downloads() later on, once the connections
* have succeeded or failed.
*/
- pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH;
+ pds_flags |= (purpose == DIR_PURPOSE_FETCH_MICRODESC) ?
+ PDS_NO_EXISTING_MICRODESC_FETCH :
+ PDS_NO_EXISTING_SERVERDESC_FETCH;
}
n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS);
- if (n_per_request > MAX_DL_PER_REQUEST)
- n_per_request = MAX_DL_PER_REQUEST;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ if (n_per_request > MAX_MICRODESC_DL_PER_REQUEST)
+ n_per_request = MAX_MICRODESC_DL_PER_REQUEST;
+ } else {
+ if (n_per_request > MAX_DL_PER_REQUEST)
+ n_per_request = MAX_DL_PER_REQUEST;
+ }
if (n_per_request < MIN_DL_PER_REQUEST)
n_per_request = MIN_DL_PER_REQUEST;
@@ -4350,11 +4448,11 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
req_plural, n_downloadable, rtr_plural, n_per_request);
smartlist_sort_digests(downloadable);
for (i=0; i < n_downloadable; i += n_per_request) {
- initiate_descriptor_downloads(source, DIR_PURPOSE_FETCH_SERVERDESC,
+ initiate_descriptor_downloads(source, purpose,
downloadable, i, i+n_per_request,
pds_flags);
}
- last_routerdesc_download_attempted = now;
+ last_descriptor_download_attempted = now;
}
}
@@ -4370,7 +4468,7 @@ update_router_descriptor_cache_downloads_v2(time_t now)
digestmap_t *map; /* Which descs are in progress, or assigned? */
int i, j, n;
int n_download;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
if (! directory_fetches_dir_info_early(options)) {
@@ -4512,7 +4610,7 @@ void
update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *map = NULL;
smartlist_t *no_longer_old = smartlist_create();
smartlist_t *downloadable = smartlist_create();
@@ -4540,15 +4638,14 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
map = digestmap_new();
list_pending_descriptor_downloads(map, 0);
- SMARTLIST_FOREACH(consensus->routerstatus_list, void *, rsp,
- {
+ SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) {
routerstatus_t *rs =
is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp;
signed_descriptor_t *sd;
if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) {
- routerinfo_t *ri;
+ const routerinfo_t *ri;
++n_have;
- if (!(ri = router_get_by_digest(rs->identity_digest)) ||
+ if (!(ri = router_get_by_id_digest(rs->identity_digest)) ||
tor_memneq(ri->cache_info.signed_descriptor_digest,
sd->signed_descriptor_digest, DIGEST_LEN)) {
/* We have a descriptor with this digest, but either there is no
@@ -4581,7 +4678,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
if (is_vote && source) {
char time_bufnew[ISO_TIME_LEN+1];
char time_bufold[ISO_TIME_LEN+1];
- routerinfo_t *oldrouter = router_get_by_digest(rs->identity_digest);
+ const routerinfo_t *oldrouter;
+ oldrouter = router_get_by_id_digest(rs->identity_digest);
format_iso_time(time_bufnew, rs->published_on);
if (oldrouter)
format_iso_time(time_bufold, oldrouter->cache_info.published_on);
@@ -4592,7 +4690,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
source->nickname, oldrouter ? "known" : "unknown");
}
smartlist_add(downloadable, rs->descriptor_digest);
- });
+ } SMARTLIST_FOREACH_END(rsp);
if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)
&& smartlist_len(no_longer_old)) {
@@ -4624,7 +4722,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters,
n_would_reject, n_wouldnt_use, n_inprogress);
- launch_router_descriptor_downloads(downloadable, source, now);
+ launch_descriptor_downloads(DIR_PURPOSE_FETCH_SERVERDESC,
+ downloadable, source, now);
digestmap_free(map, NULL);
done:
@@ -4638,27 +4737,20 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
* do this only when we aren't seeing incoming data. see bug 652. */
#define DUMMY_DOWNLOAD_INTERVAL (20*60)
-/** Launch downloads for router status as needed. */
-void
-update_router_descriptor_downloads(time_t now)
+/** As needed, launch a dummy router descriptor fetch to see if our
+ * address has changed. */
+static void
+launch_dummy_descriptor_download_as_needed(time_t now,
+ const or_options_t *options)
{
- or_options_t *options = get_options();
static time_t last_dummy_download = 0;
- if (should_delay_dir_fetches(options))
- return;
- if (directory_fetches_dir_info_early(options)) {
- update_router_descriptor_cache_downloads_v2(now);
- }
- update_consensus_router_descriptor_downloads(now, 0,
- networkstatus_get_reasonably_live_consensus(now));
-
/* XXXX023 we could be smarter here; see notes on bug 652. */
/* If we're a server that doesn't have a configured address, we rely on
* directory fetches to learn when our address changes. So if we haven't
* tried to get any routerdescs in a long time, try a dummy fetch now. */
if (!options->Address &&
server_mode(options) &&
- last_routerdesc_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
+ last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) {
last_dummy_download = now;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
@@ -4667,11 +4759,28 @@ update_router_descriptor_downloads(time_t now)
}
}
+/** Launch downloads for router status as needed. */
+void
+update_router_descriptor_downloads(time_t now)
+{
+ const or_options_t *options = get_options();
+ if (should_delay_dir_fetches(options))
+ return;
+ if (!we_fetch_router_descriptors(options))
+ return;
+ if (directory_fetches_dir_info_early(options)) {
+ update_router_descriptor_cache_downloads_v2(now);
+ }
+
+ update_consensus_router_descriptor_downloads(now, 0,
+ networkstatus_get_reasonably_live_consensus(now, FLAV_NS));
+}
+
/** Launch extrainfo downloads as needed. */
void
update_extrainfo_downloads(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
routerlist_t *rl;
smartlist_t *wanted;
digestmap_t *pending;
@@ -4699,7 +4808,7 @@ update_extrainfo_downloads(time_t now)
sd = &((routerinfo_t*)smartlist_get(lst, i))->cache_info;
if (sd->is_extrainfo)
continue; /* This should never happen. */
- if (old_routers && !router_get_by_digest(sd->identity_digest))
+ if (old_routers && !router_get_by_id_digest(sd->identity_digest))
continue; /* Couldn't check the signature if we got it. */
if (sd->extrainfo_is_bogus)
continue;
@@ -4793,23 +4902,31 @@ get_dir_info_status_string(void)
static void
count_usable_descriptors(int *num_present, int *num_usable,
const networkstatus_t *consensus,
- or_options_t *options, time_t now,
+ const or_options_t *options, time_t now,
routerset_t *in_set)
{
+ const int md = (consensus->flavor == FLAV_MICRODESC);
*num_present = 0, *num_usable=0;
- SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
- {
- if (in_set && ! routerset_contains_routerstatus(in_set, rs))
+ SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
+ {
+ if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
continue;
if (client_would_use_router(rs, now, options)) {
+ const char * const digest = rs->descriptor_digest;
+ int present;
++*num_usable; /* the consensus says we want it. */
- if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
+ if (md)
+ present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest);
+ else
+ present = NULL != router_get_by_descriptor_digest(digest);
+ if (present) {
/* we have the descriptor listed in the consensus. */
++*num_present;
}
}
- });
+ }
+ SMARTLIST_FOREACH_END(rs);
log_debug(LD_DIR, "%d usable, %d present.", *num_usable, *num_present);
}
@@ -4823,7 +4940,7 @@ count_loading_descriptors_progress(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now);
+ networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
double fraction;
if (!consensus)
@@ -4851,16 +4968,17 @@ update_router_have_minimum_dir_info(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
int res;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now);
+ networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
+ int using_md;
if (!consensus) {
if (!networkstatus_get_latest_consensus())
- strlcpy(dir_info_status, "We have no network-status consensus.",
+ strlcpy(dir_info_status, "We have no usable consensus.",
sizeof(dir_info_status));
else
- strlcpy(dir_info_status, "We have no recent network-status consensus.",
+ strlcpy(dir_info_status, "We have no recent usable consensus.",
sizeof(dir_info_status));
res = 0;
goto done;
@@ -4874,19 +4992,22 @@ update_router_have_minimum_dir_info(void)
goto done;
}
+ using_md = consensus->flavor == FLAV_MICRODESC;
+
count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
NULL);
if (num_present < num_usable/4) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
- "We have only %d/%d usable descriptors.", num_present, num_usable);
+ "We have only %d/%d usable %sdescriptors.",
+ num_present, num_usable, using_md ? "micro" : "");
res = 0;
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
goto done;
} else if (num_present < 2) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
- "Only %d descriptor%s here and believed reachable!",
- num_present, num_present ? "" : "s");
+ "Only %d %sdescriptor%s here and believed reachable!",
+ num_present, using_md ? "micro" : "", num_present ? "" : "s");
res = 0;
goto done;
}
@@ -4898,8 +5019,8 @@ update_router_have_minimum_dir_info(void)
if (!num_usable || !num_present) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
- "We have only %d/%d usable entry node descriptors.",
- num_present, num_usable);
+ "We have only %d/%d usable entry node %sdescriptors.",
+ num_present, num_usable, using_md?"micro":"");
res = 0;
goto done;
}
@@ -4939,7 +5060,7 @@ void
router_reset_descriptor_download_failures(void)
{
networkstatus_reset_download_failures();
- last_routerdesc_download_attempted = 0;
+ last_descriptor_download_attempted = 0;
if (!routerlist)
return;
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
@@ -4963,7 +5084,7 @@ router_reset_descriptor_download_failures(void)
* would not cause a recent (post 0.1.1.6) dirserver to republish.
*/
int
-router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
+router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
{
time_t r1pub, r2pub;
long time_difference;
@@ -4971,7 +5092,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
/* r1 should be the one that was published first. */
if (r1->cache_info.published_on > r2->cache_info.published_on) {
- routerinfo_t *ri_tmp = r2;
+ const routerinfo_t *ri_tmp = r2;
r2 = r1;
r1 = ri_tmp;
}
@@ -4990,7 +5111,6 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
(r1->contact_info && r2->contact_info &&
strcasecmp(r1->contact_info, r2->contact_info)) ||
r1->is_hibernating != r2->is_hibernating ||
- r1->has_old_dnsworkers != r2->has_old_dnsworkers ||
cmp_addr_policies(r1->exit_policy, r2->exit_policy))
return 0;
if ((r1->declared_family == NULL) != (r2->declared_family == NULL))
@@ -5045,7 +5165,8 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
* incompatibility (if any).
**/
int
-routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
+routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
+ extrainfo_t *ei,
signed_descriptor_t *sd,
const char **msg)
{
@@ -5053,7 +5174,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
tor_assert(ri);
tor_assert(ei);
if (!sd)
- sd = &ri->cache_info;
+ sd = (signed_descriptor_t*)&ri->cache_info;
if (ei->bad_sig) {
if (msg) *msg = "Extrainfo signature was bad, or signed with wrong key.";
@@ -5118,7 +5239,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
/** Assert that the internal representation of <b>rl</b> is
* self-consistent. */
void
-routerlist_assert_ok(routerlist_t *rl)
+routerlist_assert_ok(const routerlist_t *rl)
{
routerinfo_t *r2;
signed_descriptor_t *sd2;
@@ -5208,7 +5329,7 @@ routerlist_assert_ok(routerlist_t *rl)
* If <b>router</b> is NULL, it just frees its internal memory and returns.
*/
const char *
-esc_router_info(routerinfo_t *router)
+esc_router_info(const routerinfo_t *router)
{
static char *info=NULL;
char *esc_contact, *esc_platform;
@@ -5310,38 +5431,6 @@ routerset_get_countryname(const char *c)
return country;
}
-#if 0
-/** Add the GeoIP database's integer index (+1) of a valid two-character
- * country code to the routerset's <b>countries</b> bitarray. Return the
- * integer index if the country code is valid, -1 otherwise.*/
-static int
-routerset_add_country(const char *c)
-{
- char country[3];
- country_t cc;
-
- /* XXXX: Country codes must be of the form \{[a-z\?]{2}\} but this accepts
- \{[.]{2}\}. Do we need to be strict? -RH */
- /* Nope; if the country code is bad, we'll get 0 when we look it up. */
-
- if (!geoip_is_loaded()) {
- log(LOG_WARN, LD_CONFIG, "GeoIP database not loaded: Cannot add country"
- "entry %s, ignoring.", c);
- return -1;
- }
-
- memcpy(country, c+1, 2);
- country[2] = '\0';
- tor_strlower(country);
-
- if ((cc=geoip_get_country(country))==-1) {
- log(LOG_WARN, LD_CONFIG, "Country code '%s' is not valid, ignoring.",
- country);
- }
- return cc;
-}
-#endif
-
/** Update the routerset's <b>countries</b> bitarray_t. Called whenever
* the GeoIP database is reloaded.
*/
@@ -5430,7 +5519,7 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
void
refresh_all_country_info(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->EntryNodes)
routerset_refresh_countries(options->EntryNodes);
@@ -5443,7 +5532,7 @@ refresh_all_country_info(void)
if (options->_ExcludeExitNodesUnion)
routerset_refresh_countries(options->_ExcludeExitNodesUnion);
- routerlist_refresh_countries();
+ nodelist_refresh_countries();
}
/** Add all members of the set <b>source</b> to <b>target</b>. */
@@ -5493,11 +5582,11 @@ routerset_is_empty(const routerset_t *set)
static int
routerset_contains(const routerset_t *set, const tor_addr_t *addr,
uint16_t orport,
- const char *nickname, const char *id_digest, int is_named,
+ const char *nickname, const char *id_digest,
country_t country)
{
- if (!set || !set->list) return 0;
- (void) is_named; /* not supported */
+ if (!set || !set->list)
+ return 0;
if (nickname && strmap_get_lc(set->names, nickname))
return 4;
if (id_digest && digestmap_get(set->digests, id_digest))
@@ -5525,13 +5614,14 @@ routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
ei->port,
ei->nickname,
ei->identity_digest,
- -1, /*is_named*/
-1 /*country*/);
}
-/** Return true iff <b>ri</b> is in <b>set</b>. */
+/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_router(const routerset_t *set, routerinfo_t *ri)
+routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -5540,13 +5630,15 @@ routerset_contains_router(const routerset_t *set, routerinfo_t *ri)
ri->or_port,
ri->nickname,
ri->cache_info.identity_digest,
- ri->is_named,
- ri->country);
+ country);
}
-/** Return true iff <b>rs</b> is in <b>set</b>. */
+/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs)
+routerset_contains_routerstatus(const routerset_t *set,
+ const routerstatus_t *rs,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, rs->addr);
@@ -5555,50 +5647,59 @@ routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs)
rs->or_port,
rs->nickname,
rs->identity_digest,
- rs->is_named,
- -1);
+ country);
+}
+
+/** Return true iff <b>node</b> is in <b>set</b>. */
+int
+routerset_contains_node(const routerset_t *set, const node_t *node)
+{
+ if (node->rs)
+ return routerset_contains_routerstatus(set, node->rs, node->country);
+ else if (node->ri)
+ return routerset_contains_router(set, node->ri, node->country);
+ else
+ return 0;
}
-/** Add every known routerinfo_t that is a member of <b>routerset</b> to
+/** Add every known node_t that is a member of <b>routerset</b> to
* <b>out</b>, but never add any that are part of <b>excludeset</b>.
* If <b>running_only</b>, only add the running ones. */
void
-routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset, int running_only)
-{
+routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ const routerset_t *excludeset, int running_only)
+{ /* XXXX MOVE */
tor_assert(out);
if (!routerset || !routerset->list)
return;
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
- if (routerset_is_list(routerset)) {
+ if (routerset_is_list(routerset)) {
/* No routers are specified by type; all are given by name or digest.
* we can do a lookup in O(len(routerset)). */
SMARTLIST_FOREACH(routerset->list, const char *, name, {
- routerinfo_t *router = router_get_by_nickname(name, 1);
- if (router) {
- if (!running_only || router->is_running)
- if (!routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ const node_t *node = node_get_by_nickname(name, 1);
+ if (node) {
+ if (!running_only || node->is_running)
+ if (!routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
}
});
} else {
/* We need to iterate over the routerlist to get all the ones of the
* right kind. */
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
- if (running_only && !router->is_running)
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (running_only && !node->is_running)
continue;
- if (routerset_contains_router(routerset, router) &&
- !routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ if (routerset_contains_node(routerset, node) &&
+ !routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
});
}
}
#if 0
-/** Add to <b>target</b> every routerinfo_t from <b>source</b> except:
+/** Add to <b>target</b> every node_t from <b>source</b> except:
*
* 1) Don't add it if <b>include</b> is non-empty and the relay isn't in
* <b>include</b>; and
@@ -5607,40 +5708,40 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
* 3) If <b>running_only</b>, don't add non-running routers.
*/
void
-routersets_get_disjunction(smartlist_t *target,
+routersets_get_node_disjunction(smartlist_t *target,
const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only)
{
- SMARTLIST_FOREACH(source, routerinfo_t *, router, {
+ SMARTLIST_FOREACH(source, const node_t *, node, {
int include_result;
- if (running_only && !router->is_running)
+ if (running_only && !node->is_running)
continue;
if (!routerset_is_empty(include))
- include_result = routerset_contains_router(include, router);
+ include_result = routerset_contains_node(include, node);
else
include_result = 1;
if (include_result) {
- int exclude_result = routerset_contains_router(exclude, router);
+ int exclude_result = routerset_contains_node(exclude, node);
if (include_result >= exclude_result)
- smartlist_add(target, router);
+ smartlist_add(target, (void*)node);
}
});
}
#endif
-/** Remove every routerinfo_t from <b>lst</b> that is in <b>routerset</b>. */
+/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */
void
-routerset_subtract_routers(smartlist_t *lst, const routerset_t *routerset)
-{
+routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset)
+{ /*XXXX MOVE ? */
tor_assert(lst);
if (!routerset)
return;
- SMARTLIST_FOREACH(lst, routerinfo_t *, r, {
- if (routerset_contains_router(routerset, r)) {
+ SMARTLIST_FOREACH(lst, const node_t *, node, {
+ if (routerset_contains_node(routerset, node)) {
//log_debug(LD_DIR, "Subtracting %s",r->nickname);
- SMARTLIST_DEL_CURRENT(lst, r);
+ SMARTLIST_DEL_CURRENT(lst, node);
}
});
}
@@ -5706,18 +5807,23 @@ routerset_free(routerset_t *routerset)
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
-routerinfo_set_country(routerinfo_t *ri)
+node_set_country(node_t *node)
{
- ri->country = geoip_get_country_by_ip(ri->addr);
+ if (node->rs)
+ node->country = geoip_get_country_by_ip(node->rs->addr);
+ else if (node->ri)
+ node->country = geoip_get_country_by_ip(node->ri->addr);
+ else
+ node->country = -1;
}
/** Set the country code of all routers in the routerlist. */
void
-routerlist_refresh_countries(void)
+nodelist_refresh_countries(void) /* MOVE */
{
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
- routerinfo_set_country(ri));
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node,
+ node_set_country(node));
}
/** Determine the routers that are responsible for <b>id</b> (binary) and
@@ -5760,7 +5866,7 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
int
hid_serv_acting_as_directory(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
if (!get_options()->HidServDirectoryV2) {
@@ -5776,7 +5882,7 @@ hid_serv_acting_as_directory(void)
int
hid_serv_responsible_for_desc_id(const char *query)
{
- routerinfo_t *me;
+ const routerinfo_t *me;
routerstatus_t *last_rs;
const char *my_id, *last_id;
int result;
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index fec18705b3..cae8814333 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -11,7 +11,7 @@
#ifndef _TOR_ROUTERLIST_H
#define _TOR_ROUTERLIST_H
-int get_n_authorities(authority_type_t type);
+int get_n_authorities(dirinfo_type_t type);
int trusted_dirs_reload_certs(void);
int trusted_dirs_load_certs_from_string(const char *contents, int from_store,
int flush);
@@ -27,53 +27,50 @@ int router_reload_router_list(void);
int authority_cert_dl_looks_uncertain(const char *id_digest);
smartlist_t *router_get_trusted_dir_servers(void);
-routerstatus_t *router_pick_directory_server(authority_type_t type, int flags);
+const routerstatus_t *router_pick_directory_server(dirinfo_type_t type,
+ int flags);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
-routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags);
+const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type,
+ int flags);
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
-void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
-int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2);
int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
-void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running);
-int router_nickname_is_in_list(routerinfo_t *router, const char *list);
-routerinfo_t *routerlist_find_my_routerinfo(void);
-routerinfo_t *router_find_exact_exit_enclave(const char *address,
+int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
+const routerinfo_t *routerlist_find_my_routerinfo(void);
+const node_t *router_find_exact_exit_enclave(const char *address,
uint16_t port);
-int router_is_unreliable(routerinfo_t *router, int need_uptime,
+int node_is_unreliable(const node_t *router, int need_uptime,
int need_capacity, int need_guard);
-uint32_t router_get_advertised_bandwidth(routerinfo_t *router);
-uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
-routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
-routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
+const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule);
-routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
+const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
struct routerset_t *excludedset,
router_crn_flags_t flags);
-routerinfo_t *router_get_by_nickname(const char *nickname,
+const routerinfo_t *router_get_by_nickname(const char *nickname,
int warn_if_unnamed);
-int router_digest_version_as_new_as(const char *digest, const char *cutoff);
+int router_is_named(const routerinfo_t *router);
int router_digest_is_trusted_dir_type(const char *digest,
- authority_type_t type);
+ dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \
- router_digest_is_trusted_dir_type((d), NO_AUTHORITY)
+ router_digest_is_trusted_dir_type((d), NO_DIRINFO)
int router_addr_is_trusted_dir(uint32_t addr);
int hexdigest_to_digest(const char *hexdigest, char *digest);
-routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
-routerinfo_t *router_get_by_digest(const char *digest);
+const routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
+const routerinfo_t *router_get_by_id_digest(const char *digest);
+routerinfo_t *router_get_mutable_by_digest(const char *digest);
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
-const char *signed_descriptor_get_body(signed_descriptor_t *desc);
-const char *signed_descriptor_get_annotations(signed_descriptor_t *desc);
+const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
+const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
routerlist_t *router_get_routerlist(void);
void routerinfo_free(routerinfo_t *router);
void extrainfo_free(extrainfo_t *extrainfo);
@@ -132,63 +129,71 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
int descriptor_digests);
void routerlist_retry_directory_downloads(time_t now);
-int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime);
-int router_exit_policy_rejects_all(routerinfo_t *router);
+int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
+ int need_uptime);
+
+int router_exit_policy_rejects_all(const routerinfo_t *router);
trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
- authority_type_t type);
+ dirinfo_type_t type);
void authority_cert_free(authority_cert_t *cert);
void clear_trusted_dir_servers(void);
int any_trusted_dir_is_v1_authority(void);
void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus);
void update_router_descriptor_downloads(time_t now);
+void update_all_descriptor_downloads(time_t now);
void update_extrainfo_downloads(time_t now);
int router_have_minimum_dir_info(void);
void router_dir_info_changed(void);
const char *get_dir_info_status_string(void);
int count_loading_descriptors_progress(void);
void router_reset_descriptor_download_failures(void);
-int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2);
-int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
+int router_differences_are_cosmetic(const routerinfo_t *r1,
+ const routerinfo_t *r2);
+int routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
+ extrainfo_t *ei,
signed_descriptor_t *sd,
const char **msg);
-void routerlist_assert_ok(routerlist_t *rl);
-const char *esc_router_info(routerinfo_t *router);
+void routerlist_assert_ok(const routerlist_t *rl);
+const char *esc_router_info(const routerinfo_t *router);
void routers_sort_by_identity(smartlist_t *routers);
routerset_t *routerset_new(void);
+void routerset_refresh_countries(routerset_t *rs);
int routerset_parse(routerset_t *target, const char *s,
const char *description);
void routerset_union(routerset_t *target, const routerset_t *source);
int routerset_is_list(const routerset_t *set);
int routerset_needs_geoip(const routerset_t *set);
int routerset_is_empty(const routerset_t *set);
-int routerset_contains_router(const routerset_t *set, routerinfo_t *ri);
+int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country);
int routerset_contains_routerstatus(const routerset_t *set,
- routerstatus_t *rs);
+ const routerstatus_t *rs,
+ country_t country);
int routerset_contains_extendinfo(const routerset_t *set,
const extend_info_t *ei);
-void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset,
- int running_only);
+
+int routerset_contains_node(const routerset_t *set, const node_t *node);
+void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ const routerset_t *excludeset,
+ int running_only);
#if 0
-void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
+void routersets_get_node_disjunction(smartlist_t *target,
+ const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only);
#endif
-void routerset_subtract_routers(smartlist_t *out,
+void routerset_subtract_nodes(smartlist_t *out,
const routerset_t *routerset);
+
char *routerset_to_string(const routerset_t *routerset);
-void routerset_refresh_countries(routerset_t *target);
int routerset_equal(const routerset_t *old, const routerset_t *new);
void routerset_free(routerset_t *routerset);
-void routerinfo_set_country(routerinfo_t *ri);
-void routerlist_refresh_countries(void);
void refresh_all_country_info(void);
int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
@@ -196,5 +201,16 @@ int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
int hid_serv_acting_as_directory(void);
int hid_serv_responsible_for_desc_id(const char *id);
+void list_pending_microdesc_downloads(digestmap_t *result);
+void launch_descriptor_downloads(int purpose,
+ smartlist_t *downloadable,
+ const routerstatus_t *source,
+ time_t now);
+
+int hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_out,
+ char *nickname_out);
+
#endif
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index aed4fd131e..4ea7b964cf 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -70,7 +70,6 @@ typedef enum {
K_V,
K_W,
K_M,
- K_EVENTDNS,
K_EXTRA_INFO,
K_EXTRA_INFO_DIGEST,
K_CACHES_EXTRA_INFO,
@@ -287,7 +286,6 @@ static token_rule_t routerdesc_token_table[] = {
T01("family", K_FAMILY, ARGS, NO_OBJ ),
T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
- T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
@@ -572,7 +570,6 @@ static int check_signature_token(const char *digest,
int flags,
const char *doctype);
static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
-static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
#undef DEBUG_AREA_ALLOC
@@ -1358,7 +1355,6 @@ router_parse_entry_from_string(const char *s, const char *end,
tor_assert(tok->n_args >= 5);
router = tor_malloc_zero(sizeof(routerinfo_t));
- router->country = -1;
router->cache_info.routerlist_index = -1;
router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
router->cache_info.signed_descriptor_len = end-s;
@@ -1504,13 +1500,6 @@ router_parse_entry_from_string(const char *s, const char *end,
router->contact_info = tor_strdup(tok->args[0]);
}
- if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
- router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
- } else if (router->platform) {
- if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
- router->has_old_dnsworkers = 1;
- }
-
if (find_opt_by_keyword(tokens, K_REJECT6) ||
find_opt_by_keyword(tokens, K_ACCEPT6)) {
log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
@@ -1575,8 +1564,6 @@ router_parse_entry_from_string(const char *s, const char *end,
"router descriptor") < 0)
goto err;
- routerinfo_set_country(router);
-
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
@@ -1824,9 +1811,9 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
struct in_addr in;
char *address = NULL;
tor_assert(tok->n_args);
- /* XXX023 use tor_addr_port_parse() below instead. -RD */
- if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL,
- &cert->dir_port)<0 ||
+ /* XXX023 use some tor_addr parse function below instead. -RD */
+ if (tor_addr_port_split(LOG_WARN, tok->args[0], &address,
+ &cert->dir_port) < 0 ||
tor_inet_aton(address, &in) == 0) {
log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
tor_free(address);
@@ -1976,6 +1963,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
if (!consensus_method)
flav = FLAV_NS;
+ tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
eos = find_start_of_next_routerstatus(*s);
@@ -1988,15 +1976,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
goto err;
}
tok = find_by_keyword(tokens, K_R);
- tor_assert(tok->n_args >= 7);
+ tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
if (flav == FLAV_NS) {
if (tok->n_args < 8) {
log_warn(LD_DIR, "Too few arguments to r");
goto err;
}
- } else {
- offset = -1;
+ } else if (flav == FLAV_MICRODESC) {
+ offset = -1; /* There is no identity digest */
}
+
if (vote_rs) {
rs = &vote_rs->status;
} else {
@@ -2070,7 +2059,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
else if (!strcmp(tok->args[i], "Fast"))
rs->is_fast = 1;
else if (!strcmp(tok->args[i], "Running"))
- rs->is_running = 1;
+ rs->is_flagged_running = 1;
else if (!strcmp(tok->args[i], "Named"))
rs->is_named = 1;
else if (!strcmp(tok->args[i], "Valid"))
@@ -2101,6 +2090,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_supports_begindir = 1;
rs->version_supports_extrainfo_upload = 1;
rs->version_supports_conditional_consensus = 1;
+ rs->version_supports_microdesc_cache = 1;
+ rs->version_supports_optimistic_data = 1;
} else {
rs->version_supports_begindir =
tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
@@ -2110,6 +2101,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
rs->version_supports_conditional_consensus =
tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
+ /* XXXX023 NM microdescs: 0.2.3.1-alpha isn't widely used yet, but
+ * not all 0.2.3.0-alpha "versions" actually support microdesc cacheing
+ * right. There's a compromise here. Since this is 5 May, let's
+ * err on the side of having some possible caches to use. Once more
+ * caches are running 0.2.3.1-alpha, we can bump this version number.
+ */
+ rs->version_supports_microdesc_cache =
+ tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha");
+ rs->version_supports_optimistic_data =
+ tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);
@@ -2172,6 +2173,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
vote_rs->microdesc = line;
}
} SMARTLIST_FOREACH_END(t);
+ } else if (flav == FLAV_MICRODESC) {
+ tok = find_opt_by_keyword(tokens, K_M);
+ if (tok) {
+ tor_assert(tok->n_args);
+ if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
+ log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
+ escaped(tok->args[0]));
+ goto err;
+ }
+ }
}
if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
@@ -3503,10 +3514,10 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
siglist = detached_get_signatures(sigs, flavor);
is_duplicate = 0;
- SMARTLIST_FOREACH(siglist, document_signature_t *, s, {
- if (s->alg == alg &&
- tor_memeq(id_digest, s->identity_digest, DIGEST_LEN) &&
- tor_memeq(sk_digest, s->signing_key_digest, DIGEST_LEN)) {
+ SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, {
+ if (dsig->alg == alg &&
+ tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) &&
+ tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) {
is_duplicate = 1;
}
});
@@ -4359,7 +4370,7 @@ microdescs_parse_from_string(const char *s, const char *eos,
}
if ((tok = find_opt_by_keyword(tokens, K_P))) {
- md->exitsummary = tor_strdup(tok->args[0]);
+ md->exit_policy = parse_short_policy(tok->args[0]);
}
crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
@@ -4556,7 +4567,7 @@ tor_version_compare(tor_version_t *a, tor_version_t *b)
/** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
*/
-static int
+int
tor_version_same_series(tor_version_t *a, tor_version_t *b)
{
tor_assert(a);
@@ -4875,6 +4886,11 @@ rend_decrypt_introduction_points(char **ipos_decrypted,
crypto_cipher_env_t *cipher;
char *dec;
int declen;
+ if (ipos_encrypted_size < CIPHER_IV_LEN + 2) {
+ log_warn(LD_REND, "Size of encrypted introduction points is too "
+ "small.");
+ return -1;
+ }
dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
cipher = crypto_create_init_cipher(descriptor_cookie, 0);
declen = crypto_cipher_decrypt_with_iv(cipher, dec,
@@ -4970,7 +4986,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
info->identity_digest, DIGEST_LEN);
/* Parse IP address. */
tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
- if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
+ if (tor_addr_parse(&info->addr, tok->args[0])<0) {
log_warn(LD_REND, "Could not parse introduction point address.");
rend_intro_point_free(intro);
goto err;
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index 8b8cde25f6..527de5dc8b 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -47,6 +47,7 @@ version_status_t tor_version_is_obsolete(const char *myversion,
int tor_version_parse(const char *s, tor_version_t *out);
int tor_version_as_new_as(const char *platform, const char *cutoff);
int tor_version_compare(tor_version_t *a, tor_version_t *b);
+int tor_version_same_series(tor_version_t *a, tor_version_t *b);
void sort_version_list(smartlist_t *lst, int remove_duplicates);
void assert_addr_policy_ok(smartlist_t *t);
void dump_distinct_digest_count(int severity);
diff --git a/src/or/status.c b/src/or/status.c
new file mode 100644
index 0000000000..3e4cb779a3
--- /dev/null
+++ b/src/or/status.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file status.c
+ * \brief Keep status information and log the heartbeat messages.
+ **/
+
+#include "or.h"
+#include "config.h"
+#include "status.h"
+#include "nodelist.h"
+#include "router.h"
+#include "circuitlist.h"
+#include "main.h"
+
+/** Return the total number of circuits. */
+static int
+count_circuits(void)
+{
+ circuit_t *circ;
+ int nr=0;
+
+ for (circ = _circuit_get_global_list(); circ; circ = circ->next)
+ nr++;
+
+ return nr;
+}
+
+/** Take seconds <b>secs</b> and return a newly allocated human-readable
+ * uptime string */
+static char *
+secs_to_uptime(long secs)
+{
+ long int days = secs / 86400;
+ int hours = (int)((secs - (days * 86400)) / 3600);
+ int minutes = (int)((secs - (days * 86400) - (hours * 3600)) / 60);
+ char *uptime_string = NULL;
+
+ switch (days) {
+ case 0:
+ tor_asprintf(&uptime_string, "%d:%02d hours", hours, minutes);
+ break;
+ case 1:
+ tor_asprintf(&uptime_string, "%ld day %d:%02d hours",
+ days, hours, minutes);
+ break;
+ default:
+ tor_asprintf(&uptime_string, "%ld days %d:%02d hours",
+ days, hours, minutes);
+ break;
+ }
+
+ return uptime_string;
+}
+
+/** Take <b>bytes</b> and returns a newly allocated human-readable usage
+ * string. */
+static char *
+bytes_to_usage(uint64_t bytes)
+{
+ char *bw_string = NULL;
+
+ if (bytes < (1<<20)) { /* Less than a megabyte. */
+ tor_asprintf(&bw_string, U64_FORMAT" kB", U64_PRINTF_ARG(bytes>>10));
+ } else if (bytes < (1<<30)) { /* Megabytes. Let's add some precision. */
+ double bw = U64_TO_DBL(bytes);
+ tor_asprintf(&bw_string, "%.2f MB", bw/(1<<20));
+ } else { /* Gigabytes. */
+ double bw = U64_TO_DBL(bytes);
+ tor_asprintf(&bw_string, "%.2f GB", bw/(1<<30));
+ }
+
+ return bw_string;
+}
+
+/** Log a "heartbeat" message describing Tor's status and history so that the
+ * user can know that there is indeed a running Tor. Return 0 on success and
+ * -1 on failure. */
+int
+log_heartbeat(time_t now)
+{
+ char *bw_sent = NULL;
+ char *bw_rcvd = NULL;
+ char *uptime = NULL;
+ const routerinfo_t *me;
+
+ const or_options_t *options = get_options();
+ (void)now;
+
+ if (public_server_mode(options)) {
+ /* Let's check if we are in the current cached consensus. */
+ if (!(me = router_get_my_routerinfo()))
+ return -1; /* Something stinks, we won't even attempt this. */
+ else
+ if (!node_get_by_id(me->cache_info.identity_digest))
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: It seems like we are not "
+ "in the cached consensus.");
+ }
+
+ uptime = secs_to_uptime(get_uptime());
+ bw_rcvd = bytes_to_usage(get_bytes_read());
+ bw_sent = bytes_to_usage(get_bytes_written());
+
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d "
+ "circuits open. I've sent %s and received %s.",
+ uptime, count_circuits(),bw_sent,bw_rcvd);
+
+ tor_free(uptime);
+ tor_free(bw_sent);
+ tor_free(bw_rcvd);
+
+ return 0;
+}
+
diff --git a/src/or/status.h b/src/or/status.h
new file mode 100644
index 0000000000..ac726a1d2d
--- /dev/null
+++ b/src/or/status.h
@@ -0,0 +1,10 @@
+/* Copyright (c) 2010, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef _TOR_STATUS_H
+#define _TOR_STATUS_H
+
+int log_heartbeat(time_t now);
+
+#endif
+
diff --git a/src/or/transports.c b/src/or/transports.c
new file mode 100644
index 0000000000..10155c4475
--- /dev/null
+++ b/src/or/transports.c
@@ -0,0 +1,1248 @@
+/* Copyright (c) 2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file transports.c
+ * \brief Pluggable Transports related code.
+ **/
+
+#define PT_PRIVATE
+#include "or.h"
+#include "config.h"
+#include "circuitbuild.h"
+#include "transports.h"
+#include "util.h"
+
+#ifdef MS_WINDOWS
+static void set_managed_proxy_environment(LPVOID *envp,
+ const managed_proxy_t *mp);
+#else
+static int set_managed_proxy_environment(char ***envp,
+ const managed_proxy_t *mp);
+#endif
+
+static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
+
+static void managed_proxy_destroy(managed_proxy_t *mp,
+ int also_terminate_process);
+
+static void handle_finished_proxy(managed_proxy_t *mp);
+static void configure_proxy(managed_proxy_t *mp);
+
+static void parse_method_error(const char *line, int is_server_method);
+#define parse_server_method_error(l) parse_method_error(l, 1)
+#define parse_client_method_error(l) parse_method_error(l, 0)
+
+static INLINE void free_execve_args(char **arg);
+
+/** Managed proxy protocol strings */
+#define PROTO_ENV_ERROR "ENV-ERROR"
+#define PROTO_NEG_SUCCESS "VERSION"
+#define PROTO_NEG_FAIL "VERSION-ERROR no-version"
+#define PROTO_CMETHOD "CMETHOD"
+#define PROTO_SMETHOD "SMETHOD"
+#define PROTO_CMETHOD_ERROR "CMETHOD-ERROR"
+#define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
+#define PROTO_CMETHODS_DONE "CMETHODS DONE"
+#define PROTO_SMETHODS_DONE "SMETHODS DONE"
+
+/* The smallest valid managed proxy protocol line that can
+ appear. It's the size of "VERSION 1" */
+#define SMALLEST_MANAGED_LINE_SIZE 9
+
+/** Number of environment variables for managed proxy clients/servers. */
+#define ENVIRON_SIZE_CLIENT 5
+#define ENVIRON_SIZE_SERVER 8
+
+/** The first and only supported - at the moment - configuration
+ protocol version. */
+#define PROTO_VERSION_ONE 1
+
+/** List of unconfigured managed proxies. */
+static smartlist_t *managed_proxy_list = NULL;
+/** Number of still unconfigured proxies. */
+static int unconfigured_proxies_n = 0;
+
+/** "The main idea is:"
+
+ Each managed proxy is represented by a 'managed_proxy_t'.
+ Each managed proxy can support multiple transports.
+ Each managed proxy gets configured through a multistep process.
+
+ 'managed_proxy_list' contains all the managed proxies this tor
+ instance is supporting.
+ In the 'managed_proxy_list' there are 'unconfigured_proxies_n'
+ managed proxies that are still unconfigured.
+
+ In every run_scheduled_event() tick, we attempt to launch and then
+ configure the unconfiged managed proxies, using the configuration
+ protocol defined in the 180_pluggable_transport.txt proposal. A
+ managed proxy might need several ticks to get fully configured.
+
+ When a managed proxy is fully configured, we register all its
+ transports to the circuitbuild.c subsystem. At that point the
+ transports are owned by the circuitbuild.c subsystem.
+
+ When a managed proxy fails to follow the 180 configuration
+ protocol, it gets marked as broken and gets destroyed.
+
+ "In a little more technical detail:"
+
+ While we are serially parsing torrc, we store all the transports
+ that a proxy should spawn in its 'transports_to_launch' element.
+
+ When we finish reading the torrc, we spawn the managed proxy and
+ expect {S,C}METHOD lines from its output. We add transports
+ described by METHOD lines to its 'transports' element, as
+ 'transport_t' structs.
+
+ When the managed proxy stops spitting METHOD lines (signified by a
+ '{S,C}METHODS DONE' message) we register all the transports
+ collected to the circuitbuild.c subsystem. At this point, the
+ 'transport_t's can be transformed into dangling pointers at any
+ point by the circuitbuild.c subsystem, and so we replace all
+ 'transport_t's with strings describing the transport names. We
+ can still go from a transport name to a 'transport_t' using the
+ fact that transport names uniquely identify 'transport_t's.
+
+ "In even more technical detail I shall describe what happens when
+ the SIGHUP bell tolls:"
+
+ We immediately destroy all unconfigured proxies (We shouldn't have
+ unconfigured proxies in the first place, except when SIGHUP rings
+ immediately after tor is launched.).
+
+ We mark all managed proxies and transports to signify that they
+ must be removed if they don't contribute by the new torrc
+ (marked_for_removal).
+ We also mark all managed proxies to signify that they might need
+ to be restarted so that they end up supporting all the transports
+ the new torrc wants them to support (got_hup).
+ We also clear their 'transports_to_launch' list so that we can put
+ there the transports we need to launch according to the new torrc.
+
+ We then start parsing torrc again.
+
+ Everytime we encounter a transport line using a known pre-SIGHUP
+ managed proxy, we cleanse that proxy from the removal mark.
+
+ We also mark it as unconfigured so that on the next scheduled
+ events tick, we investigate whether we need to restart the proxy
+ so that it also spawns the new transports.
+ If the post-SIGHUP 'transports_to_launch' list is identical to the
+ pre-SIGHUP one, it means that no changes were introduced to this
+ proxy during the SIGHUP and no restart has to take place.
+
+ During the post-SIGHUP torrc parsing, we unmark all transports
+ spawned by managed proxies that we find in our torrc.
+ We do that so that if we don't need to restart a managed proxy, we
+ can continue using its old transports normally.
+ If we end up restarting the proxy, we destroy and unregister all
+ old transports from the circuitbuild.c subsystem.
+*/
+
+/** Return true if there are still unconfigured managed proxies. */
+int
+pt_proxies_configuration_pending(void)
+{
+ return !! unconfigured_proxies_n;
+}
+
+/** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
+static int
+managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
+{
+ char **tmp1=proxy_argv;
+ char **tmp2=mp->argv;
+
+ tor_assert(tmp1);
+ tor_assert(tmp2);
+
+ while (*tmp1 && *tmp2) {
+ if (strcmp(*tmp1++, *tmp2++))
+ return 0;
+ }
+
+ if (!*tmp1 && !*tmp2)
+ return 1;
+
+ return 0;
+}
+
+/** Return a managed proxy with the same argv as <b>proxy_argv</b>.
+ * If no such managed proxy exists, return NULL. */
+static managed_proxy_t *
+get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server)
+{
+ if (!managed_proxy_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ if (managed_proxy_has_argv(mp, proxy_argv) &&
+ mp->is_server == is_server)
+ return mp;
+ } SMARTLIST_FOREACH_END(mp);
+
+ return NULL;
+}
+
+/** Add <b>transport</b> to managed proxy <b>mp</b>. */
+static void
+add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
+{
+ tor_assert(mp->transports_to_launch);
+ if (!smartlist_string_isin(mp->transports_to_launch, transport))
+ smartlist_add(mp->transports_to_launch, tor_strdup(transport));
+}
+
+/** Called when a SIGHUP occurs. Returns true if managed proxy
+ * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
+ * torrc. */
+static int
+proxy_needs_restart(const managed_proxy_t *mp)
+{
+ /* mp->transport_to_launch is populated with the names of the
+ transports that must be launched *after* the SIGHUP.
+ mp->transports is populated with the names of the transports that
+ were launched *before* the SIGHUP.
+
+ If the two lists contain the same strings, we don't need to
+ restart the proxy, since it already does what we want. */
+
+ tor_assert(smartlist_len(mp->transports_to_launch) > 0);
+ tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+ if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
+ goto needs_restart;
+
+ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
+ if (!smartlist_string_isin(mp->transports, t_t_l))
+ goto needs_restart;
+
+ } SMARTLIST_FOREACH_END(t_t_l);
+
+ return 0;
+
+ needs_restart:
+ return 1;
+}
+
+/** Managed proxy <b>mp</b> must be restarted. Do all the necessary
+ * preparations and then flag its state so that it will be relaunched
+ * in the next tick. */
+static void
+proxy_prepare_for_restart(managed_proxy_t *mp)
+{
+ transport_t *t_tmp = NULL;
+
+ tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+ /* destroy the process handle and terminate the process. */
+ tor_process_handle_destroy(mp->process_handle, 1);
+ mp->process_handle = NULL;
+
+ /* destroy all its old transports. we no longer use them. */
+ SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) {
+ t_tmp = transport_get_by_name(t_name);
+ if (t_tmp)
+ t_tmp->marked_for_removal = 1;
+ } SMARTLIST_FOREACH_END(t_name);
+ sweep_transport_list();
+
+ /* free the transport names in mp->transports */
+ SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+ smartlist_clear(mp->transports);
+
+ /* flag it as an infant proxy so that it gets launched on next tick */
+ mp->conf_state = PT_PROTO_INFANT;
+}
+
+/** Launch managed proxy <b>mp</b>. */
+static int
+launch_managed_proxy(managed_proxy_t *mp)
+{
+ int retval;
+
+#ifdef MS_WINDOWS
+
+ LPVOID envp=NULL;
+
+ set_managed_proxy_environment(&envp, mp);
+ tor_assert(envp);
+
+ /* Passing NULL as lpApplicationName makes Windows search for the .exe */
+ retval = tor_spawn_background(NULL, (const char **)mp->argv, envp,
+ &mp->process_handle);
+
+ tor_free(envp);
+
+#else
+
+ char **envp=NULL;
+
+ /* prepare the environment variables for the managed proxy */
+ if (set_managed_proxy_environment(&envp, mp) < 0) {
+ log_warn(LD_GENERAL, "Could not setup the environment of "
+ "the managed proxy at '%s'.", mp->argv[0]);
+ free_execve_args(envp);
+ return -1;
+ }
+
+ retval = tor_spawn_background(mp->argv[0], (const char **)mp->argv,
+ (const char **)envp, &mp->process_handle);
+
+ /* free the memory allocated by set_managed_proxy_environment(). */
+ free_execve_args(envp);
+
+#endif
+
+ if (retval == PROCESS_STATUS_ERROR) {
+ log_warn(LD_GENERAL, "Managed proxy at '%s' failed at launch.",
+ mp->argv[0]);
+ return -1;
+ }
+
+ log_info(LD_CONFIG, "Managed proxy at '%s' has spawned with PID '%d'.",
+ mp->argv[0], tor_process_get_pid(mp->process_handle));
+
+ mp->conf_state = PT_PROTO_LAUNCHED;
+
+ return 0;
+}
+
+/** Check if any of the managed proxies we are currently trying to
+ * configure have anything new to say. This is called from
+ * run_scheduled_events(). */
+void
+pt_configure_remaining_proxies(void)
+{
+ log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
+ unconfigured_proxies_n);
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ tor_assert(mp->conf_state != PT_PROTO_BROKEN ||
+ mp->conf_state != PT_PROTO_FAILED_LAUNCH);
+
+ if (mp->got_hup) {
+ mp->got_hup = 0;
+
+ /* This proxy is marked by a SIGHUP. Check whether we need to
+ restart it. */
+ if (proxy_needs_restart(mp)) {
+ log_info(LD_GENERAL, "Preparing managed proxy for restart.");
+ proxy_prepare_for_restart(mp);
+ continue;
+ } else { /* it doesn't need to be restarted. */
+ log_info(LD_GENERAL, "Nothing changed for managed proxy after HUP: "
+ "not restarting.");
+ unconfigured_proxies_n--;
+ tor_assert(unconfigured_proxies_n >= 0);
+ }
+
+ continue;
+ }
+
+ /* If the proxy is not fully configured, try to configure it
+ futher. */
+ if (!proxy_configuration_finished(mp))
+ configure_proxy(mp);
+
+ } SMARTLIST_FOREACH_END(mp);
+}
+
+#ifdef MS_WINDOWS
+
+/** Attempt to continue configuring managed proxy <b>mp</b>. */
+static void
+configure_proxy(managed_proxy_t *mp)
+{
+ int pos;
+ char stdout_buf[200];
+ smartlist_t *lines = NULL;
+
+ /* if we haven't launched the proxy yet, do it now */
+ if (mp->conf_state == PT_PROTO_INFANT) {
+ if (launch_managed_proxy(mp) < 0) { /* launch fail */
+ mp->conf_state = PT_PROTO_FAILED_LAUNCH;
+ handle_finished_proxy(mp);
+ }
+ return;
+ }
+
+ tor_assert(mp->conf_state != PT_PROTO_INFANT);
+ tor_assert(mp->process_handle);
+
+ pos = tor_read_all_handle(tor_process_get_stdout_pipe(mp->process_handle),
+ stdout_buf, sizeof(stdout_buf) - 1, NULL);
+ if (pos < 0) {
+ log_notice(LD_GENERAL, "Failed to read data from managed proxy");
+ mp->conf_state = PT_PROTO_BROKEN;
+ goto done;
+ }
+
+ if (pos == 0) /* proxy has nothing interesting to say. */
+ return;
+
+ /* End with a null even if there isn't a \r\n at the end */
+ /* TODO: What if this is a partial line? */
+ stdout_buf[pos] = '\0';
+
+ /* Split up the buffer */
+ lines = smartlist_create();
+ tor_split_lines(lines, stdout_buf, pos);
+
+ /* Handle lines. */
+ SMARTLIST_FOREACH_BEGIN(lines, const char *, line) {
+ handle_proxy_line(line, mp);
+ if (proxy_configuration_finished(mp))
+ goto done;
+ } SMARTLIST_FOREACH_END(line);
+
+ done:
+ /* if the proxy finished configuring, exit the loop. */
+ if (proxy_configuration_finished(mp))
+ handle_finished_proxy(mp);
+
+ if (lines)
+ smartlist_free(lines);
+}
+
+#else /* MS_WINDOWS */
+
+/** Attempt to continue configuring managed proxy <b>mp</b>. */
+static void
+configure_proxy(managed_proxy_t *mp)
+{
+ enum stream_status r;
+ char stdout_buf[200];
+
+ /* if we haven't launched the proxy yet, do it now */
+ if (mp->conf_state == PT_PROTO_INFANT) {
+ if (launch_managed_proxy(mp) < 0) { /* launch fail */
+ mp->conf_state = PT_PROTO_FAILED_LAUNCH;
+ handle_finished_proxy(mp);
+ }
+ return;
+ }
+
+ tor_assert(mp->conf_state != PT_PROTO_INFANT);
+ tor_assert(mp->process_handle);
+
+ while (1) {
+ r = get_string_from_pipe(tor_process_get_stdout_pipe(mp->process_handle),
+ stdout_buf, sizeof(stdout_buf) - 1);
+
+ if (r == IO_STREAM_OKAY) { /* got a line; handle it! */
+ handle_proxy_line((const char *)stdout_buf, mp);
+ } else if (r == IO_STREAM_EAGAIN) { /* check back later */
+ return;
+ } else if (r == IO_STREAM_CLOSED || r == IO_STREAM_TERM) { /* snap! */
+ log_notice(LD_GENERAL, "Managed proxy stream closed. "
+ "Most probably application stopped running");
+ mp->conf_state = PT_PROTO_BROKEN;
+ } else { /* unknown stream status */
+ log_notice(LD_GENERAL, "Unknown stream status while configuring proxy.");
+ }
+
+ /* if the proxy finished configuring, exit the loop. */
+ if (proxy_configuration_finished(mp)) {
+ handle_finished_proxy(mp);
+ return;
+ }
+ }
+}
+
+#endif /* MS_WINDOWS */
+
+/** Register server managed proxy <b>mp</b> transports to state */
+static void
+register_server_proxy(managed_proxy_t *mp)
+{
+ /* After we register this proxy's transports, we switch its
+ mp->transports to a list containing strings of its transport
+ names. (See transports.h) */
+ smartlist_t *sm_tmp = smartlist_create();
+
+ tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+ SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
+ save_transport_to_state(t->name, &t->addr, t->port);
+ /* LOG_WARN so that the bridge operator can easily find the
+ transport's port in the log file and send it to the users. */
+ log_warn(LD_GENERAL, "Registered server transport '%s' at '%s:%d'",
+ t->name, fmt_addr(&t->addr), (int)t->port);
+ smartlist_add(sm_tmp, tor_strdup(t->name));
+ } SMARTLIST_FOREACH_END(t);
+
+ /* Since server proxies don't register their transports in the
+ circuitbuild.c subsystem, it's our duty to free them when we
+ switch mp->transports to strings. */
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+ smartlist_free(mp->transports);
+
+ mp->transports = sm_tmp;
+}
+
+/** Register all the transports supported by client managed proxy
+ * <b>mp</b> to the bridge subsystem. */
+static void
+register_client_proxy(managed_proxy_t *mp)
+{
+ int r;
+ /* After we register this proxy's transports, we switch its
+ mp->transports to a list containing strings of its transport
+ names. (See transports.h) */
+ smartlist_t *sm_tmp = smartlist_create();
+
+ tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+ SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
+ r = transport_add(t);
+ switch (r) {
+ case -1:
+ log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
+ transport_free(t);
+ break;
+ case 0:
+ log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
+ smartlist_add(sm_tmp, tor_strdup(t->name));
+ break;
+ case 1:
+ log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
+ smartlist_add(sm_tmp, tor_strdup(t->name));
+ transport_free(t);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(t);
+
+ smartlist_free(mp->transports);
+ mp->transports = sm_tmp;
+}
+
+/** Register the transports of managed proxy <b>mp</b>. */
+static INLINE void
+register_proxy(managed_proxy_t *mp)
+{
+ if (mp->is_server)
+ register_server_proxy(mp);
+ else
+ register_client_proxy(mp);
+}
+
+/** Free memory allocated by managed proxy <b>mp</b>. */
+static void
+managed_proxy_destroy(managed_proxy_t *mp,
+ int also_terminate_process)
+{
+ if (mp->conf_state != PT_PROTO_COMPLETED)
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+ else
+ SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+
+ /* free the transports smartlist */
+ smartlist_free(mp->transports);
+
+ /* free the transports_to_launch smartlist */
+ SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
+ smartlist_free(mp->transports_to_launch);
+
+ /* remove it from the list of managed proxies */
+ smartlist_remove(managed_proxy_list, mp);
+
+ /* free the argv */
+ free_execve_args(mp->argv);
+
+ tor_process_handle_destroy(mp->process_handle, also_terminate_process);
+ mp->process_handle = NULL;
+
+ tor_free(mp);
+}
+
+/** Handle a configured or broken managed proxy <b>mp</b>. */
+static void
+handle_finished_proxy(managed_proxy_t *mp)
+{
+ switch (mp->conf_state) {
+ case PT_PROTO_BROKEN: /* if broken: */
+ managed_proxy_destroy(mp, 1); /* annihilate it. */
+ break;
+ case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
+ managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
+ break;
+ case PT_PROTO_CONFIGURED: /* if configured correctly: */
+ register_proxy(mp); /* register its transports */
+ mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
+ break;
+ case PT_PROTO_INFANT:
+ case PT_PROTO_LAUNCHED:
+ case PT_PROTO_ACCEPTING_METHODS:
+ case PT_PROTO_COMPLETED:
+ default:
+ log_warn(LD_CONFIG, "Unexpected managed proxy state in "
+ "handle_finished_proxy().");
+ tor_assert(0);
+ }
+
+ unconfigured_proxies_n--;
+ tor_assert(unconfigured_proxies_n >= 0);
+}
+
+/** Return true if the configuration of the managed proxy <b>mp</b> is
+ finished. */
+static INLINE int
+proxy_configuration_finished(const managed_proxy_t *mp)
+{
+ return (mp->conf_state == PT_PROTO_CONFIGURED ||
+ mp->conf_state == PT_PROTO_BROKEN ||
+ mp->conf_state == PT_PROTO_FAILED_LAUNCH);
+}
+
+/** This function is called when a proxy sends an {S,C}METHODS DONE message. */
+static void
+handle_methods_done(const managed_proxy_t *mp)
+{
+ tor_assert(mp->transports);
+
+ if (smartlist_len(mp->transports) == 0)
+ log_notice(LD_GENERAL, "Proxy was spawned successfully, "
+ "but it didn't laucn any pluggable transport listeners!");
+
+ log_info(LD_CONFIG, "%s managed proxy configuration completed!",
+ mp->is_server ? "Server" : "Client");
+}
+
+/** Handle a configuration protocol <b>line</b> received from a
+ * managed proxy <b>mp</b>. */
+void
+handle_proxy_line(const char *line, managed_proxy_t *mp)
+{
+ log_debug(LD_GENERAL, "Got a line from managed proxy: %s", line);
+
+ if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) {
+ log_warn(LD_GENERAL, "Managed proxy configuration line is too small. "
+ "Discarding");
+ goto err;
+ }
+
+ if (!strcmpstart(line, PROTO_ENV_ERROR)) {
+ if (mp->conf_state != PT_PROTO_LAUNCHED)
+ goto err;
+
+ parse_env_error(line);
+ goto err;
+ } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
+ if (mp->conf_state != PT_PROTO_LAUNCHED)
+ goto err;
+
+ log_warn(LD_CONFIG, "Managed proxy could not pick a "
+ "configuration protocol version.");
+ goto err;
+ } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
+ if (mp->conf_state != PT_PROTO_LAUNCHED)
+ goto err;
+
+ if (parse_version(line,mp) < 0)
+ goto err;
+
+ tor_assert(mp->conf_protocol != 0);
+ mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
+ return;
+ } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ handle_methods_done(mp);
+
+ mp->conf_state = PT_PROTO_CONFIGURED;
+ return;
+ } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ handle_methods_done(mp);
+
+ mp->conf_state = PT_PROTO_CONFIGURED;
+ return;
+ } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ parse_client_method_error(line);
+ goto err;
+ } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ parse_server_method_error(line);
+ goto err;
+ } else if (!strcmpstart(line, PROTO_CMETHOD)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ if (parse_cmethod_line(line, mp) < 0)
+ goto err;
+
+ return;
+ } else if (!strcmpstart(line, PROTO_SMETHOD)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ if (parse_smethod_line(line, mp) < 0)
+ goto err;
+
+ return;
+ } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) {
+ log_warn(LD_GENERAL, "Could not launch managed proxy executable!");
+ mp->conf_state = PT_PROTO_FAILED_LAUNCH;
+ return;
+ }
+
+ log_warn(LD_CONFIG, "Unknown line received by managed proxy. (%s)", line);
+
+ err:
+ mp->conf_state = PT_PROTO_BROKEN;
+ log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
+ " and will be destroyed.", mp->argv ? mp->argv[0] : "");
+}
+
+/** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
+void
+parse_env_error(const char *line)
+{
+ /* (Length of the protocol string) plus (a space) and (the first char of
+ the error message) */
+ if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
+ log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
+ "message.", PROTO_ENV_ERROR);
+
+ log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
+ "pluggable transport environment variables. (%s)",
+ line+strlen(PROTO_ENV_ERROR)+1);
+}
+
+/** Handles a VERSION <b>line</b>. Updates the configuration protocol
+ * version in <b>mp</b>. */
+int
+parse_version(const char *line, managed_proxy_t *mp)
+{
+ if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
+ log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
+ PROTO_NEG_SUCCESS);
+ return -1;
+ }
+
+ if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
+ log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
+ "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
+ return -1;
+ }
+
+ mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
+ return 0;
+}
+
+/** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
+ * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
+ * otherwise it is a CMETHOD-ERROR. */
+static void
+parse_method_error(const char *line, int is_server)
+{
+ const char* error = is_server ?
+ PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
+
+ /* (Length of the protocol string) plus (a space) and (the first char of
+ the error message) */
+ if (strlen(line) < (strlen(error) + 2))
+ log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
+ "message.", error);
+
+ log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
+ is_server ? "Server" : "Client",
+ line+strlen(error)+1);
+}
+
+/** Parses an SMETHOD <b>line</b> and if well-formed it registers the
+ * new transport in <b>mp</b>. */
+int
+parse_smethod_line(const char *line, managed_proxy_t *mp)
+{
+ int r;
+ smartlist_t *items = NULL;
+
+ char *method_name=NULL;
+
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ transport_t *transport=NULL;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+ if (smartlist_len(items) < 3) {
+ log_warn(LD_CONFIG, "Server managed proxy sent us a SMETHOD line "
+ "with too few arguments.");
+ goto err;
+ }
+
+ tor_assert(!strcmp(smartlist_get(items,0),PROTO_SMETHOD));
+
+ method_name = smartlist_get(items,1);
+ if (!string_is_C_identifier(method_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ method_name);
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 2);
+ if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ transport = transport_create(&addr, port, method_name, PROXY_NONE);
+ if (!transport)
+ goto err;
+
+ smartlist_add(mp->transports, transport);
+
+ /* For now, notify the user so that he knows where the server
+ transport is listening. */
+ log_info(LD_CONFIG, "Server transport %s at %s:%d.",
+ method_name, fmt_addr(&addr), (int)port);
+
+ r=0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ return r;
+}
+
+/** Parses a CMETHOD <b>line</b>, and if well-formed it registers
+ * the new transport in <b>mp</b>. */
+int
+parse_cmethod_line(const char *line, managed_proxy_t *mp)
+{
+ int r;
+ smartlist_t *items = NULL;
+
+ char *method_name=NULL;
+
+ char *socks_ver_str=NULL;
+ int socks_ver=PROXY_NONE;
+
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ transport_t *transport=NULL;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+ if (smartlist_len(items) < 4) {
+ log_warn(LD_CONFIG, "Client managed proxy sent us a CMETHOD line "
+ "with too few arguments.");
+ goto err;
+ }
+
+ tor_assert(!strcmp(smartlist_get(items,0),PROTO_CMETHOD));
+
+ method_name = smartlist_get(items,1);
+ if (!string_is_C_identifier(method_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ method_name);
+ goto err;
+ }
+
+ socks_ver_str = smartlist_get(items,2);
+
+ if (!strcmp(socks_ver_str,"socks4")) {
+ socks_ver = PROXY_SOCKS4;
+ } else if (!strcmp(socks_ver_str,"socks5")) {
+ socks_ver = PROXY_SOCKS5;
+ } else {
+ log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
+ "we don't recognize. (%s)", socks_ver_str);
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 3);
+ if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ transport = transport_create(&addr, port, method_name, socks_ver);
+ if (!transport)
+ goto err;
+
+ smartlist_add(mp->transports, transport);
+
+ log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
+ "Attached to managed proxy.",
+ method_name, fmt_addr(&addr), (int)port, socks_ver);
+
+ r=0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ return r;
+}
+
+/** Return a string containing the address:port that <b>transport</b>
+ * should use. It's the responsibility of the caller to free() the
+ * received string. */
+static char *
+get_bindaddr_for_proxy(const managed_proxy_t *mp)
+{
+ char *bindaddr = NULL;
+ smartlist_t *string_tmp = smartlist_create();
+
+ tor_assert(mp->is_server);
+
+ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
+ tor_asprintf(&bindaddr, "%s-%s", t, get_bindaddr_for_transport(t));
+ smartlist_add(string_tmp, bindaddr);
+ } SMARTLIST_FOREACH_END(t);
+
+ bindaddr = smartlist_join_strings(string_tmp, ",", 0, NULL);
+
+ SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
+ smartlist_free(string_tmp);
+
+ return bindaddr;
+}
+
+#ifdef MS_WINDOWS
+
+/** Prepare the environment <b>envp</b> of managed proxy <b>mp</b>.
+ * <b>envp</b> is allocated on the heap and should be freed by the
+ * caller after its use. */
+static void
+set_managed_proxy_environment(LPVOID *envp, const managed_proxy_t *mp)
+{
+ const or_options_t *options = get_options();
+ extern char **environ;
+
+ LPVOID tmp=NULL;
+
+ char *state_tmp=NULL;
+ char *state_env=NULL;
+ char *transports_to_launch=NULL;
+ char *transports_env=NULL;
+ char *bindaddr_tmp=NULL;
+ char *bindaddr_env=NULL;
+ char *orport_env=NULL;
+
+ char version_env[31]; /* XXX temp */
+ char extended_env[43]; /* XXX temp */
+
+ int env_size = 0;
+
+ /* A smartlist carrying all the env. variables that the managed
+ proxy should inherit. */
+ smartlist_t *envs = smartlist_create();
+
+ /* Copy the whole environment of the Tor process.
+ It should also copy PATH and HOME of the Tor process.*/
+ char **environ_tmp = environ;
+ while (*environ_tmp)
+ smartlist_add(envs, *environ_tmp++);
+
+ /* Create the TOR_PT_* environment variables. */
+ state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
+ tor_asprintf(&state_env, "TOR_PT_STATE_LOCATION=%s", state_tmp);
+
+ strcpy(version_env, "TOR_PT_MANAGED_TRANSPORT_VER=1");
+
+ transports_to_launch =
+ smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
+
+ tor_asprintf(&transports_env,
+ mp->is_server ?
+ "TOR_PT_SERVER_TRANSPORTS=%s" : "TOR_PT_CLIENT_TRANSPORTS=%s",
+ transports_to_launch);
+
+ smartlist_add(envs, state_env);
+ smartlist_add(envs, version_env);
+ smartlist_add(envs, transports_env);
+
+ if (mp->is_server) {
+ tor_asprintf(&orport_env, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort);
+
+ bindaddr_tmp = get_bindaddr_for_proxy(mp);
+ tor_asprintf(&bindaddr_env, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
+
+ strcpy(extended_env, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200");
+
+ smartlist_add(envs, orport_env);
+ smartlist_add(envs, extended_env);
+ smartlist_add(envs, bindaddr_env);
+ }
+
+ /* It seems like some versions of Windows need a sorted lpEnvironment
+ block. */
+ smartlist_sort_strings(envs);
+
+ /* An environment block consists of a null-terminated block of
+ null-terminated strings: */
+
+ /* Calculate the block's size. */
+ SMARTLIST_FOREACH(envs, const char *, s,
+ env_size += strlen(s) + 1);
+ env_size += 1; /* space for last NUL */
+
+ *envp = tor_malloc(env_size);
+ tmp = *envp;
+
+ /* Create the block. */
+ SMARTLIST_FOREACH_BEGIN(envs, const char *, s) {
+ memcpy(tmp, s, strlen(s)); /* copy the env. variable string */
+ tmp += strlen(s);
+ memset(tmp, '\0', 1); /* append NUL at the end of the string */
+ tmp += 1;
+ } SMARTLIST_FOREACH_END(s);
+ memset(tmp, '\0', 1); /* last NUL */
+
+ /* Finally, free the whole mess. */
+ tor_free(state_tmp);
+ tor_free(state_env);
+ tor_free(transports_to_launch);
+ tor_free(transports_env);
+ tor_free(bindaddr_tmp);
+ tor_free(bindaddr_env);
+ tor_free(orport_env);
+
+ smartlist_free(envs);
+}
+
+#else /* MS_WINDOWS */
+
+/** Prepare the environment <b>envp</b> of managed proxy <b>mp</b>.
+ * <b>envp</b> is allocated on the heap and should be freed by the
+ * caller after its use. */
+static int
+set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp)
+{
+ const or_options_t *options = get_options();
+ char **tmp=NULL;
+ char *state_loc=NULL;
+ char *transports_to_launch=NULL;
+ char *bindaddr=NULL;
+ char *home_env=NULL;
+ char *path_env=NULL;
+
+ int r = -1;
+ int n_envs = mp->is_server ? ENVIRON_SIZE_SERVER : ENVIRON_SIZE_CLIENT;
+
+ /* allocate enough space for our env. vars and a NULL pointer */
+ *envp = tor_malloc(sizeof(char*)*(n_envs+1));
+ tmp = *envp;
+
+ state_loc = get_datadir_fname("pt_state/"); /* XXX temp */
+ transports_to_launch =
+ smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
+
+ home_env = getenv("HOME");
+ path_env = getenv("PATH");
+ if (!home_env || !path_env)
+ goto done;
+
+ tor_asprintf(tmp++, "HOME=%s", home_env);
+ tor_asprintf(tmp++, "PATH=%s", path_env);
+ tor_asprintf(tmp++, "TOR_PT_STATE_LOCATION=%s", state_loc);
+ tor_asprintf(tmp++, "TOR_PT_MANAGED_TRANSPORT_VER=1"); /* temp */
+ if (mp->is_server) {
+ bindaddr = get_bindaddr_for_proxy(mp);
+
+ /* XXX temp */
+ tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort);
+ tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=%s", bindaddr);
+ tor_asprintf(tmp++, "TOR_PT_SERVER_TRANSPORTS=%s", transports_to_launch);
+ /* XXX temp*/
+ tor_asprintf(tmp++, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200");
+ } else {
+ tor_asprintf(tmp++, "TOR_PT_CLIENT_TRANSPORTS=%s", transports_to_launch);
+ }
+ *tmp = NULL;
+
+ r = 0;
+
+ done:
+ tor_free(state_loc);
+ tor_free(transports_to_launch);
+ tor_free(bindaddr);
+
+ return r;
+}
+
+#endif /* MS_WINDOWS */
+
+/** Create and return a new managed proxy for <b>transport</b> using
+ * <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server
+ * managed proxy. */
+static managed_proxy_t *
+managed_proxy_create(const smartlist_t *transport_list,
+ char **proxy_argv, int is_server)
+{
+ managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
+ mp->conf_state = PT_PROTO_INFANT;
+ mp->is_server = is_server;
+ mp->argv = proxy_argv;
+ mp->transports = smartlist_create();
+
+ mp->transports_to_launch = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, const char *, transport,
+ add_transport_to_proxy(transport, mp));
+
+ /* register the managed proxy */
+ if (!managed_proxy_list)
+ managed_proxy_list = smartlist_create();
+ smartlist_add(managed_proxy_list, mp);
+ unconfigured_proxies_n++;
+
+ return mp;
+}
+
+/** Register <b>transport</b> using proxy with <b>proxy_argv</b> to
+ * the managed proxy subsystem.
+ * If <b>is_server</b> is true, then the proxy is a server proxy. */
+void
+pt_kickstart_proxy(const smartlist_t *transport_list,
+ char **proxy_argv, int is_server)
+{
+ managed_proxy_t *mp=NULL;
+ transport_t *old_transport = NULL;
+
+ mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
+
+ if (!mp) { /* we haven't seen this proxy before */
+ managed_proxy_create(transport_list, proxy_argv, is_server);
+
+ } else { /* known proxy. add its transport to its transport list */
+ if (mp->got_hup) {
+ /* If the managed proxy we found is marked by a SIGHUP, it means
+ that it's not useless and should be kept. If it's marked for
+ removal, unmark it and increase the unconfigured proxies so
+ that we try to restart it if we need to. Afterwards, check if
+ a transport_t for 'transport' used to exist before the SIGHUP
+ and make sure it doesn't get deleted because we might reuse
+ it. */
+ if (mp->marked_for_removal) {
+ mp->marked_for_removal = 0;
+ unconfigured_proxies_n++;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport) {
+ old_transport = transport_get_by_name(transport);
+ if (old_transport)
+ old_transport->marked_for_removal = 0;
+ } SMARTLIST_FOREACH_END(transport);
+ }
+
+ SMARTLIST_FOREACH(transport_list, const char *, transport,
+ add_transport_to_proxy(transport, mp));
+ free_execve_args(proxy_argv);
+ }
+}
+
+/** Frees the array of pointers in <b>arg</b> used as arguments to
+ execve(2). */
+static INLINE void
+free_execve_args(char **arg)
+{
+ char **tmp = arg;
+ while (*tmp) /* use the fact that the last element of the array is a
+ NULL pointer to know when to stop freeing */
+ _tor_free(*tmp++);
+
+ tor_free(arg);
+}
+
+/** Tor will read its config.
+ * Prepare the managed proxy list so that proxies not used in the new
+ * config will shutdown, and proxies that need to spawn different
+ * transports will do so. */
+void
+pt_prepare_proxy_list_for_config_read(void)
+{
+ if (!managed_proxy_list)
+ return;
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ /* Destroy unconfigured proxies. */
+ if (mp->conf_state != PT_PROTO_COMPLETED) {
+ managed_proxy_destroy(mp, 1);
+ unconfigured_proxies_n--;
+ continue;
+ }
+
+ tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+ mp->marked_for_removal = 1;
+ mp->got_hup = 1;
+ SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
+ smartlist_clear(mp->transports_to_launch);
+ } SMARTLIST_FOREACH_END(mp);
+
+ tor_assert(unconfigured_proxies_n == 0);
+}
+
+/** The tor config was read.
+ * Destroy all managed proxies that were marked by a previous call to
+ * prepare_proxy_list_for_config_read() and are not used by the new
+ * config. */
+void
+sweep_proxy_list(void)
+{
+ if (!managed_proxy_list)
+ return;
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ if (mp->marked_for_removal) {
+ SMARTLIST_DEL_CURRENT(managed_proxy_list, mp);
+ managed_proxy_destroy(mp, 1);
+ }
+ } SMARTLIST_FOREACH_END(mp);
+}
+
+/** Release all storage held by the pluggable transports subsystem. */
+void
+pt_free_all(void)
+{
+ if (managed_proxy_list) {
+ /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
+ transports and it's the duty of the circuitbuild.c subsystem to
+ free them. Otherwise, it hasn't registered its transports yet
+ and we should free them here. */
+ SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp,
+ managed_proxy_destroy(mp, 1));
+
+ smartlist_free(managed_proxy_list);
+ managed_proxy_list=NULL;
+ }
+}
+
diff --git a/src/or/transports.h b/src/or/transports.h
new file mode 100644
index 0000000000..314af2b3a0
--- /dev/null
+++ b/src/or/transports.h
@@ -0,0 +1,106 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file transports.h
+ * \brief Headers for transports.c
+ **/
+
+#ifndef TOR_TRANSPORTS_H
+#define TOR_TRANSPORTS_H
+
+void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv,
+ int is_server);
+
+#define pt_kickstart_client_proxy(tl, pa) \
+ pt_kickstart_proxy(tl, pa, 0)
+#define pt_kickstart_server_proxy(tl, pa) \
+ pt_kickstart_proxy(tl, pa, 1)
+
+void pt_configure_remaining_proxies(void);
+
+int pt_proxies_configuration_pending(void);
+
+void pt_free_all(void);
+
+void pt_prepare_proxy_list_for_config_read(void);
+void sweep_proxy_list(void);
+
+#ifdef PT_PRIVATE
+/** State of the managed proxy configuration protocol. */
+enum pt_proto_state {
+ PT_PROTO_INFANT, /* was just born */
+ PT_PROTO_LAUNCHED, /* was just launched */
+ PT_PROTO_ACCEPTING_METHODS, /* accepting methods */
+ PT_PROTO_CONFIGURED, /* configured successfully */
+ PT_PROTO_COMPLETED, /* configure and registered its transports */
+ PT_PROTO_BROKEN, /* broke during the protocol */
+ PT_PROTO_FAILED_LAUNCH /* failed while launching */
+};
+
+/** Structure containing information of a managed proxy. */
+typedef struct {
+ enum pt_proto_state conf_state; /* the current configuration state */
+ char **argv; /* the cli arguments of this proxy */
+ int conf_protocol; /* the configuration protocol version used */
+
+ int is_server; /* is it a server proxy? */
+
+ /* A pointer to the process handle of this managed proxy. */
+ process_handle_t *process_handle;
+
+ int pid; /* The Process ID this managed proxy is using. */
+
+ /** Boolean: We are re-parsing our config, and we are going to
+ * remove this managed proxy if we don't find it any transport
+ * plugins that use it. */
+ unsigned int marked_for_removal : 1;
+
+ /** Boolean: We got a SIGHUP while this proxy was running. We use
+ * this flag to signify that this proxy might need to be restarted
+ * so that it can listen for other transports according to the new
+ * torrc. */
+ unsigned int got_hup : 1;
+
+ /* transports to-be-launched by this proxy */
+ smartlist_t *transports_to_launch;
+
+ /* The 'transports' list contains all the transports this proxy has
+ launched.
+
+ Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase,
+ this smartlist contains a 'transport_t' for every transport it
+ has launched.
+
+ When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it
+ registers all its transports to the circuitbuild.c subsystem. At
+ that point the 'transport_t's are owned by the circuitbuild.c
+ subsystem.
+
+ To avoid carrying dangling 'transport_t's in this smartlist,
+ right before the managed_proxy_t reaches the PT_PROTO_COMPLETED
+ phase we replace all 'transport_t's with strings of their
+ transport names.
+
+ So, tl;dr:
+ When (conf_state != PT_PROTO_COMPLETED) this list carries
+ (transport_t *).
+ When (conf_state == PT_PROTO_COMPLETED) this list carries
+ (char *).
+ */
+ smartlist_t *transports;
+} managed_proxy_t;
+
+int parse_cmethod_line(const char *line, managed_proxy_t *mp);
+int parse_smethod_line(const char *line, managed_proxy_t *mp);
+
+int parse_version(const char *line, managed_proxy_t *mp);
+void parse_env_error(const char *line);
+void handle_proxy_line(const char *line, managed_proxy_t *mp);
+
+#endif
+
+#endif
+
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 904719d94b..ffe1f942e7 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -1,6 +1,6 @@
TESTS = test
-noinst_PROGRAMS = test
+noinst_PROGRAMS = test test-child bench
AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
-DLOCALSTATEDIR="\"$(localstatedir)\"" \
@@ -12,19 +12,37 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# matters a lot there, and is quite hard to debug if you forget to do it.
test_SOURCES = \
- test_data.c \
test.c \
test_addr.c \
+ test_containers.c \
test_crypto.c \
+ test_data.c \
test_dir.c \
- test_containers.c \
+ test_microdesc.c \
+ test_pt.c \
test_util.c \
tinytest.c
+bench_SOURCES = \
+ bench.c
+
test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
@TOR_LDFLAGS_libevent@
test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \
../common/libor-event.a \
- @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
+ @TOR_LDFLAGS_libevent@
+bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \
+ ../common/libor-event.a \
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS = \
+ tinytest.h \
+ tinytest_macros.h \
+ test.h
+
-noinst_HEADERS = tinytest.h tinytest_macros.h test.h
diff --git a/src/test/bench.c b/src/test/bench.c
new file mode 100644
index 0000000000..ff2794e7c7
--- /dev/null
+++ b/src/test/bench.c
@@ -0,0 +1,327 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/* Ordinarily defined in tor_main.c; this bit is just here to provide one
+ * since we're not linking to tor_main.c */
+const char tor_git_revision[] = "";
+
+/**
+ * \file bench.c
+ * \brief Benchmarks for lower level Tor modules.
+ **/
+
+#include "orconfig.h"
+
+#define RELAY_PRIVATE
+
+#include "or.h"
+#include "relay.h"
+
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
+static uint64_t nanostart;
+static inline uint64_t
+timespec_to_nsec(const struct timespec *ts)
+{
+ return ((uint64_t)ts->tv_sec)*1000000000 + ts->tv_nsec;
+}
+
+static void
+reset_perftime(void)
+{
+ struct timespec ts;
+ int r;
+ r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
+ tor_assert(r == 0);
+ nanostart = timespec_to_nsec(&ts);
+}
+
+static uint64_t
+perftime(void)
+{
+ struct timespec ts;
+ int r;
+ r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
+ tor_assert(r == 0);
+ return timespec_to_nsec(&ts) - nanostart;
+}
+
+#else
+static struct timeval tv_start = { 0, 0 };
+static void
+reset_perftime(void)
+{
+ tor_gettimeofday(&tv_start);
+}
+static uint64_t
+perftime(void)
+{
+ struct timeval now, out;
+ tor_gettimeofday(&now);
+ timersub(&now, &tv_start, &out);
+ return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000;
+}
+#endif
+
+#define NANOCOUNT(start,end,iters) \
+ ( ((double)((end)-(start))) / (iters) )
+
+/** Run AES performance benchmarks. */
+static void
+bench_aes(void)
+{
+ int len, i;
+ char *b1, *b2;
+ crypto_cipher_env_t *c;
+ uint64_t start, end;
+ const int bytes_per_iter = (1<<24);
+ reset_perftime();
+ c = crypto_new_cipher_env();
+ crypto_cipher_generate_key(c);
+ crypto_cipher_encrypt_init_cipher(c);
+ for (len = 1; len <= 8192; len *= 2) {
+ int iters = bytes_per_iter / len;
+ b1 = tor_malloc_zero(len);
+ b2 = tor_malloc_zero(len);
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ crypto_cipher_encrypt(c, b1, b2, len);
+ }
+ end = perftime();
+ tor_free(b1);
+ tor_free(b2);
+ printf("%d bytes: %.2f nsec per byte\n", len,
+ NANOCOUNT(start, end, iters*len));
+ }
+ crypto_free_cipher_env(c);
+}
+
+static void
+bench_cell_aes(void)
+{
+ uint64_t start, end;
+ const int len = 509;
+ const int iters = (1<<16);
+ const int max_misalign = 15;
+ char *b = tor_malloc(len+max_misalign);
+ crypto_cipher_env_t *c;
+ int i, misalign;
+
+ c = crypto_new_cipher_env();
+ crypto_cipher_generate_key(c);
+ crypto_cipher_encrypt_init_cipher(c);
+
+ reset_perftime();
+ for (misalign = 0; misalign <= max_misalign; ++misalign) {
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ crypto_cipher_crypt_inplace(c, b+misalign, len);
+ }
+ end = perftime();
+ printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign,
+ NANOCOUNT(start, end, iters*len));
+ }
+
+ crypto_free_cipher_env(c);
+ tor_free(b);
+}
+
+/** Run digestmap_t performance benchmarks. */
+static void
+bench_dmap(void)
+{
+ smartlist_t *sl = smartlist_create();
+ smartlist_t *sl2 = smartlist_create();
+ uint64_t start, end, pt2, pt3, pt4;
+ int iters = 8192;
+ const int elts = 4000;
+ const int fpostests = 100000;
+ char d[20];
+ int i,n=0, fp = 0;
+ digestmap_t *dm = digestmap_new();
+ digestset_t *ds = digestset_new(elts);
+
+ for (i = 0; i < elts; ++i) {
+ crypto_rand(d, 20);
+ smartlist_add(sl, tor_memdup(d, 20));
+ }
+ for (i = 0; i < elts; ++i) {
+ crypto_rand(d, 20);
+ smartlist_add(sl2, tor_memdup(d, 20));
+ }
+ printf("nbits=%d\n", ds->mask+1);
+
+ reset_perftime();
+
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1));
+ }
+ pt2 = perftime();
+ printf("digestmap_set: %.2f ns per element\n",
+ NANOCOUNT(start, pt2, iters*elts));
+
+ for (i = 0; i < iters; ++i) {
+ SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp));
+ SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp));
+ }
+ pt3 = perftime();
+ printf("digestmap_get: %.2f ns per element\n",
+ NANOCOUNT(pt2, pt3, iters*elts*2));
+
+ for (i = 0; i < iters; ++i) {
+ SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp));
+ }
+ pt4 = perftime();
+ printf("digestset_add: %.2f ns per element\n",
+ NANOCOUNT(pt3, pt4, iters*elts));
+
+ for (i = 0; i < iters; ++i) {
+ SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp));
+ SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp));
+ }
+ end = perftime();
+ printf("digestset_isin: %.2f ns per element.\n",
+ NANOCOUNT(pt4, end, iters*elts*2));
+ /* We need to use this, or else the whole loop gets optimized out. */
+ printf("Hits == %d\n", n);
+
+ for (i = 0; i < fpostests; ++i) {
+ crypto_rand(d, 20);
+ if (digestset_isin(ds, d)) ++fp;
+ }
+ printf("False positive rate on digestset: %.2f%%\n",
+ (fp/(double)fpostests)*100);
+
+ digestmap_free(dm, NULL);
+ digestset_free(ds);
+ SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp));
+ smartlist_free(sl);
+ smartlist_free(sl2);
+}
+
+static void
+bench_cell_ops(void)
+{
+ const int iters = 1<<16;
+ int i;
+
+ /* benchmarks for cell ops at relay. */
+ or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t));
+ cell_t *cell = tor_malloc(sizeof(cell_t));
+ int outbound;
+ uint64_t start, end;
+
+ crypto_rand((char*)cell->payload, sizeof(cell->payload));
+
+ /* Mock-up or_circuit_t */
+ or_circ->_base.magic = OR_CIRCUIT_MAGIC;
+ or_circ->_base.purpose = CIRCUIT_PURPOSE_OR;
+
+ /* Initialize crypto */
+ or_circ->p_crypto = crypto_new_cipher_env();
+ crypto_cipher_generate_key(or_circ->p_crypto);
+ crypto_cipher_encrypt_init_cipher(or_circ->p_crypto);
+ or_circ->n_crypto = crypto_new_cipher_env();
+ crypto_cipher_generate_key(or_circ->n_crypto);
+ crypto_cipher_encrypt_init_cipher(or_circ->n_crypto);
+ or_circ->p_digest = crypto_new_digest_env();
+ or_circ->n_digest = crypto_new_digest_env();
+
+ reset_perftime();
+
+ for (outbound = 0; outbound <= 1; ++outbound) {
+ cell_direction_t d = outbound ? CELL_DIRECTION_OUT : CELL_DIRECTION_IN;
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ char recognized = 0;
+ crypt_path_t *layer_hint = NULL;
+ relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized);
+ }
+ end = perftime();
+ printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n",
+ outbound?"Out":" In",
+ NANOCOUNT(start,end,iters),
+ NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE));
+ }
+
+ crypto_free_digest_env(or_circ->p_digest);
+ crypto_free_digest_env(or_circ->n_digest);
+ crypto_free_cipher_env(or_circ->p_crypto);
+ crypto_free_cipher_env(or_circ->n_crypto);
+ tor_free(or_circ);
+ tor_free(cell);
+}
+
+typedef void (*bench_fn)(void);
+
+typedef struct benchmark_t {
+ const char *name;
+ bench_fn fn;
+ int enabled;
+} benchmark_t;
+
+#define ENT(s) { #s , bench_##s, 0 }
+
+static struct benchmark_t benchmarks[] = {
+ ENT(dmap),
+ ENT(aes),
+ ENT(cell_aes),
+ ENT(cell_ops),
+ {NULL,NULL,0}
+};
+
+static benchmark_t *
+find_benchmark(const char *name)
+{
+ benchmark_t *b;
+ for (b = benchmarks; b->name; ++b) {
+ if (!strcmp(name, b->name)) {
+ return b;
+ }
+ }
+ return NULL;
+}
+
+/** Main entry point for benchmark code: parse the command line, and run
+ * some benchmarks. */
+int
+main(int argc, const char **argv)
+{
+ int i;
+ int list=0, n_enabled=0;
+ benchmark_t *b;
+
+ tor_threads_init();
+
+ for (i = 1; i < argc; ++i) {
+ if (!strcmp(argv[i], "--list")) {
+ list = 1;
+ } else {
+ benchmark_t *b = find_benchmark(argv[i]);
+ ++n_enabled;
+ if (b) {
+ b->enabled = 1;
+ } else {
+ printf("No such benchmark as %s\n", argv[i]);
+ }
+ }
+ }
+
+ reset_perftime();
+
+ crypto_seed_rng(1);
+
+ for (b = benchmarks; b->name; ++b) {
+ if (b->enabled || n_enabled == 0) {
+ printf("===== %s =====\n", b->name);
+ if (!list)
+ b->fn();
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/test/test-child.c b/src/test/test-child.c
new file mode 100644
index 0000000000..1b9c5e3d57
--- /dev/null
+++ b/src/test/test-child.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include "orconfig.h"
+#ifdef MS_WINDOWS
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+/** Trivial test program which prints out its command line arguments so we can
+ * check if tor_spawn_background() works */
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ fprintf(stdout, "OUT\n");
+ fprintf(stderr, "ERR\n");
+ for (i = 1; i < argc; i++)
+ fprintf(stdout, "%s\n", argv[i]);
+ fprintf(stdout, "SLEEPING\n");
+ /* We need to flush stdout so that test_util_spawn_background_partial_read()
+ succeed. Otherwise ReadFile() will get the entire output in one */
+ // XXX: Can we make stdio flush on newline?
+ fflush(stdout);
+#ifdef MS_WINDOWS
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ fprintf(stdout, "DONE\n");
+#ifdef MS_WINDOWS
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+
+ return 0;
+}
+
diff --git a/src/test/test.c b/src/test/test.c
index b5b744eba7..092b2c3780 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -119,30 +119,46 @@ get_fname(const char *name)
return buf;
}
-/** Remove all files stored under the temporary directory, and the directory
- * itself. Called by atexit(). */
+/* Remove a directory and all of its subdirectories */
static void
-remove_directory(void)
+rm_rf(const char *dir)
{
+ struct stat st;
smartlist_t *elements;
- if (getpid() != temp_dir_setup_in_pid) {
- /* Only clean out the tempdir when the main process is exiting. */
- return;
- }
- elements = tor_listdir(temp_dir);
+
+ elements = tor_listdir(dir);
if (elements) {
SMARTLIST_FOREACH(elements, const char *, cp,
{
- size_t len = strlen(cp)+strlen(temp_dir)+16;
- char *tmp = tor_malloc(len);
- tor_snprintf(tmp, len, "%s"PATH_SEPARATOR"%s", temp_dir, cp);
- unlink(tmp);
+ char *tmp = NULL;
+ tor_asprintf(&tmp, "%s"PATH_SEPARATOR"%s", dir, cp);
+ if (0 == stat(tmp,&st) && (st.st_mode & S_IFDIR)) {
+ rm_rf(tmp);
+ } else {
+ if (unlink(tmp)) {
+ fprintf(stderr, "Error removing %s: %s\n", tmp, strerror(errno));
+ }
+ }
tor_free(tmp);
});
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements);
}
- rmdir(temp_dir);
+ if (rmdir(dir))
+ fprintf(stderr, "Error removing directory %s: %s\n", dir, strerror(errno));
+}
+
+/** Remove all files stored under the temporary directory, and the directory
+ * itself. Called by atexit(). */
+static void
+remove_directory(void)
+{
+ if (getpid() != temp_dir_setup_in_pid) {
+ /* Only clean out the tempdir when the main process is exiting. */
+ return;
+ }
+
+ rm_rf(temp_dir);
}
/** Define this if unit tests spend too much time generating public keys*/
@@ -187,6 +203,437 @@ free_pregenerated_keys(void)
}
}
+typedef struct socks_test_data_t {
+ socks_request_t *req;
+ buf_t *buf;
+} socks_test_data_t;
+
+static void *
+socks_test_setup(const struct testcase_t *testcase)
+{
+ socks_test_data_t *data = tor_malloc(sizeof(socks_test_data_t));
+ (void)testcase;
+ data->buf = buf_new_with_capacity(256);
+ data->req = socks_request_new();
+ config_register_addressmaps(get_options());
+ return data;
+}
+static int
+socks_test_cleanup(const struct testcase_t *testcase, void *ptr)
+{
+ socks_test_data_t *data = ptr;
+ (void)testcase;
+ buf_free(data->buf);
+ socks_request_free(data->req);
+ tor_free(data);
+ return 1;
+}
+
+const struct testcase_setup_t socks_setup = {
+ socks_test_setup, socks_test_cleanup
+};
+
+#define SOCKS_TEST_INIT() \
+ socks_test_data_t *testdata = ptr; \
+ buf_t *buf = testdata->buf; \
+ socks_request_t *socks = testdata->req;
+#define ADD_DATA(buf, s) \
+ write_to_buf(s, sizeof(s)-1, buf)
+
+static void
+socks_request_clear(socks_request_t *socks)
+{
+ tor_free(socks->username);
+ tor_free(socks->password);
+ memset(socks, 0, sizeof(socks_request_t));
+}
+
+/** Perform unsupported SOCKS 4 commands */
+static void
+test_socks_4_unsupported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 4 Send BIND [02] to IP address 2.2.2.2:4369 */
+ ADD_DATA(buf, "\x04\x02\x11\x11\x02\x02\x02\x02\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == -1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+
+ done:
+ ;
+}
+
+/** Perform supported SOCKS 4 commands */
+static void
+test_socks_4_supported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ test_eq(0, buf_datalen(buf));
+
+ /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */
+ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ test_eq(SOCKS_COMMAND_CONNECT, socks->command);
+ test_streq("2.2.2.3", socks->address);
+ test_eq(4370, socks->port);
+ test_assert(socks->got_auth == 0);
+ test_assert(! socks->username);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/
+ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ test_eq(SOCKS_COMMAND_CONNECT, socks->command);
+ test_streq("2.2.2.4", socks->address);
+ test_eq(4370, socks->port);
+ test_assert(socks->got_auth == 1);
+ test_assert(socks->username);
+ test_eq(2, socks->usernamelen);
+ test_memeq("me", socks->username, 2);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 4a Send RESOLVE [F0] request for torproject.org */
+ ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ test_streq("torproject.org", socks->address);
+
+ test_eq(0, buf_datalen(buf));
+
+ done:
+ ;
+}
+
+/** Perform unsupported SOCKS 5 commands */
+static void
+test_socks_5_unsupported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Send unsupported BIND [02] command */
+ ADD_DATA(buf, "\x05\x02\x00\x01");
+
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 0);
+ test_eq(0, buf_datalen(buf));
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ ADD_DATA(buf, "\x05\x02\x00\x01\x02\x02\x02\x01\x01\x01");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), -1);
+ /* XXX: shouldn't tor reply 'command not supported' [07]? */
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send unsupported UDP_ASSOCIATE [03] command */
+ ADD_DATA(buf, "\x05\x03\x00\x01\x02");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 0);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), -1);
+ /* XXX: shouldn't tor reply 'command not supported' [07]? */
+
+ done:
+ ;
+}
+
+/** Perform supported SOCKS 5 commands */
+static void
+test_socks_5_supported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 0);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 1);
+ test_streq("2.2.2.2", socks->address);
+ test_eq(4369, socks->port);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 1);
+
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ test_streq("torproject.org", socks->address);
+ test_eq(4369, socks->port);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ test_streq("torproject.org", socks->address);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ test_streq("2.2.2.5", socks->address);
+
+ test_eq(0, buf_datalen(buf));
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication */
+static void
+test_socks_5_no_authenticate(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /*SOCKS 5 No Authentication */
+ ADD_DATA(buf,"\x05\x01\x00");
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(SOCKS_NO_AUTH, socks->reply[1]);
+
+ test_eq(0, buf_datalen(buf));
+
+ /*SOCKS 5 Send username/password anyway - pretend to be broken */
+ ADD_DATA(buf,"\x01\x02\x01\x01\x02\x01\x01");
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ test_eq(2, socks->usernamelen);
+ test_eq(2, socks->passwordlen);
+
+ test_memeq("\x01\x01", socks->username, 2);
+ test_memeq("\x01\x01", socks->password, 2);
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication */
+static void
+test_socks_5_authenticate(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(SOCKS_USER_PASS, socks->reply[1]);
+ test_eq(5, socks->socks_version);
+
+ test_eq(0, buf_datalen(buf));
+
+ /* SOCKS 5 Send username/password */
+ ADD_DATA(buf, "\x01\x02me\x08mypasswd");
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ test_eq(2, socks->usernamelen);
+ test_eq(8, socks->passwordlen);
+
+ test_memeq("me", socks->username, 2);
+ test_memeq("mypasswd", socks->password, 8);
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication and send data all in one go */
+static void
+test_socks_5_authenticate_with_data(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(SOCKS_USER_PASS, socks->reply[1]);
+ test_eq(5, socks->socks_version);
+
+ test_eq(0, buf_datalen(buf));
+
+ /* SOCKS 5 Send username/password */
+ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
+ ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
+ test_assert(fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ test_streq("2.2.2.2", socks->address);
+ test_eq(4369, socks->port);
+
+ test_eq(2, socks->usernamelen);
+ test_eq(3, socks->passwordlen);
+ test_memeq("me", socks->username, 2);
+ test_memeq("you", socks->password, 3);
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication before method negotiated */
+static void
+test_socks_5_auth_before_negotiation(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Send username/password */
+ ADD_DATA(buf, "\x01\x02me\x02me");
+ test_assert(fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks) == -1);
+ test_eq(0, socks->socks_version);
+ test_eq(0, socks->replylen);
+ test_eq(0, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ done:
+ ;
+}
+
+static void
+test_buffer_copy(void *arg)
+{
+ generic_buffer_t *buf=NULL, *buf2=NULL;
+ const char *s;
+ size_t len;
+ char b[256];
+ int i;
+ (void)arg;
+
+ buf = generic_buffer_new();
+ tt_assert(buf);
+
+ /* Copy an empty buffer. */
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_assert(buf2);
+ tt_int_op(0, ==, generic_buffer_len(buf2));
+
+ /* Now try with a short buffer. */
+ s = "And now comes an act of enormous enormance!";
+ len = strlen(s);
+ generic_buffer_add(buf, s, len);
+ tt_int_op(len, ==, generic_buffer_len(buf));
+ /* Add junk to buf2 so we can test replacing.*/
+ generic_buffer_add(buf2, "BLARG", 5);
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(len, ==, generic_buffer_len(buf2));
+ generic_buffer_get(buf2, b, len);
+ test_mem_op(b, ==, s, len);
+ /* Now free buf2 and retry so we can test allocating */
+ generic_buffer_free(buf2);
+ buf2 = NULL;
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(len, ==, generic_buffer_len(buf2));
+ generic_buffer_get(buf2, b, len);
+ test_mem_op(b, ==, s, len);
+ /* Clear buf for next test */
+ generic_buffer_get(buf, b, len);
+ tt_int_op(generic_buffer_len(buf),==,0);
+
+ /* Okay, now let's try a bigger buffer. */
+ s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
+ "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
+ "fugiat quo voluptas nulla pariatur?";
+ len = strlen(s);
+ for (i = 0; i < 256; ++i) {
+ b[0]=i;
+ generic_buffer_add(buf, b, 1);
+ generic_buffer_add(buf, s, len);
+ }
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(generic_buffer_len(buf2), ==, generic_buffer_len(buf));
+ for (i = 0; i < 256; ++i) {
+ generic_buffer_get(buf2, b, len+1);
+ tt_int_op((unsigned char)b[0],==,i);
+ test_mem_op(b+1, ==, s, len);
+ }
+
+ done:
+ if (buf)
+ generic_buffer_free(buf);
+ if (buf2)
+ generic_buffer_free(buf2);
+}
+
/** Run unit tests for buffers.c */
static void
test_buffers(void)
@@ -566,6 +1013,7 @@ test_policy_summary_helper(const char *policy_str,
smartlist_t *policy = smartlist_create();
char *summary = NULL;
int r;
+ short_policy_t *short_policy = NULL;
line.key = (char*)"foo";
line.value = (char *)policy_str;
@@ -578,10 +1026,14 @@ test_policy_summary_helper(const char *policy_str,
test_assert(summary != NULL);
test_streq(summary, expected_summary);
+ short_policy = parse_short_policy(summary);
+ tt_assert(short_policy);
+
done:
tor_free(summary);
if (policy)
addr_policy_list_free(policy);
+ short_policy_free(short_policy);
}
/** Run unit tests for generating summary lines of exit policies */
@@ -611,12 +1063,15 @@ test_policies(void)
smartlist_add(policy, p);
+ tor_addr_from_ipv4h(&tar, 0x01020304u);
test_assert(ADDR_POLICY_ACCEPTED ==
- compare_addr_to_addr_policy(0x01020304u, 2, policy));
+ compare_tor_addr_to_addr_policy(&tar, 2, policy));
+ tor_addr_make_unspec(&tar);
test_assert(ADDR_POLICY_PROBABLY_ACCEPTED ==
- compare_addr_to_addr_policy(0, 2, policy));
+ compare_tor_addr_to_addr_policy(&tar, 2, policy));
+ tor_addr_from_ipv4h(&tar, 0xc0a80102);
test_assert(ADDR_POLICY_REJECTED ==
- compare_addr_to_addr_policy(0xc0a80102, 2, policy));
+ compare_tor_addr_to_addr_policy(&tar, 2, policy));
test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL, 1));
test_assert(policy2);
@@ -810,102 +1265,6 @@ test_policies(void)
}
}
-/** Run AES performance benchmarks. */
-static void
-bench_aes(void)
-{
- int len, i;
- char *b1, *b2;
- crypto_cipher_env_t *c;
- struct timeval start, end;
- const int iters = 100000;
- uint64_t nsec;
- c = crypto_new_cipher_env();
- crypto_cipher_generate_key(c);
- crypto_cipher_encrypt_init_cipher(c);
- for (len = 1; len <= 8192; len *= 2) {
- b1 = tor_malloc_zero(len);
- b2 = tor_malloc_zero(len);
- tor_gettimeofday(&start);
- for (i = 0; i < iters; ++i) {
- crypto_cipher_encrypt(c, b1, b2, len);
- }
- tor_gettimeofday(&end);
- tor_free(b1);
- tor_free(b2);
- nsec = (uint64_t) tv_udiff(&start,&end);
- nsec *= 1000;
- nsec /= (iters*len);
- printf("%d bytes: "U64_FORMAT" nsec per byte\n", len,
- U64_PRINTF_ARG(nsec));
- }
- crypto_free_cipher_env(c);
-}
-
-/** Run digestmap_t performance benchmarks. */
-static void
-bench_dmap(void)
-{
- smartlist_t *sl = smartlist_create();
- smartlist_t *sl2 = smartlist_create();
- struct timeval start, end, pt2, pt3, pt4;
- const int iters = 10000;
- const int elts = 4000;
- const int fpostests = 1000000;
- char d[20];
- int i,n=0, fp = 0;
- digestmap_t *dm = digestmap_new();
- digestset_t *ds = digestset_new(elts);
-
- for (i = 0; i < elts; ++i) {
- crypto_rand(d, 20);
- smartlist_add(sl, tor_memdup(d, 20));
- }
- for (i = 0; i < elts; ++i) {
- crypto_rand(d, 20);
- smartlist_add(sl2, tor_memdup(d, 20));
- }
- printf("nbits=%d\n", ds->mask+1);
-
- tor_gettimeofday(&start);
- for (i = 0; i < iters; ++i) {
- SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1));
- }
- tor_gettimeofday(&pt2);
- for (i = 0; i < iters; ++i) {
- SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp));
- SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp));
- }
- tor_gettimeofday(&pt3);
- for (i = 0; i < iters; ++i) {
- SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp));
- }
- tor_gettimeofday(&pt4);
- for (i = 0; i < iters; ++i) {
- SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp));
- SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp));
- }
- tor_gettimeofday(&end);
-
- for (i = 0; i < fpostests; ++i) {
- crypto_rand(d, 20);
- if (digestset_isin(ds, d)) ++fp;
- }
-
- printf("%ld\n",(unsigned long)tv_udiff(&start, &pt2));
- printf("%ld\n",(unsigned long)tv_udiff(&pt2, &pt3));
- printf("%ld\n",(unsigned long)tv_udiff(&pt3, &pt4));
- printf("%ld\n",(unsigned long)tv_udiff(&pt4, &end));
- printf("-- %d\n", n);
- printf("++ %f\n", fp/(double)fpostests);
- digestmap_free(dm, NULL);
- digestset_free(ds);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp));
- smartlist_free(sl);
- smartlist_free(sl2);
-}
-
/** Test encoding and parsing of rendezvous service descriptors. */
static void
test_rend_fns(void)
@@ -1026,8 +1385,73 @@ static void
test_geoip(void)
{
int i, j;
- time_t now = time(NULL);
+ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
char *s = NULL;
+ const char *bridge_stats_1 =
+ "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "bridge-ips zz=24,xy=8\n",
+ *dirreq_stats_1 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips ab=8\n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs ab=8\n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_2 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_3 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_4 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *entry_stats_1 =
+ "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "entry-ips ab=8\n",
+ *entry_stats_2 =
+ "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "entry-ips \n";
/* Populate the DB a bit. Add these in order, since we can't do the final
* 'sort' step. These aren't very good IP addresses, but they're perfectly
@@ -1053,8 +1477,8 @@ test_geoip(void)
test_streq("??", NAMEFOR(2000));
#undef NAMEFOR
- get_options()->BridgeRelay = 1;
- get_options()->BridgeRecordUsageByCountry = 1;
+ get_options_mutable()->BridgeRelay = 1;
+ get_options_mutable()->BridgeRecordUsageByCountry = 1;
/* Put 9 observations in AB... */
for (i=32; i < 40; ++i)
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200);
@@ -1077,6 +1501,114 @@ test_geoip(void)
test_assert(s);
test_streq("zz=24,xy=8", s);
+ /* Start testing bridge statistics by making sure that we don't output
+ * bridge stats without initializing them. */
+ s = geoip_format_bridge_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats and generate the bridge-stats history string out of
+ * the connecting clients added above. */
+ geoip_bridge_stats_init(now);
+ s = geoip_format_bridge_stats(now + 86400);
+ test_streq(bridge_stats_1, s);
+ tor_free(s);
+
+ /* Stop collecting bridge stats and make sure we don't write a history
+ * string anymore. */
+ geoip_bridge_stats_term();
+ s = geoip_format_bridge_stats(now + 86400);
+ test_assert(!s);
+
+ /* Stop being a bridge and start being a directory mirror that gathers
+ * directory request statistics. */
+ geoip_bridge_stats_term();
+ get_options_mutable()->BridgeRelay = 0;
+ get_options_mutable()->BridgeRecordUsageByCountry = 0;
+ get_options_mutable()->DirReqStatistics = 1;
+
+ /* Start testing dirreq statistics by making sure that we don't collect
+ * dirreq stats without initializing them. */
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note one connecting client, and generate the
+ * dirreq-stats history string. */
+ geoip_dirreq_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_1, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add another connecting client, and ensure we
+ * don't generate a history string. */
+ geoip_dirreq_stats_term();
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 101, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add a connecting client, reset stats, and make sure
+ * that we get an all empty history string. */
+ geoip_dirreq_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now);
+ geoip_reset_dirreq_stats(now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_2, s);
+ tor_free(s);
+
+ /* Note a successful network status response and make sure that it
+ * appears in the history string. */
+ geoip_note_ns_response(GEOIP_CLIENT_NETWORKSTATUS, GEOIP_SUCCESS);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_3, s);
+ tor_free(s);
+
+ /* Start a tunneled directory request. */
+ geoip_start_dirreq((uint64_t) 1, 1024, GEOIP_CLIENT_NETWORKSTATUS,
+ DIRREQ_TUNNELED);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_4, s);
+
+ /* Stop collecting directory request statistics and start gathering
+ * entry stats. */
+ geoip_dirreq_stats_term();
+ get_options_mutable()->DirReqStatistics = 0;
+ get_options_mutable()->EntryStatistics = 1;
+
+ /* Start testing entry statistics by making sure that we don't collect
+ * anything without initializing entry stats. */
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note one connecting client, and generate the
+ * entry-stats history string. */
+ geoip_entry_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_streq(entry_stats_1, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add another connecting client, and ensure we
+ * don't generate a history string. */
+ geoip_entry_stats_term();
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 101, now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add a connecting client, reset stats, and make sure
+ * that we get an all empty history string. */
+ geoip_entry_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now);
+ geoip_reset_entry_stats(now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_streq(entry_stats_2, s);
+ tor_free(s);
+
+ /* Stop collecting entry statistics. */
+ geoip_entry_stats_term();
+ get_options_mutable()->EntryStatistics = 0;
+
done:
tor_free(s);
}
@@ -1089,7 +1621,8 @@ test_stats(void)
char *s = NULL;
int i;
- /* We shouldn't collect exit stats without initializing them. */
+ /* Start with testing exit port statistics; we shouldn't collect exit
+ * stats without initializing them. */
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
s = rep_hist_format_exit_stats(now + 86400);
@@ -1134,7 +1667,7 @@ test_stats(void)
test_assert(!s);
/* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no streams or bytes at all. */
+ * get when observing no streams or bytes at all. */
rep_hist_exit_stats_init(now);
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
@@ -1144,6 +1677,96 @@ test_stats(void)
"exit-kibibytes-written other=0\n"
"exit-kibibytes-read other=0\n"
"exit-streams-opened other=0\n", s);
+ tor_free(s);
+
+ /* Continue with testing connection statistics; we shouldn't collect
+ * conn stats without initializing them. */
+ rep_hist_note_or_conn_bytes(1, 20, 400, now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note bytes, and generate history string. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n", s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_conn_stats_term();
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no bytes at all. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ rep_hist_reset_conn_stats(now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", s);
+ tor_free(s);
+
+ /* Continue with testing buffer statistics; we shouldn't collect buffer
+ * stats without initializing them. */
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, add statistics for a single circuit, and generate
+ * the history string. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 1\n", s);
+ tor_free(s);
+
+ /* Add nineteen more circuit statistics to the one that's already in the
+ * history to see that the math works correctly. */
+ for (i = 21; i < 30; i++)
+ rep_hist_add_buffer_stats(2.0, 2.0, i);
+ for (i = 20; i < 30; i++)
+ rep_hist_add_buffer_stats(3.5, 3.5, i);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
+ "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
+ "2.75,2.75\n"
+ "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
+ "cell-circuits-per-decile 2\n", s);
+ tor_free(s);
+
+ /* Stop collecting stats, add statistics for one circuit, and ensure we
+ * don't generate a history string. */
+ rep_hist_buffer_stats_term();
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add statistics for one circuit, reset stats, and make
+ * sure that the history has all zeros. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ rep_hist_reset_buffer_stats(now);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 0\n", s);
done:
tor_free(s);
@@ -1180,12 +1803,13 @@ const struct testcase_setup_t legacy_setup = {
{ #group "_" #name, legacy_test_helper, 0, &legacy_setup, \
test_ ## group ## _ ## name }
#define DISABLED(name) \
- { #name, legacy_test_helper, TT_SKIP, &legacy_setup, name }
+ { #name, legacy_test_helper, TT_SKIP, &legacy_setup, test_ ## name }
#define FORK(name) \
{ #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name }
static struct testcase_t test_array[] = {
ENT(buffers),
+ { "buffer_copy", test_buffer_copy, 0, NULL, NULL },
ENT(onion_handshake),
ENT(circuit_timeout),
ENT(policies),
@@ -1193,8 +1817,23 @@ static struct testcase_t test_array[] = {
ENT(geoip),
FORK(stats),
- DISABLED(bench_aes),
- DISABLED(bench_dmap),
+ END_OF_TESTCASES
+};
+
+#define SOCKSENT(name) \
+ { #name, test_socks_##name, TT_FORK, &socks_setup, NULL }
+
+static struct testcase_t socks_tests[] = {
+ SOCKSENT(4_unsupported_commands),
+ SOCKSENT(4_supported_commands),
+
+ SOCKSENT(5_unsupported_commands),
+ SOCKSENT(5_supported_commands),
+ SOCKSENT(5_no_authenticate),
+ SOCKSENT(5_auth_before_negotiation),
+ SOCKSENT(5_authenticate),
+ SOCKSENT(5_authenticate_with_data),
+
END_OF_TESTCASES
};
@@ -1203,14 +1842,19 @@ extern struct testcase_t crypto_tests[];
extern struct testcase_t container_tests[];
extern struct testcase_t util_tests[];
extern struct testcase_t dir_tests[];
+extern struct testcase_t microdesc_tests[];
+extern struct testcase_t pt_tests[];
static struct testgroup_t testgroups[] = {
{ "", test_array },
+ { "socks/", socks_tests },
{ "addr/", addr_tests },
{ "crypto/", crypto_tests },
{ "container/", container_tests },
{ "util/", util_tests },
{ "dir/", dir_tests },
+ { "dir/md/", microdesc_tests },
+ { "pt/", pt_tests },
END_OF_GROUPS
};
@@ -1259,7 +1903,11 @@ main(int c, const char **v)
}
options->command = CMD_RUN_UNITTESTS;
- crypto_global_init(0, NULL, NULL);
+ if (crypto_global_init(0, NULL, NULL)) {
+ printf("Can't initialize crypto subsystem; exiting.\n");
+ return 1;
+ }
+ crypto_set_tls_dh_prime(NULL);
rep_hist_init();
network_init();
setup_directory();
diff --git a/src/test/test.h b/src/test/test.h
index f7ae46ce6d..a053a7ac43 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -45,7 +45,8 @@
_print = tor_malloc(printlen); \
base16_encode(_print, printlen, _value, \
(len)); }, \
- { tor_free(_print); } \
+ { tor_free(_print); }, \
+ TT_EXIT_TEST_FUNCTION \
);
#define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len)
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 1dab0e0112..9d8e1fe8c5 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -14,30 +14,30 @@ test_addr_basic(void)
uint16_t u16;
char *cp;
- /* Test parse_addr_port */
+ /* Test addr_port_lookup */
cp = NULL; u32 = 3; u16 = 3;
- test_assert(!parse_addr_port(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
+ test_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
test_streq(cp, "1.2.3.4");
test_eq(u32, 0x01020304u);
test_eq(u16, 0);
tor_free(cp);
- test_assert(!parse_addr_port(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
+ test_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
test_streq(cp, "4.3.2.1");
test_eq(u32, 0x04030201u);
test_eq(u16, 99);
tor_free(cp);
- test_assert(!parse_addr_port(LOG_WARN, "nonexistent.address:4040",
+ test_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040",
&cp, NULL, &u16));
test_streq(cp, "nonexistent.address");
test_eq(u16, 4040);
tor_free(cp);
- test_assert(!parse_addr_port(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
+ test_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
test_streq(cp, "localhost");
test_eq(u32, 0x7f000001u);
test_eq(u16, 9999);
tor_free(cp);
u32 = 3;
- test_assert(!parse_addr_port(LOG_WARN, "localhost", NULL, &u32, &u16));
+ test_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16));
test_eq(cp, NULL);
test_eq(u32, 0x7f000001u);
test_eq(u16, 0);
@@ -53,9 +53,17 @@ test_addr_basic(void)
char tmpbuf[TOR_ADDR_BUF_LEN];
const char *ip = "176.192.208.224";
struct in_addr in;
- tor_inet_pton(AF_INET, ip, &in);
- tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf));
+
+ /* good round trip */
+ test_eq(tor_inet_pton(AF_INET, ip, &in), 1);
+ test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)), &tmpbuf);
test_streq(tmpbuf, ip);
+
+ /* just enough buffer length */
+ test_streq(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip) + 1), ip);
+
+ /* too short buffer */
+ test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip)), NULL);
}
done:
@@ -74,7 +82,9 @@ test_addr_basic(void)
cp += 2; \
if (i != 15) *cp++ = ':'; \
} \
- }, { tor_free(_print); } \
+ }, \
+ { tor_free(_print); }, \
+ TT_EXIT_TEST_FUNCTION \
); \
STMT_END
@@ -165,6 +175,7 @@ static void
test_addr_ip6_helpers(void)
{
char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN];
+ char rbuf[REVERSE_LOOKUP_NAME_BUF_LEN];
struct in6_addr a1, a2;
tor_addr_t t1, t2;
int r, i;
@@ -175,8 +186,30 @@ test_addr_ip6_helpers(void)
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
- // struct in_addr b1, b2;
/* Test tor_inet_ntop and tor_inet_pton: IPv6 */
+ {
+ const char *ip = "2001::1234";
+ const char *ip_ffff = "::ffff:192.168.1.2";
+
+ /* good round trip */
+ test_eq(tor_inet_pton(AF_INET6, ip, &a1), 1);
+ test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), &buf);
+ test_streq(buf, ip);
+
+ /* good round trip - ::ffff:0:0 style */
+ test_eq(tor_inet_pton(AF_INET6, ip_ffff, &a2), 1);
+ test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)), &buf);
+ test_streq(buf, ip_ffff);
+
+ /* just long enough buffer (remember \0) */
+ test_streq(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1), ip);
+ test_streq(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1),
+ ip_ffff);
+
+ /* too short buffer (remember \0) */
+ test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)), NULL);
+ test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)), NULL);
+ }
/* ==== Converting to and from sockaddr_t. */
sin = (struct sockaddr_in *)&sa_storage;
@@ -268,12 +301,23 @@ test_addr_ip6_helpers(void)
test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000",
"1000:1:0:7::");
+ /* Bad af param */
+ test_eq(tor_inet_pton(AF_UNSPEC, 0, 0), -1);
+
/* === Test pton: invalid in6. */
test_pton6_bad("foobar.");
+ test_pton6_bad("-1::");
+ test_pton6_bad("00001::");
+ test_pton6_bad("10000::");
+ test_pton6_bad("::10000");
test_pton6_bad("55555::");
test_pton6_bad("9:-60::");
+ test_pton6_bad("9:+60::");
+ test_pton6_bad("9|60::");
+ test_pton6_bad("0x60::");
+ test_pton6_bad("::0x60");
+ test_pton6_bad("9:0x60::");
test_pton6_bad("1:2:33333:4:0002:3::");
- //test_pton6_bad("1:2:3333:4:00002:3::");// BAD, but glibc doesn't say so.
test_pton6_bad("1:2:3333:4:fish:3::");
test_pton6_bad("1:2:3:4:5:6:7:8:9");
test_pton6_bad("1:2:3:4:5:6:7");
@@ -281,8 +325,14 @@ test_addr_ip6_helpers(void)
test_pton6_bad("1:2:3:4:5:6:1.2.3");
test_pton6_bad("::1.2.3");
test_pton6_bad("::1.2.3.4.5");
+ test_pton6_bad("::ffff:0xff.0.0.0");
+ test_pton6_bad("::ffff:ff.0.0.0");
+ test_pton6_bad("::ffff:256.0.0.0");
+ test_pton6_bad("::ffff:-1.0.0.0");
test_pton6_bad("99");
test_pton6_bad("");
+ test_pton6_bad(".");
+ test_pton6_bad(":");
test_pton6_bad("1::2::3:4");
test_pton6_bad("a:::b:c");
test_pton6_bad(":::a:b:c");
@@ -291,6 +341,9 @@ test_addr_ip6_helpers(void)
/* test internal checking */
test_external_ip("fbff:ffff::2:7", 0);
test_internal_ip("fc01::2:7", 0);
+ test_internal_ip("fc01::02:7", 0);
+ test_internal_ip("fc01::002:7", 0);
+ test_internal_ip("fc01::0002:7", 0);
test_internal_ip("fdff:ffff::f:f", 0);
test_external_ip("fe00::3:f", 0);
@@ -361,33 +414,67 @@ test_addr_ip6_helpers(void)
test_addr_compare_masked("0::2:2:1", <, "0::8000:2:1", 81);
test_addr_compare_masked("0::2:2:1", ==, "0::8000:2:1", 80);
- /* Test decorated addr_to_string. */
- test_eq(AF_INET6, tor_addr_from_str(&t1, "[123:45:6789::5005:11]"));
+ /* Test undecorated tor_addr_to_str */
+ test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
+ p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
+ test_streq(p1, "123:45:6789::5005:11");
+ test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1"));
+ p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
+ test_streq(p1, "18.0.0.1");
+
+ /* Test decorated tor_addr_to_str */
+ test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
test_streq(p1, "[123:45:6789::5005:11]");
- test_eq(AF_INET, tor_addr_from_str(&t1, "18.0.0.1"));
+ test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1"));
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
test_streq(p1, "18.0.0.1");
- /* Test tor_addr_parse_reverse_lookup_name */
- i = tor_addr_parse_reverse_lookup_name(&t1, "Foobar.baz", AF_UNSPEC, 0);
+ /* Test buffer bounds checking of tor_addr_to_str */
+ test_eq(AF_INET6, tor_addr_parse(&t1, "::")); /* 2 + \0 */
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 2, 0), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 3, 0), "::");
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 4, 1), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 5, 1), "[::]");
+
+ test_eq(AF_INET6, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 10, 0), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 11, 0), "2000::1337");
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 12, 1), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 13, 1), "[2000::1337]");
+
+ test_eq(AF_INET, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 7, 0), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 8, 0), "1.2.3.4");
+
+ test_eq(AF_INET, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 0), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 16, 0), "255.255.255.255");
+ test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 1), NULL); /* too short buf */
+ test_streq(tor_addr_to_str(buf, &t1, 16, 1), "255.255.255.255");
+
+ t1.family = AF_UNSPEC;
+ test_eq_ptr(tor_addr_to_str(buf, &t1, sizeof(buf), 0), NULL);
+
+ /* Test tor_addr_parse_PTR_name */
+ i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 0);
test_eq(0, i);
- i = tor_addr_parse_reverse_lookup_name(&t1, "Foobar.baz", AF_UNSPEC, 1);
+ i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 1);
test_eq(0, i);
- i = tor_addr_parse_reverse_lookup_name(&t1, "1.0.168.192.in-addr.arpa",
+ i = tor_addr_parse_PTR_name(&t1, "1.0.168.192.in-addr.arpa",
AF_UNSPEC, 1);
test_eq(1, i);
test_eq(tor_addr_family(&t1), AF_INET);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
test_streq(p1, "192.168.0.1");
- i = tor_addr_parse_reverse_lookup_name(&t1, "192.168.0.99", AF_UNSPEC, 0);
+ i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 0);
test_eq(0, i);
- i = tor_addr_parse_reverse_lookup_name(&t1, "192.168.0.99", AF_UNSPEC, 1);
+ i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 1);
test_eq(1, i);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
test_streq(p1, "192.168.0.99");
memset(&t1, 0, sizeof(t1));
- i = tor_addr_parse_reverse_lookup_name(&t1,
+ i = tor_addr_parse_PTR_name(&t1,
"0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
@@ -396,43 +483,91 @@ test_addr_ip6_helpers(void)
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
test_streq(p1, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]");
/* Failing cases. */
- i = tor_addr_parse_reverse_lookup_name(&t1,
+ i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1,
+ i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.f.0."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1,
+ i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f.X.0.0.0.0.9."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1, "32.1.1.in-addr.arpa",
+ i = tor_addr_parse_PTR_name(&t1, "32.1.1.in-addr.arpa",
AF_UNSPEC, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1, ".in-addr.arpa",
+ i = tor_addr_parse_PTR_name(&t1, ".in-addr.arpa",
AF_UNSPEC, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1, "1.2.3.4.5.in-addr.arpa",
+ i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
AF_UNSPEC, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1, "1.2.3.4.5.in-addr.arpa",
+ i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
AF_INET6, 0);
test_eq(i, -1);
- i = tor_addr_parse_reverse_lookup_name(&t1,
+ i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.0."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_INET, 0);
test_eq(i, -1);
+ /* === Test tor_addr_to_PTR_name */
+
+ /* Stage IPv4 addr */
+ memset(&sa_storage, 0, sizeof(sa_storage));
+ sin = (struct sockaddr_in *)&sa_storage;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = htonl(0x7f010203); /* 127.1.2.3 */
+ tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL);
+
+ /* Check IPv4 PTR - too short buffer */
+ test_eq(tor_addr_to_PTR_name(rbuf, 1, &t1), -1);
+ test_eq(tor_addr_to_PTR_name(rbuf,
+ strlen("3.2.1.127.in-addr.arpa") - 1,
+ &t1), -1);
+
+ /* Check IPv4 PTR - valid addr */
+ test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),
+ strlen("3.2.1.127.in-addr.arpa"));
+ test_streq(rbuf, "3.2.1.127.in-addr.arpa");
+
+ /* Invalid addr family */
+ t1.family = AF_UNSPEC;
+ test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), -1);
+
+ /* Stage IPv6 addr */
+ memset(&sa_storage, 0, sizeof(sa_storage));
+ sin6 = (struct sockaddr_in6 *)&sa_storage;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_addr.s6_addr[0] = 0x80; /* 8000::abcd */
+ sin6->sin6_addr.s6_addr[14] = 0xab;
+ sin6->sin6_addr.s6_addr[15] = 0xcd;
+
+ tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL);
+
+ {
+ const char* addr_PTR = "d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0."
+ "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.ip6.arpa";
+
+ /* Check IPv6 PTR - too short buffer */
+ test_eq(tor_addr_to_PTR_name(rbuf, 0, &t1), -1);
+ test_eq(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1), -1);
+
+ /* Check IPv6 PTR - valid addr */
+ test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),
+ strlen(addr_PTR));
+ test_streq(rbuf, addr_PTR);
+ }
+
/* test tor_addr_parse_mask_ports */
test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6,
0, 0, 0, 0x0000000f, 17, 47, 95);
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 121af279c7..cad8c2f556 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -7,6 +7,7 @@
#define CRYPTO_PRIVATE
#include "or.h"
#include "test.h"
+#include "aes.h"
/** Run unit tests for Diffie-Hellman functionality. */
static void
@@ -95,13 +96,16 @@ test_crypto_rng(void)
/** Run unit tests for our AES functionality */
static void
-test_crypto_aes(void)
+test_crypto_aes(void *arg)
{
char *data1 = NULL, *data2 = NULL, *data3 = NULL;
crypto_cipher_env_t *env1 = NULL, *env2 = NULL;
int i, j;
char *mem_op_hex_tmp=NULL;
+ int use_evp = !strcmp(arg,"evp");
+ evaluate_evp_for_aes(use_evp);
+
data1 = tor_malloc(1024);
data2 = tor_malloc(1024);
data3 = tor_malloc(1024);
@@ -231,7 +235,7 @@ test_crypto_sha(void)
{
crypto_digest_env_t *d1 = NULL, *d2 = NULL;
int i;
- char key[80];
+ char key[160];
char digest[32];
char data[50];
char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN];
@@ -276,6 +280,75 @@ test_crypto_sha(void)
test_streq(hex_str(digest, 20),
"AA4AE5E15272D00E95705637CE8A3B55ED402112");
+ /* Test HMAC-SHA256 with test cases from wikipedia and RFC 4231 */
+
+ /* Case empty (wikipedia) */
+ crypto_hmac_sha256(digest, "", 0, "", 0);
+ test_streq(hex_str(digest, 32),
+ "B613679A0814D9EC772F95D778C35FC5FF1697C493715653C6C712144292C5AD");
+
+ /* Case quick-brown (wikipedia) */
+ crypto_hmac_sha256(digest, "key", 3,
+ "The quick brown fox jumps over the lazy dog", 43);
+ test_streq(hex_str(digest, 32),
+ "F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8");
+
+ /* "Test Case 1" from RFC 4231 */
+ memset(key, 0x0b, 20);
+ crypto_hmac_sha256(digest, key, 20, "Hi There", 8);
+ test_memeq_hex(digest,
+ "b0344c61d8db38535ca8afceaf0bf12b"
+ "881dc200c9833da726e9376c2e32cff7");
+
+ /* "Test Case 2" from RFC 4231 */
+ memset(key, 0x0b, 20);
+ crypto_hmac_sha256(digest, "Jefe", 4, "what do ya want for nothing?", 28);
+ test_memeq_hex(digest,
+ "5bdcc146bf60754e6a042426089575c7"
+ "5a003f089d2739839dec58b964ec3843");
+
+ /* "Test case 3" from RFC 4231 */
+ memset(key, 0xaa, 20);
+ memset(data, 0xdd, 50);
+ crypto_hmac_sha256(digest, key, 20, data, 50);
+ test_memeq_hex(digest,
+ "773ea91e36800e46854db8ebd09181a7"
+ "2959098b3ef8c122d9635514ced565fe");
+
+ /* "Test case 4" from RFC 4231 */
+ base16_decode(key, 25,
+ "0102030405060708090a0b0c0d0e0f10111213141516171819", 50);
+ memset(data, 0xcd, 50);
+ crypto_hmac_sha256(digest, key, 25, data, 50);
+ test_memeq_hex(digest,
+ "82558a389a443c0ea4cc819899f2083a"
+ "85f0faa3e578f8077a2e3ff46729665b");
+
+ /* "Test case 5" from RFC 4231 */
+ memset(key, 0x0c, 20);
+ crypto_hmac_sha256(digest, key, 20, "Test With Truncation", 20);
+ test_memeq_hex(digest,
+ "a3b6167473100ee06e0c796c2955552b");
+
+ /* "Test case 6" from RFC 4231 */
+ memset(key, 0xaa, 131);
+ crypto_hmac_sha256(digest, key, 131,
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ 54);
+ test_memeq_hex(digest,
+ "60e431591ee0b67f0d8a26aacbf5b77f"
+ "8e0bc6213728c5140546040f0ee37f54");
+
+ /* "Test case 7" from RFC 4231 */
+ memset(key, 0xaa, 131);
+ crypto_hmac_sha256(digest, key, 131,
+ "This is a test using a larger than block-size key and a "
+ "larger than block-size data. The key needs to be hashed "
+ "before being used by the HMAC algorithm.", 152);
+ test_memeq_hex(digest,
+ "9b09ffa71b942fcb27635fbcd5b0e944"
+ "bfdc63644f0713938a7f51535c3a35e2");
+
/* Incremental digest code. */
d1 = crypto_new_digest_env();
test_assert(d1);
@@ -601,7 +674,7 @@ test_crypto_s2k(void)
/** Test AES-CTR encryption and decryption with IV. */
static void
-test_crypto_aes_iv(void)
+test_crypto_aes_iv(void *arg)
{
crypto_cipher_env_t *cipher;
char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2;
@@ -609,6 +682,9 @@ test_crypto_aes_iv(void)
char key1[16], key2[16];
ssize_t encrypted_size, decrypted_size;
+ int use_evp = !strcmp(arg,"evp");
+ evaluate_evp_for_aes(use_evp);
+
plain = tor_malloc(4095);
encrypted1 = tor_malloc(4095 + 1 + 16);
encrypted2 = tor_malloc(4095 + 1 + 16);
@@ -630,7 +706,7 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 4095);
- tor_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
+ tt_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
* greater than 0, but its truth is not
* obvious to all analysis tools. */
cipher = crypto_create_init_cipher(key1, 0);
@@ -639,7 +715,7 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 4095);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain, decrypted1, 4095);
/* Encrypt a second time (with a new random initialization vector). */
cipher = crypto_create_init_cipher(key1, 1);
@@ -648,14 +724,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 4095);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095,
encrypted2, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 4095);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain, decrypted2, 4095);
test_memneq(encrypted1, encrypted2, encrypted_size);
/* Decrypt with the wrong key. */
@@ -680,14 +756,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 1);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 1,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 1);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_1, decrypted1, 1);
/* Special length case: 15. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -696,14 +772,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 15);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 15,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 15);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_15, decrypted1, 15);
/* Special length case: 16. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -712,14 +788,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 16);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 16,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 16);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_16, decrypted1, 16);
/* Special length case: 17. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -728,12 +804,12 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 17);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 17,
encrypted1, encrypted_size);
test_eq(decrypted_size, 17);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_17, decrypted1, 17);
done:
@@ -782,18 +858,36 @@ test_crypto_base32_decode(void)
;
}
+static void *
+pass_data_setup_fn(const struct testcase_t *testcase)
+{
+ return testcase->setup_data;
+}
+static int
+pass_data_cleanup_fn(const struct testcase_t *testcase, void *ptr)
+{
+ (void)ptr;
+ (void)testcase;
+ return 1;
+}
+static const struct testcase_setup_t pass_data = {
+ pass_data_setup_fn, pass_data_cleanup_fn
+};
+
#define CRYPTO_LEGACY(name) \
{ #name, legacy_test_helper, 0, &legacy_setup, test_crypto_ ## name }
struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(formats),
CRYPTO_LEGACY(rng),
- CRYPTO_LEGACY(aes),
+ { "aes_AES", test_crypto_aes, TT_FORK, &pass_data, (void*)"aes" },
+ { "aes_EVP", test_crypto_aes, TT_FORK, &pass_data, (void*)"evp" },
CRYPTO_LEGACY(sha),
CRYPTO_LEGACY(pk),
CRYPTO_LEGACY(dh),
CRYPTO_LEGACY(s2k),
- CRYPTO_LEGACY(aes_iv),
+ { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"aes" },
+ { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"evp" },
CRYPTO_LEGACY(base32_decode),
END_OF_TESTCASES
};
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 8fd94289a9..5b7ce5cabe 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -7,10 +7,12 @@
#define DIRSERV_PRIVATE
#define DIRVOTE_PRIVATE
#define ROUTER_PRIVATE
+#define HIBERNATE_PRIVATE
#include "or.h"
#include "directory.h"
#include "dirserv.h"
#include "dirvote.h"
+#include "hibernate.h"
#include "networkstatus.h"
#include "router.h"
#include "routerlist.h"
@@ -85,6 +87,8 @@ test_dir_formats(void)
test_assert(pk1 && pk2 && pk3);
+ hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE);
+
get_platform_str(platform, sizeof(platform));
r1 = tor_malloc_zero(sizeof(routerinfo_t));
r1->address = tor_strdup("18.244.0.1");
@@ -298,7 +302,7 @@ test_dir_versions(void)
#define tt_versionstatus_op(vs1, op, vs2) \
tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \
- (_val1 op _val2),"%d")
+ (_val1 op _val2),"%d",TT_EXIT_TEST_FUNCTION)
#define test_v_i_o(val, ver, lst) \
tt_versionstatus_op(val, ==, tor_version_is_obsolete(ver, lst))
@@ -616,13 +620,81 @@ test_dir_param_voting(void)
test_eq(0, networkstatus_get_param(&vote4, "foobar", 0, -100, 8));
smartlist_add(votes, &vote1);
+
+ /* Do the first tests without adding all the other votes, for
+ * networks without many dirauths. */
+
+ res = dirvote_compute_params(votes, 11, 6);
+ test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 2);
+ test_streq(res, "");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 1);
+ test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99");
+ tor_free(res);
+
smartlist_add(votes, &vote2);
+
+ res = dirvote_compute_params(votes, 11, 2);
+ test_streq(res, "ab=27 abcd=20 cw=5 x-yz=-99");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 2);
+ test_streq(res, "ab=27 cw=5 x-yz=-99");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 3);
+ test_streq(res, "ab=27 cw=5 x-yz=-99");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 6);
+ test_streq(res, "");
+ tor_free(res);
+
smartlist_add(votes, &vote3);
+
+ res = dirvote_compute_params(votes, 11, 3);
+ test_streq(res, "ab=27 abcd=20 c=60 cw=50 x-yz=-9 zzzzz=101");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 3);
+ test_streq(res, "ab=27 abcd=20 cw=50 x-yz=-9");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 5);
+ test_streq(res, "cw=50 x-yz=-9");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 9);
+ test_streq(res, "cw=50 x-yz=-9");
+ tor_free(res);
+
smartlist_add(votes, &vote4);
- res = dirvote_compute_params(votes);
- test_streq(res,
- "ab=90 abcd=20 c=1 cw=50 x-yz=-9 zzzzz=101");
+ res = dirvote_compute_params(votes, 11, 4);
+ test_streq(res, "ab=90 abcd=20 c=1 cw=50 x-yz=-9 zzzzz=101");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 4);
+ test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 5);
+ test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tor_free(res);
+
+ /* Test that the special-cased "at least three dirauths voted for
+ * this param" logic works as expected. */
+ res = dirvote_compute_params(votes, 12, 6);
+ test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tor_free(res);
+
+ res = dirvote_compute_params(votes, 12, 10);
+ test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tor_free(res);
done:
tor_free(res);
@@ -803,7 +875,7 @@ test_dir_v3_networkstatus(void)
rs->or_port = 443;
rs->dir_port = 8000;
/* all flags but running cleared */
- rs->is_running = 1;
+ rs->is_flagged_running = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -818,7 +890,7 @@ test_dir_v3_networkstatus(void)
rs->addr = 0x99009901;
rs->or_port = 443;
rs->dir_port = 0;
- rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running =
+ rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -835,7 +907,8 @@ test_dir_v3_networkstatus(void)
rs->or_port = 400;
rs->dir_port = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
- rs->is_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
+ rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
+ rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -1044,7 +1117,7 @@ test_dir_v3_networkstatus(void)
"Running:Stable:V2Dir:Valid");
tor_free(cp);
cp = smartlist_join_strings(con->net_params, ":", 0, NULL);
- test_streq(cp, "bar=2000000000:circuitwindow=80:foo=660");
+ test_streq(cp, "circuitwindow=80:foo=660");
tor_free(cp);
test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/
@@ -1075,7 +1148,8 @@ test_dir_v3_networkstatus(void)
test_assert(!rs->is_fast);
test_assert(!rs->is_possible_guard);
test_assert(!rs->is_stable);
- test_assert(rs->is_running); /* If it wasn't running it wouldn't be here */
+ /* (If it wasn't running it wouldn't be here) */
+ test_assert(rs->is_flagged_running);
test_assert(!rs->is_v2_dir);
test_assert(!rs->is_valid);
test_assert(!rs->is_named);
@@ -1097,7 +1171,7 @@ test_dir_v3_networkstatus(void)
test_assert(rs->is_fast);
test_assert(rs->is_possible_guard);
test_assert(rs->is_stable);
- test_assert(rs->is_running);
+ test_assert(rs->is_flagged_running);
test_assert(rs->is_v2_dir);
test_assert(rs->is_valid);
test_assert(!rs->is_named);
@@ -1167,10 +1241,10 @@ test_dir_v3_networkstatus(void)
/* Extract a detached signature from con3. */
detached_text1 = get_detached_sigs(con3, con_md3);
- tor_assert(detached_text1);
+ tt_assert(detached_text1);
/* Try to parse it. */
dsig1 = networkstatus_parse_detached_signatures(detached_text1, NULL);
- tor_assert(dsig1);
+ tt_assert(dsig1);
/* Are parsed values as expected? */
test_eq(dsig1->valid_after, con3->valid_after);
@@ -1301,7 +1375,7 @@ test_dir_v3_networkstatus(void)
}
#define DIR_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_dir_ ## name }
+ { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name }
#define DIR(name) \
{ #name, test_dir_##name, 0, NULL, NULL }
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
new file mode 100644
index 0000000000..b807265c84
--- /dev/null
+++ b/src/test/test_microdesc.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "or.h"
+
+#include "config.h"
+#include "microdesc.h"
+
+#include "test.h"
+
+#ifdef MS_WINDOWS
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif
+
+static const char test_md1[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
+ "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
+ "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char test_md2[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
+ "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
+ "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char test_md3[] =
+ "@last-listed 2009-06-22\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
+ "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
+ "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept 1-700,800-1000\n"
+ "family nodeX nodeY nodeZ\n";
+
+static void
+test_md_cache(void *data)
+{
+ or_options_t *options = NULL;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *added = NULL, *wanted = NULL;
+ microdesc_t *md1, *md2, *md3;
+ char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
+ const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
+ time_t time1, time2, time3;
+ char *fn = NULL, *s = NULL;
+ (void)data;
+
+ options = get_options_mutable();
+ tt_assert(options);
+
+ time1 = time(NULL);
+ time2 = time(NULL) - 2*24*60*60;
+ time3 = time(NULL) - 15*24*60*60;
+
+ /* Possibly, turn this into a test setup/cleanup pair */
+ tor_free(options->DataDirectory);
+ options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
+#ifdef MS_WINDOWS
+ tt_int_op(0, ==, mkdir(options->DataDirectory));
+#else
+ tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
+#endif
+
+ tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
+
+ crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
+ crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
+ crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
+ DIGEST_SHA256);
+
+ mc = get_microdesc_cache();
+
+ added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
+ time1, NULL);
+ tt_int_op(1, ==, smartlist_len(added));
+ md1 = smartlist_get(added, 0);
+ smartlist_free(added);
+ added = NULL;
+
+ wanted = smartlist_create();
+ added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
+ time2, wanted);
+ /* Should fail, since we didn't list test_md2's digest in wanted */
+ tt_int_op(0, ==, smartlist_len(added));
+ smartlist_free(added);
+ added = NULL;
+
+ smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
+ smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
+ added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
+ time2, wanted);
+ /* Now it can work. md2 should have been added */
+ tt_int_op(1, ==, smartlist_len(added));
+ md2 = smartlist_get(added, 0);
+ /* And it should have gotten removed from 'wanted' */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
+ smartlist_free(added);
+ added = NULL;
+
+ added = microdescs_add_to_cache(mc, test_md3, NULL,
+ SAVED_NOWHERE, 0, -1, NULL);
+ /* Must fail, since SAVED_NOWHERE precludes annotations */
+ tt_int_op(0, ==, smartlist_len(added));
+ smartlist_free(added);
+ added = NULL;
+
+ added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
+ SAVED_NOWHERE, 0, time3, NULL);
+ /* Now it can work */
+ tt_int_op(1, ==, smartlist_len(added));
+ md3 = smartlist_get(added, 0);
+ smartlist_free(added);
+ added = NULL;
+
+ /* Okay. We added 1...3. Let's poke them to see how they look, and make
+ * sure they're really in the journal. */
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+
+ tt_int_op(md1->last_listed, ==, time1);
+ tt_int_op(md2->last_listed, ==, time2);
+ tt_int_op(md3->last_listed, ==, time3);
+
+ tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL);
+ tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL);
+ tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
+
+ tt_int_op(md1->bodylen, ==, strlen(test_md1));
+ tt_int_op(md2->bodylen, ==, strlen(test_md2));
+ tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
+ test_mem_op(md1->body, ==, test_md1, strlen(test_md1));
+ test_mem_op(md2->body, ==, test_md2, strlen(test_md2));
+ test_mem_op(md3->body, ==, test_md3_noannotation,
+ strlen(test_md3_noannotation));
+
+ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
+ options->DataDirectory);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ tt_assert(s);
+ test_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
+ test_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
+ test_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
+
+ tt_ptr_op(md1->family, ==, NULL);
+ tt_ptr_op(md3->family, !=, NULL);
+ tt_int_op(smartlist_len(md3->family), ==, 3);
+ tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX");
+
+ /* Now rebuild the cache! */
+ tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
+
+ tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
+ tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
+ tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
+
+ /* The journal should be empty now */
+ tor_free(s);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ tt_str_op(s, ==, "");
+ tor_free(s);
+ tor_free(fn);
+
+ /* read the cache. */
+ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
+ options->DataDirectory);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+
+ /* Okay, now we are going to forget about the cache entirely, and reload it
+ * from the disk. */
+ microdesc_free_all();
+ mc = get_microdesc_cache();
+ md1 = microdesc_cache_lookup_by_digest256(mc, d1);
+ md2 = microdesc_cache_lookup_by_digest256(mc, d2);
+ md3 = microdesc_cache_lookup_by_digest256(mc, d3);
+ test_assert(md1);
+ test_assert(md2);
+ test_assert(md3);
+ test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+
+ tt_int_op(md1->last_listed, ==, time1);
+ tt_int_op(md2->last_listed, ==, time2);
+ tt_int_op(md3->last_listed, ==, time3);
+
+ /* Okay, now we are going to clear out everything older than a week old.
+ * In practice, that means md3 */
+ microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+ md3 = NULL; /* it's history now! */
+
+ /* rebuild again, make sure it stays gone. */
+ microdesc_cache_rebuild(mc, 1);
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+
+ done:
+ if (options)
+ tor_free(options->DataDirectory);
+ microdesc_free_all();
+
+ smartlist_free(added);
+ if (wanted)
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+ tor_free(s);
+ tor_free(fn);
+}
+
+struct testcase_t microdesc_tests[] = {
+ { "cache", test_md_cache, TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
new file mode 100644
index 0000000000..45f441106e
--- /dev/null
+++ b/src/test/test_pt.c
@@ -0,0 +1,147 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#define PT_PRIVATE
+#include "or.h"
+#include "transports.h"
+#include "circuitbuild.h"
+#include "test.h"
+
+static void
+reset_mp(managed_proxy_t *mp)
+{
+ mp->conf_state = PT_PROTO_LAUNCHED;
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+ smartlist_clear(mp->transports);
+}
+
+static void
+test_pt_parsing(void)
+{
+ char line[200];
+
+ managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t));
+ mp->conf_state = PT_PROTO_INFANT;
+ mp->transports = smartlist_create();
+
+ /* incomplete cmethod */
+ strcpy(line,"CMETHOD trebuchet");
+ test_assert(parse_cmethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* wrong proxy type */
+ strcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999");
+ test_assert(parse_cmethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* wrong addrport */
+ strcpy(line,"CMETHOD trebuchet socks4 abcd");
+ test_assert(parse_cmethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* correct line */
+ strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999");
+ test_assert(parse_cmethod_line(line, mp) == 0);
+ test_assert(smartlist_len(mp->transports));
+
+ reset_mp(mp);
+
+ /* incomplete smethod */
+ strcpy(line,"SMETHOD trebuchet");
+ test_assert(parse_smethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* wrong addr type */
+ strcpy(line,"SMETHOD trebuchet abcd");
+ test_assert(parse_smethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* cowwect */
+ strcpy(line,"SMETHOD trebuchy 127.0.0.1:1999");
+ test_assert(parse_smethod_line(line, mp) == 0);
+
+ reset_mp(mp);
+
+ /* unsupported version */
+ strcpy(line,"VERSION 666");
+ test_assert(parse_version(line, mp) < 0);
+
+ /* incomplete VERSION */
+ strcpy(line,"VERSION ");
+ test_assert(parse_version(line, mp) < 0);
+
+ /* correct VERSION */
+ strcpy(line,"VERSION 1");
+ test_assert(parse_version(line, mp) == 0);
+
+ done:
+ tor_free(mp);
+}
+
+static void
+test_pt_protocol(void)
+{
+ char line[200];
+
+ managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
+ mp->conf_state = PT_PROTO_LAUNCHED;
+ mp->transports = smartlist_create();
+
+ /* various wrong protocol runs: */
+
+ strcpy(line, "TEST TEST");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_BROKEN);
+
+ reset_mp(mp);
+
+ strcpy(line,"VERSION 1");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+
+ strcpy(line,"VERSION 1");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_BROKEN);
+
+ reset_mp(mp);
+
+ strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_BROKEN);
+
+ reset_mp(mp);
+
+ /* correct protocol run: */
+ strcpy(line,"VERSION 1");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+
+ strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+
+ strcpy(line,"CMETHODS DONE");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_CONFIGURED);
+
+ done:
+ tor_free(mp);
+}
+
+#define PT_LEGACY(name) \
+ { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name }
+
+struct testcase_t pt_tests[] = {
+ PT_LEGACY(parsing),
+ PT_LEGACY(protocol),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 23cd059cf7..93f11cd208 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -6,6 +6,7 @@
#include "orconfig.h"
#define CONTROL_PRIVATE
#define MEMPOOL_PRIVATE
+#define UTIL_PRIVATE
#include "or.h"
#include "config.h"
#include "control.h"
@@ -362,20 +363,10 @@ test_util_strmisc(void)
test_assert(!tor_strisprint(cp));
tor_free(cp);
- /* Test eat_whitespace. */
- {
- const char *s = " \n a";
- test_eq_ptr(eat_whitespace(s), s+4);
- s = "abcd";
- test_eq_ptr(eat_whitespace(s), s);
- s = "#xyz\nab";
- test_eq_ptr(eat_whitespace(s), s+5);
- }
-
/* Test memmem and memstr */
{
const char *haystack = "abcde";
- tor_assert(!tor_memmem(haystack, 5, "ef", 2));
+ tt_assert(!tor_memmem(haystack, 5, "ef", 2));
test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
haystack = "ababcad";
@@ -408,6 +399,20 @@ test_util_strmisc(void)
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_free(sl);
}
+
+ /* Test hex_str */
+ {
+ char binary_data[64];
+ size_t i;
+ for (i = 0; i < sizeof(binary_data); ++i)
+ binary_data[i] = i;
+ test_streq(hex_str(binary_data, 0), "");
+ test_streq(hex_str(binary_data, 1), "00");
+ test_streq(hex_str(binary_data, 17), "000102030405060708090A0B0C0D0E0F10");
+ test_streq(hex_str(binary_data, 32),
+ "000102030405060708090A0B0C0D0E0F"
+ "101112131415161718191A1B1C1D1E1F");
+ }
done:
;
}
@@ -639,26 +644,26 @@ test_util_gzip(void)
tor_strdup("String with low redundancy that won't be compressed much.");
test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
ZLIB_METHOD));
- tor_assert(len1>16);
+ tt_assert(len1>16);
/* when we allow an incomplete string, we should succeed.*/
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
ZLIB_METHOD, 0, LOG_INFO));
buf3[len2]='\0';
- tor_assert(len2 > 5);
- tor_assert(!strcmpstart(buf1, buf3));
+ tt_assert(len2 > 5);
+ tt_assert(!strcmpstart(buf1, buf3));
/* when we demand a complete string, this must fail. */
tor_free(buf3);
- tor_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
+ tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
ZLIB_METHOD, 1, LOG_INFO));
- tor_assert(!buf3);
+ tt_assert(!buf3);
/* Now, try streaming compression. */
tor_free(buf1);
tor_free(buf2);
tor_free(buf3);
state = tor_zlib_new(1, ZLIB_METHOD);
- tor_assert(state);
+ tt_assert(state);
cp1 = buf1 = tor_malloc(1024);
len1 = 1024;
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
@@ -675,7 +680,7 @@ test_util_gzip(void)
test_eq(len2, 0);
test_assert(cp1 > cp2); /* Make sure we really added something. */
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
ZLIB_METHOD, 1, LOG_WARN));
test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
@@ -832,6 +837,18 @@ test_util_sscanf(void)
test_eq(u2, 3u);
test_eq(u3, 99u);
+ /* %x should work. */
+ r = tor_sscanf("1234 02aBcdEf", "%x %x", &u1, &u2);
+ test_eq(r, 2);
+ test_eq(u1, 0x1234);
+ test_eq(u2, 0x2ABCDEF);
+ /* Width works on %x */
+ r = tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3);
+ test_eq(r, 3);
+ test_eq(u1, 0xf00d);
+ test_eq(u2, 0xcafe);
+ test_eq(u3, 444);
+
r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/
test_eq(r, 1);
test_eq(u1, 99);
@@ -1239,6 +1256,446 @@ test_util_load_win_lib(void *ptr)
#endif
static void
+clear_hex_errno(char *hex_errno)
+{
+ memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
+}
+
+static void
+test_util_exit_status(void *ptr)
+{
+ /* Leave an extra byte for a \0 so we can do string comparison */
+ char hex_errno[HEX_ERRNO_SIZE + 1];
+
+ (void)ptr;
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0, 0, hex_errno);
+ tt_str_op(hex_errno, ==, " 0/0\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
+ tt_str_op(hex_errno, ==, " 0/7FFFFFFF\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0xFF, -0x80000000, hex_errno);
+ tt_str_op(hex_errno, ==, "FF/-80000000\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0x7F, 0, hex_errno);
+ tt_str_op(hex_errno, ==, " 7F/0\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0x08, -0x242, hex_errno);
+ tt_str_op(hex_errno, ==, " 8/-242\n");
+
+ done:
+ ;
+}
+
+#ifndef MS_WINDOWS
+/** Check that fgets waits until a full line, and not return a partial line, on
+ * a EAGAIN with a non-blocking pipe */
+static void
+test_util_fgets_eagain(void *ptr)
+{
+ int test_pipe[2] = {-1, -1};
+ int retval;
+ ssize_t retlen;
+ char *retptr;
+ FILE *test_stream = NULL;
+ char buf[10];
+
+ (void)ptr;
+
+ /* Set up a pipe to test on */
+ retval = pipe(test_pipe);
+ tt_int_op(retval, >=, 0);
+
+ /* Set up the read-end to be non-blocking */
+ retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
+ tt_int_op(retval, >=, 0);
+
+ /* Open it as a stdio stream */
+ test_stream = fdopen(test_pipe[0], "r");
+ tt_ptr_op(test_stream, !=, NULL);
+
+ /* Send in a partial line */
+ retlen = write(test_pipe[1], "A", 1);
+ tt_int_op(retlen, ==, 1);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_want(retptr == NULL);
+ tt_int_op(errno, ==, EAGAIN);
+
+ /* Send in the rest */
+ retlen = write(test_pipe[1], "B\n", 2);
+ tt_int_op(retlen, ==, 2);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "AB\n");
+
+ /* Send in a full line */
+ retlen = write(test_pipe[1], "CD\n", 3);
+ tt_int_op(retlen, ==, 3);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "CD\n");
+
+ /* Send in a partial line */
+ retlen = write(test_pipe[1], "E", 1);
+ tt_int_op(retlen, ==, 1);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, NULL);
+ tt_int_op(errno, ==, EAGAIN);
+
+ /* Send in the rest */
+ retlen = write(test_pipe[1], "F\n", 2);
+ tt_int_op(retlen, ==, 2);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "EF\n");
+
+ /* Send in a full line and close */
+ retlen = write(test_pipe[1], "GH", 2);
+ tt_int_op(retlen, ==, 2);
+ retval = close(test_pipe[1]);
+ test_pipe[1] = -1;
+ tt_int_op(retval, ==, 0);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "GH");
+
+ /* Check for EOF */
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, NULL);
+ tt_int_op(feof(test_stream), >, 0);
+
+ done:
+ if (test_stream != NULL)
+ fclose(test_stream);
+ if (test_pipe[0] != -1)
+ close(test_pipe[0]);
+ if (test_pipe[1] != -1)
+ close(test_pipe[1]);
+}
+#endif
+
+/** Helper function for testing tor_spawn_background */
+static void
+run_util_spawn_background(const char *argv[], const char *expected_out,
+ const char *expected_err, int expected_exit,
+ int expected_status)
+{
+ int retval, exit_code;
+ ssize_t pos;
+ process_handle_t *process_handle=NULL;
+ char stdout_buf[100], stderr_buf[100];
+ int status;
+
+ /* Start the program */
+#ifdef MS_WINDOWS
+ status = tor_spawn_background(NULL, argv, NULL, &process_handle);
+#else
+ status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
+#endif
+
+ tt_int_op(status, ==, expected_status);
+ if (status == PROCESS_STATUS_ERROR)
+ return;
+
+ tt_assert(process_handle != NULL);
+ tt_int_op(process_handle->status, ==, expected_status);
+
+ tt_int_op(process_handle->stdout_pipe, >, 0);
+ tt_int_op(process_handle->stderr_pipe, >, 0);
+
+ /* Check stdout */
+ pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
+ sizeof(stdout_buf) - 1);
+ tt_assert(pos >= 0);
+ stdout_buf[pos] = '\0';
+ tt_str_op(stdout_buf, ==, expected_out);
+ tt_int_op(pos, ==, strlen(expected_out));
+
+ /* Check it terminated correctly */
+ retval = tor_get_exit_code(process_handle, 1, &exit_code);
+ tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
+ tt_int_op(exit_code, ==, expected_exit);
+ // TODO: Make test-child exit with something other than 0
+
+ /* Check stderr */
+ pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
+ sizeof(stderr_buf) - 1);
+ tt_assert(pos >= 0);
+ stderr_buf[pos] = '\0';
+ tt_str_op(stderr_buf, ==, expected_err);
+ tt_int_op(pos, ==, strlen(expected_err));
+
+ done:
+ if (process_handle)
+ tor_process_handle_destroy(process_handle, 1);
+}
+
+/** Check that we can launch a process and read the output */
+static void
+test_util_spawn_background_ok(void *ptr)
+{
+#ifdef MS_WINDOWS
+ const char *argv[] = {"test-child.exe", "--test", NULL};
+ const char *expected_out = "OUT\r\n--test\r\nSLEEPING\r\nDONE\r\n";
+ const char *expected_err = "ERR\r\n";
+#else
+ const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
+ const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
+ const char *expected_err = "ERR\n";
+#endif
+
+ (void)ptr;
+
+ run_util_spawn_background(argv, expected_out, expected_err, 0,
+ PROCESS_STATUS_RUNNING);
+}
+
+/** Check that failing to find the executable works as expected */
+static void
+test_util_spawn_background_fail(void *ptr)
+{
+#ifdef MS_WINDOWS
+ const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
+ const char *expected_out = "ERR: Failed to spawn background process "
+ "- code 9/2\n";
+ const char *expected_err = "";
+ const int expected_status = PROCESS_STATUS_ERROR;
+#else
+ const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
+ const char *expected_out = "ERR: Failed to spawn background process "
+ "- code 9/2\n";
+ const char *expected_err = "";
+ /* TODO: Once we can signal failure to exec, set this to be
+ * PROCESS_STATUS_ERROR */
+ const int expected_status = PROCESS_STATUS_RUNNING;
+#endif
+
+ (void)ptr;
+
+ run_util_spawn_background(argv, expected_out, expected_err, 255,
+ expected_status);
+}
+
+/** Test that reading from a handle returns a partial read rather than
+ * blocking */
+static void
+test_util_spawn_background_partial_read(void *ptr)
+{
+ const int expected_exit = 0;
+ const int expected_status = PROCESS_STATUS_RUNNING;
+
+ int retval, exit_code;
+ ssize_t pos = -1;
+ process_handle_t *process_handle=NULL;
+ int status;
+ char stdout_buf[100], stderr_buf[100];
+#ifdef MS_WINDOWS
+ const char *argv[] = {"test-child.exe", "--test", NULL};
+ const char *expected_out[] = { "OUT\r\n--test\r\nSLEEPING\r\n",
+ "DONE\r\n",
+ NULL };
+ const char *expected_err = "ERR\r\n";
+#else
+ const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
+ const char *expected_out[] = { "OUT\n--test\nSLEEPING\n",
+ "DONE\n",
+ NULL };
+ const char *expected_err = "ERR\n";
+ int eof = 0;
+#endif
+ int expected_out_ctr;
+ (void)ptr;
+
+ /* Start the program */
+#ifdef MS_WINDOWS
+ status = tor_spawn_background(NULL, argv, NULL, &process_handle);
+#else
+ status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
+#endif
+ tt_int_op(status, ==, expected_status);
+ tt_assert(process_handle);
+ tt_int_op(process_handle->status, ==, expected_status);
+
+ /* Check stdout */
+ for (expected_out_ctr = 0; expected_out[expected_out_ctr] != NULL;) {
+#ifdef MS_WINDOWS
+ pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
+ sizeof(stdout_buf) - 1, NULL);
+#else
+ /* Check that we didn't read the end of file last time */
+ tt_assert(!eof);
+ pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
+ sizeof(stdout_buf) - 1, NULL, &eof);
+#endif
+ log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
+
+ /* We would have blocked, keep on trying */
+ if (0 == pos)
+ continue;
+
+ tt_int_op(pos, >, 0);
+ stdout_buf[pos] = '\0';
+ tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]);
+ tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr]));
+ expected_out_ctr++;
+ }
+
+ /* The process should have exited without writing more */
+#ifdef MS_WINDOWS
+ pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
+ sizeof(stdout_buf) - 1,
+ process_handle);
+ tt_int_op(pos, ==, 0);
+#else
+ if (!eof) {
+ /* We should have got all the data, but maybe not the EOF flag */
+ pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
+ sizeof(stdout_buf) - 1,
+ process_handle, &eof);
+ tt_int_op(pos, ==, 0);
+ tt_assert(eof);
+ }
+ /* Otherwise, we got the EOF on the last read */
+#endif
+
+ /* Check it terminated correctly */
+ retval = tor_get_exit_code(process_handle, 1, &exit_code);
+ tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
+ tt_int_op(exit_code, ==, expected_exit);
+
+ // TODO: Make test-child exit with something other than 0
+
+ /* Check stderr */
+ pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
+ sizeof(stderr_buf) - 1);
+ tt_assert(pos >= 0);
+ stderr_buf[pos] = '\0';
+ tt_str_op(stderr_buf, ==, expected_err);
+ tt_int_op(pos, ==, strlen(expected_err));
+
+ done:
+ tor_process_handle_destroy(process_handle, 1);
+}
+
+/**
+ * Test that we can properly format q Windows command line
+ */
+static void
+test_util_join_win_cmdline(void *ptr)
+{
+ /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
+ * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
+ * will try to only generate simple cases for the child process to parse;
+ * i.e. we never embed quoted strings in arguments. */
+
+ const char *argvs[][4] = {
+ {"a", "bb", "CCC", NULL}, // Normal
+ {NULL, NULL, NULL, NULL}, // Empty argument list
+ {"", NULL, NULL, NULL}, // Empty argument
+ {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
+ {"a\tbc", "dd dd", "E", NULL}, // Whitespace
+ {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
+ {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
+ {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
+ { NULL } // Terminator
+ };
+
+ const char *cmdlines[] = {
+ "a bb CCC",
+ "",
+ "\"\"",
+ "\\\"a b\\\"b CCC\\\"",
+ "\"a\tbc\" \"dd dd\" E",
+ "a\\\\\\b \"de fg\" H",
+ "a\\\\\\\"b \\c D\\",
+ "\"a\\\\b c\" d E",
+ NULL // Terminator
+ };
+
+ int i;
+ char *joined_argv;
+
+ (void)ptr;
+
+ for (i=0; cmdlines[i]!=NULL; i++) {
+ log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
+ joined_argv = tor_join_win_cmdline(argvs[i]);
+ tt_str_op(joined_argv, ==, cmdlines[i]);
+ tor_free(joined_argv);
+ }
+
+ done:
+ ;
+}
+
+#define MAX_SPLIT_LINE_COUNT 3
+struct split_lines_test_t {
+ const char *orig_line; // Line to be split (may contain \0's)
+ int orig_length; // Length of orig_line
+ const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
+};
+
+/**
+ * Test that we properly split a buffer into lines
+ */
+static void
+test_util_split_lines(void *ptr)
+{
+ /* Test cases. orig_line of last test case must be NULL.
+ * The last element of split_line[i] must be NULL. */
+ struct split_lines_test_t tests[] = {
+ {"", 0, {NULL}},
+ {"foo", 3, {"foo", NULL}},
+ {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
+ {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
+ {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
+ {NULL, 0, { NULL }}
+ };
+
+ int i, j;
+ char *orig_line;
+ smartlist_t *sl;
+
+ (void)ptr;
+
+ for (i=0; tests[i].orig_line; i++) {
+ sl = smartlist_create();
+ /* Allocate space for string and trailing NULL */
+ orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
+ tor_split_lines(sl, orig_line, tests[i].orig_length);
+
+ j = 0;
+ log_info(LD_GENERAL, "Splitting test %d of length %d",
+ i, tests[i].orig_length);
+ SMARTLIST_FOREACH(sl, const char *, line,
+ {
+ /* Check we have not got too many lines */
+ tt_int_op(j, <, MAX_SPLIT_LINE_COUNT);
+ /* Check that there actually should be a line here */
+ tt_assert(tests[i].split_line[j] != NULL);
+ log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
+ j, i, tests[i].split_line[j]);
+ /* Check that the line is as expected */
+ tt_str_op(tests[i].split_line[j], ==, line);
+ j++;
+ });
+ /* Check that we didn't miss some lines */
+ tt_assert(tests[i].split_line[j] == NULL);
+ tor_free(orig_line);
+ smartlist_free(sl);
+ }
+
+ done:
+ ;
+}
+
+static void
test_util_di_ops(void)
{
#define LT -1
@@ -1291,6 +1748,92 @@ test_util_di_ops(void)
;
}
+/**
+ * Test counting high bits
+ */
+static void
+test_util_n_bits_set(void *ptr)
+{
+ (void)ptr;
+ test_eq(n_bits_set_u8(0), 0);
+ test_eq(n_bits_set_u8(1), 1);
+ test_eq(n_bits_set_u8(129), 2);
+ test_eq(n_bits_set_u8(255), 8);
+ done:
+ ;
+}
+
+/**
+ * Test LHS whitespace (and comment) eater
+ */
+static void
+test_util_eat_whitespace(void *ptr)
+{
+ const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
+ char str[80];
+ size_t i;
+
+ (void)ptr;
+
+ /* Try one leading ws */
+ strcpy(str, "fuubaar");
+ for (i = 0; i < sizeof(ws); ++i) {
+ str[0] = ws[i];
+ test_streq(eat_whitespace(str), str + 1);
+ test_streq(eat_whitespace_eos(str, str + strlen(str)), str + 1);
+ test_streq(eat_whitespace_eos_no_nl(str, str + strlen(str)), str + 1);
+ test_streq(eat_whitespace_no_nl(str), str + 1);
+ }
+ str[0] = '\n';
+ test_streq(eat_whitespace(str), str + 1);
+ test_streq(eat_whitespace_eos(str, str + strlen(str)), str + 1);
+
+ /* Empty string */
+ strcpy(str, "");
+ test_eq_ptr(eat_whitespace(str), str);
+ test_eq_ptr(eat_whitespace_eos(str, str), str);
+ test_eq_ptr(eat_whitespace_eos_no_nl(str, str), str);
+ test_eq_ptr(eat_whitespace_no_nl(str), str);
+
+ /* Only ws */
+ strcpy(str, " \t\r\n");
+ test_eq_ptr(eat_whitespace(str), str + strlen(str));
+ test_eq_ptr(eat_whitespace_eos(str, str + strlen(str)), str + strlen(str));
+
+ strcpy(str, " \t\r ");
+ test_eq_ptr(eat_whitespace_no_nl(str), str + strlen(str));
+ test_eq_ptr(eat_whitespace_eos_no_nl(str, str + strlen(str)),
+ str + strlen(str));
+
+ /* Multiple ws */
+ strcpy(str, "fuubaar");
+ for (i = 0; i < sizeof(ws); ++i)
+ str[i] = ws[i];
+ test_streq(eat_whitespace(str), str + sizeof(ws));
+ test_streq(eat_whitespace_eos(str, str + strlen(str)), str + sizeof(ws));
+ test_streq(eat_whitespace_no_nl(str), str + sizeof(ws));
+ test_streq(eat_whitespace_eos_no_nl(str, str + strlen(str)),
+ str + sizeof(ws));
+
+ /* Eat comment */
+ strcpy(str, "# Comment \n No Comment");
+ test_streq(eat_whitespace(str), "No Comment");
+ test_streq(eat_whitespace_eos(str, str + strlen(str)), "No Comment");
+
+ /* Eat comment & ws mix */
+ strcpy(str, " # \t Comment \n\t\nNo Comment");
+ test_streq(eat_whitespace(str), "No Comment");
+ test_streq(eat_whitespace_eos(str, str + strlen(str)), "No Comment");
+
+ /* Eat entire comment */
+ strcpy(str, "#Comment");
+ test_eq_ptr(eat_whitespace(str), str + strlen(str));
+ test_eq_ptr(eat_whitespace_eos(str, str + strlen(str)), str + strlen(str));
+
+ done:
+ ;
+}
+
#define UTIL_LEGACY(name) \
{ #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
@@ -1319,6 +1862,17 @@ struct testcase_t util_tests[] = {
#ifdef MS_WINDOWS
UTIL_TEST(load_win_lib, 0),
#endif
+ UTIL_TEST(exit_status, 0),
+#ifndef MS_WINDOWS
+ UTIL_TEST(fgets_eagain, TT_SKIP),
+#endif
+ UTIL_TEST(spawn_background_ok, 0),
+ UTIL_TEST(spawn_background_fail, 0),
+ UTIL_TEST(spawn_background_partial_read, 0),
+ UTIL_TEST(join_win_cmdline, 0),
+ UTIL_TEST(split_lines, 0),
+ UTIL_TEST(n_bits_set, 0),
+ UTIL_TEST(eat_whitespace, 0),
END_OF_TESTCASES
};
diff --git a/src/test/tinytest.c b/src/test/tinytest.c
index 11ffc2fe56..8caa4f5453 100644
--- a/src/test/tinytest.c
+++ b/src/test/tinytest.c
@@ -28,7 +28,11 @@
#include <string.h>
#include <assert.h>
-#ifdef WIN32
+#ifdef TINYTEST_LOCAL
+#include "tinytest_local.h"
+#endif
+
+#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
@@ -40,9 +44,6 @@
#define __attribute__(x)
#endif
-#ifdef TINYTEST_LOCAL
-#include "tinytest_local.h"
-#endif
#include "tinytest.h"
#include "tinytest_macros.h"
@@ -64,7 +65,7 @@ const char *cur_test_prefix = NULL; /**< prefix of the current test group */
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL;
-#ifdef WIN32
+#ifdef _WIN32
/** Pointer to argv[0] for win32. */
static const char *commandname = NULL;
#endif
@@ -103,7 +104,7 @@ static enum outcome
_testcase_run_forked(const struct testgroup_t *group,
const struct testcase_t *testcase)
{
-#ifdef WIN32
+#ifdef _WIN32
/* Fork? On Win32? How primitive! We'll do what the smart kids do:
we'll invoke our own exe (whose name we recall from the command
line) with a command line that tells it to run just the test we
@@ -174,6 +175,7 @@ _testcase_run_forked(const struct testgroup_t *group,
exit(1);
}
exit(0);
+ return FAIL; /* unreachable */
} else {
/* parent */
int status, r;
@@ -239,6 +241,7 @@ testcase_run_one(const struct testgroup_t *group,
if (opt_forked) {
exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
+ return 1; /* unreachable */
} else {
return (int)outcome;
}
@@ -287,7 +290,7 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
{
int i, j, n=0;
-#ifdef WIN32
+#ifdef _WIN32
commandname = v[0];
#endif
for (i=1; i<c; ++i) {
diff --git a/src/test/tinytest_demo.c b/src/test/tinytest_demo.c
index 4d2f588435..98cb773d1a 100644
--- a/src/test/tinytest_demo.c
+++ b/src/test/tinytest_demo.c
@@ -1,4 +1,4 @@
-/* tinytest_demo.c -- Copyright 2009 Nick Mathewson
+/* tinytest_demo.c -- Copyright 2009-2010 Nick Mathewson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -53,7 +53,7 @@ test_strcmp(void *data)
}
/* Pretty often, calling tt_abort_msg to indicate failure is more
- heavy-weight than you want. Instead, just say: */
+ heavy-weight than you want. Instead, just say: */
tt_assert(strcmp("testcase", "testcase") == 0);
/* Occasionally, you don't want to stop the current testcase just
@@ -91,7 +91,7 @@ test_strcmp(void *data)
/* First you declare a type to hold the environment info, and functions to
set it up and tear it down. */
struct data_buffer {
- /* We're just going to have couple of character buffer. Using
+ /* We're just going to have couple of character buffer. Using
setup/teardown functions is probably overkill for this case.
You could also do file descriptors, complicated handles, temporary
@@ -164,7 +164,7 @@ test_memcpy(void *ptr)
/* ============================================================ */
-/* Now we need to make sure that our tests get invoked. First, you take
+/* Now we need to make sure that our tests get invoked. First, you take
a bunch of related tests and put them into an array of struct testcase_t.
*/
@@ -189,15 +189,15 @@ struct testgroup_t groups[] = {
/* Every group has a 'prefix', and an array of tests. That's it. */
{ "demo/", demo_tests },
- END_OF_GROUPS
+ END_OF_GROUPS
};
int
main(int c, const char **v)
{
- /* Finally, just call tinytest_main(). It lets you specify verbose
- or quiet output with --verbose and --quiet. You can list
+ /* Finally, just call tinytest_main(). It lets you specify verbose
+ or quiet output with --verbose and --quiet. You can list
specific tests:
tinytest-demo demo/memcpy
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index a7fa64a824..032393ccf7 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -90,10 +90,10 @@
TT_STMT_BEGIN \
if (!(b)) { \
_tinytest_set_test_failed(); \
- TT_GRIPE((msg)); \
+ TT_GRIPE(("%s",msg)); \
fail; \
} else { \
- TT_BLATHER((msg)); \
+ TT_BLATHER(("%s",msg)); \
} \
TT_STMT_END
@@ -111,7 +111,7 @@
#define tt_assert(b) tt_assert_msg((b), "assert("#b")")
#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
- setup_block,cleanup_block) \
+ setup_block,cleanup_block,die_on_fail) \
TT_STMT_BEGIN \
type _val1 = (type)(a); \
type _val2 = (type)(b); \
@@ -135,33 +135,50 @@
cleanup_block; \
if (!_tt_status) { \
_tinytest_set_test_failed(); \
- TT_EXIT_TEST_FUNCTION; \
+ die_on_fail ; \
} \
} \
TT_STMT_END
-#define tt_assert_test_type(a,b,str_test,type,test,fmt) \
+#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \
tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \
- {_print=_value;},{})
+ {_print=_value;},{},die_on_fail)
/* Helper: assert that a op b, when cast to type. Format the values with
* printf format fmt on failure. */
#define tt_assert_op_type(a,op,b,type,fmt) \
- tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt)
+ tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt, \
+ TT_EXIT_TEST_FUNCTION)
#define tt_int_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld")
+ tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2), \
+ "%ld",TT_EXIT_TEST_FUNCTION)
#define tt_uint_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
- (_val1 op _val2),"%lu")
+ (_val1 op _val2),"%lu",TT_EXIT_TEST_FUNCTION)
#define tt_ptr_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
- (_val1 op _val2),"%p")
+ (_val1 op _val2),"%p",TT_EXIT_TEST_FUNCTION)
#define tt_str_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
- (strcmp(_val1,_val2) op 0),"<%s>")
+ (strcmp(_val1,_val2) op 0),"<%s>",TT_EXIT_TEST_FUNCTION)
+
+#define tt_want_int_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld",(void)0)
+
+#define tt_want_uint_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
+ (_val1 op _val2),"%lu",(void)0)
+
+#define tt_want_ptr_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
+ (_val1 op _val2),"%p",(void)0)
+
+#define tt_want_str_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
+ (strcmp(_val1,_val2) op 0),"<%s>",(void)0)
#endif
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 1bb5076849..a9a619757a 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -2,17 +2,19 @@ bin_PROGRAMS = tor-resolve tor-gencert
noinst_PROGRAMS = tor-checkkey
tor_resolve_SOURCES = tor-resolve.c
-tor_resolve_LDFLAGS = @TOR_LDFLAGS_libevent@
-tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIBEVENT_LIBS@ @TOR_LIB_WS32@
+tor_resolve_LDFLAGS =
+tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIB_WS32@
tor_gencert_SOURCES = tor-gencert.c
-tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
+tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
tor_gencert_LDADD = ../common/libor.a ../common/libor-crypto.a \
- -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ -lm @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
tor_checkkey_SOURCES = tor-checkkey.c
-tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
+tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
tor_checkkey_LDADD = ../common/libor.a ../common/libor-crypto.a \
- -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ -lm @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+SUBDIRS = tor-fw-helper
+DIST_SUBDIRS = tor-fw-helper
+
diff --git a/src/tools/tor-fw-helper/Makefile.am b/src/tools/tor-fw-helper/Makefile.am
new file mode 100644
index 0000000000..8f64ad2ba3
--- /dev/null
+++ b/src/tools/tor-fw-helper/Makefile.am
@@ -0,0 +1,38 @@
+if USE_FW_HELPER
+bin_PROGRAMS = tor-fw-helper
+else
+bin_PROGRAMS =
+endif
+
+tor_fw_helper_SOURCES = \
+ tor-fw-helper.c \
+ tor-fw-helper-natpmp.c \
+ tor-fw-helper-upnp.c
+noinst_HEADERS = \
+ tor-fw-helper.h \
+ tor-fw-helper-natpmp.h \
+ tor-fw-helper-upnp.h
+
+if NAT_PMP
+nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@
+nat_pmp_ldadd = -lnatpmp
+nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@
+else
+nat_pmp_ldflags =
+nat_pmp_ldadd =
+nat_pmp_cppflags =
+endif
+
+if MINIUPNPC
+miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@
+miniupnpc_ldadd = -lminiupnpc -lm @TOR_LIB_IPHLPAPI@
+miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@
+else
+miniupnpc_ldflags =
+miniupnpc_ldadd =
+miniupnpc_cppflags =
+endif
+
+tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags)
+tor_fw_helper_LDADD = ../../common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) @TOR_LIB_WS32@
+tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags)
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
new file mode 100644
index 0000000000..f9d5d0d586
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-natpmp.c
+ * \brief The implementation of our NAT-PMP firewall helper.
+ **/
+
+#include "orconfig.h"
+#ifdef NAT_PMP
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+// debugging stuff
+#include <assert.h>
+
+#include "tor-fw-helper.h"
+#include "tor-fw-helper-natpmp.h"
+
+/** This hooks NAT-PMP into our multi-backend API. */
+static tor_fw_backend_t tor_natpmp_backend = {
+ "natpmp",
+ sizeof(struct natpmp_state_t),
+ tor_natpmp_init,
+ tor_natpmp_cleanup,
+ tor_natpmp_fetch_public_ip,
+ tor_natpmp_add_tcp_mapping
+};
+
+/** Return the backend for NAT-PMP. */
+const tor_fw_backend_t *
+tor_fw_get_natpmp_backend(void)
+{
+ return &tor_natpmp_backend;
+}
+
+/** Initialize the NAT-PMP backend and store the results in
+ * <b>backend_state</b>.*/
+int
+tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+
+ memset(&(state->natpmp), 0, sizeof(natpmp_t));
+ memset(&(state->response), 0, sizeof(natpmpresp_t));
+ state->init = 0;
+ state->protocol = NATPMP_PROTOCOL_TCP;
+ state->lease = NATPMP_DEFAULT_LEASE;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: natpmp init...\n");
+
+ r = initnatpmp(&(state->natpmp), 0, 0);
+ if (r == 0) {
+ state->init = 1;
+ fprintf(stdout, "tor-fw-helper: natpmp initialized...\n");
+ return r;
+ } else {
+ fprintf(stderr, "tor-fw-helper: natpmp failed to initialize...\n");
+ return r;
+ }
+}
+
+/** Tear down the NAT-PMP connection stored in <b>backend_state</b>.*/
+int
+tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: natpmp cleanup...\n");
+ r = closenatpmp(&(state->natpmp));
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: closing natpmp socket: %d\n", r);
+ return r;
+}
+
+/** Use select() to wait until we can read on fd. */
+static int
+wait_until_fd_readable(int fd, struct timeval *timeout)
+{
+ int r;
+ fd_set fds;
+ if (fd >= FD_SETSIZE) {
+ fprintf(stderr, "E: NAT-PMP FD_SETSIZE error %d\n", fd);
+ return -1;
+ }
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ r = select(fd+1, &fds, NULL, NULL, timeout);
+ if (r == -1) {
+ fprintf(stdout, "V: select failed in wait_until_fd_readable: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ /* XXXX we should really check to see whether fd was readable, or we timed
+ out. */
+ return 0;
+}
+
+/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
+ * using the <b>natpmp_t</b> stored in <b>backend_state</b>. */
+int
+tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options,
+ void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+ int x = 0;
+ int sav_errno;
+
+ struct timeval timeout;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: sending natpmp portmapping request...\n");
+ r = sendnewportmappingrequest(&(state->natpmp), state->protocol,
+ tor_fw_options->internal_port,
+ tor_fw_options->external_port,
+ state->lease);
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "tor-fw-helper: NAT-PMP sendnewportmappingrequest "
+ "returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED");
+
+ do {
+ getnatpmprequesttimeout(&(state->natpmp), &timeout);
+ x = wait_until_fd_readable(state->natpmp.s, &timeout);
+ if (x == -1)
+ return -1;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: attempting to readnatpmpreponseorretry...\n");
+ r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
+ sav_errno = errno;
+
+ if (r<0 && r!=NATPMP_TRYAGAIN) {
+ fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r);
+ fprintf(stderr, "E: errno=%d '%s'\n", sav_errno,
+ strerror(sav_errno));
+ }
+
+ } while (r == NATPMP_TRYAGAIN);
+
+ if (r != 0) {
+ /* XXX TODO: NATPMP_* should be formatted into useful error strings */
+ fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
+ " %d\n", r);
+ if (r == -51)
+ fprintf(stderr, "E: NAT-PMP It appears that the request was "
+ "unauthorized\n");
+ return r;
+ }
+
+ if (r == NATPMP_SUCCESS) {
+ fprintf(stdout, "tor-fw-helper: NAT-PMP mapped public port %hu to"
+ " localport %hu liftime %u\n",
+ (state->response).pnu.newportmapping.mappedpublicport,
+ (state->response).pnu.newportmapping.privateport,
+ (state->response).pnu.newportmapping.lifetime);
+ }
+
+ tor_fw_options->nat_pmp_status = 1;
+
+ return r;
+}
+
+/** Fetch our likely public IP from our upstream NAT-PMP enabled NAT device.
+ * Use the connection context stored in <b>backend_state</b>. */
+int
+tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ void *backend_state)
+{
+ int r = 0;
+ int x = 0;
+ int sav_errno;
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+
+ struct timeval timeout;
+
+ r = sendpublicaddressrequest(&(state->natpmp));
+ fprintf(stdout, "tor-fw-helper: NAT-PMP sendpublicaddressrequest returned"
+ " %d (%s)\n", r, r==2?"SUCCESS":"FAILED");
+
+ do {
+ getnatpmprequesttimeout(&(state->natpmp), &timeout);
+
+ x = wait_until_fd_readable(state->natpmp.s, &timeout);
+ if (x == -1)
+ return -1;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: NAT-PMP attempting to read reponse...\n");
+ r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
+ sav_errno = errno;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: NAT-PMP readnatpmpresponseorretry returned"
+ " %d\n", r);
+
+ if ( r < 0 && r != NATPMP_TRYAGAIN) {
+ fprintf(stderr, "E: NAT-PMP readnatpmpresponseorretry failed %d\n",
+ r);
+ fprintf(stderr, "E: NAT-PMP errno=%d '%s'\n", sav_errno,
+ strerror(sav_errno));
+ }
+
+ } while (r == NATPMP_TRYAGAIN );
+
+ if (r != 0) {
+ fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
+ " %d\n", r);
+ return r;
+ }
+
+ fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n",
+ inet_ntoa((state->response).pnu.publicaddress.addr));
+ tor_fw_options->public_ip_status = 1;
+
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: result = %u\n", r);
+ fprintf(stdout, "V: type = %u\n", (state->response).type);
+ fprintf(stdout, "V: resultcode = %u\n", (state->response).resultcode);
+ fprintf(stdout, "V: epoch = %u\n", (state->response).epoch);
+ }
+
+ return r;
+}
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h
new file mode 100644
index 0000000000..0190379a23
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-natpmp.h
+ **/
+
+#ifdef NAT_PMP
+#ifndef _TOR_FW_HELPER_NATPMP_H
+#define _TOR_FW_HELPER_NATPMP_H
+
+#include <natpmp.h>
+
+/** This is the default NAT-PMP lease time in seconds. */
+#define NATPMP_DEFAULT_LEASE 3600
+/** NAT-PMP has many codes for success; this is one of them. */
+#define NATPMP_SUCCESS 0
+
+/** This is our NAT-PMP meta structure - it holds our request data, responses,
+ * various NAT-PMP parameters, and of course the status of the motion in the
+ * NAT-PMP ocean. */
+typedef struct natpmp_state_t {
+ natpmp_t natpmp;
+ natpmpresp_t response;
+ int fetch_public_ip;
+ int status;
+ int init; /**< Have we been initialized? */
+ int protocol; /**< This will only be TCP. */
+ int lease;
+} natpmp_state_t;
+
+const tor_fw_backend_t *tor_fw_get_natpmp_backend(void);
+
+int tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state);
+
+int tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state);
+
+int tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options,
+ void *backend_state);
+
+int tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ void *backend_state);
+
+#endif
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c
new file mode 100644
index 0000000000..c4b14a84e2
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-upnp.c
+ * \brief The implementation of our UPnP firewall helper.
+ **/
+
+#include "orconfig.h"
+#ifdef MINIUPNPC
+#ifdef MS_WINDOWS
+#define STATICLIB
+#endif
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <assert.h>
+
+#include "compat.h"
+#include "tor-fw-helper.h"
+#include "tor-fw-helper-upnp.h"
+
+/** UPnP timeout value. */
+#define UPNP_DISCOVER_TIMEOUT 2000
+/** Description of the port mapping in the UPnP table. */
+#define UPNP_DESC "Tor relay"
+
+/* XXX TODO: We should print these as a useful user string when we return the
+ * number to a user */
+/** Magic numbers as miniupnpc return codes. */
+#define UPNP_ERR_SUCCESS 0
+#define UPNP_ERR_NODEVICESFOUND 1
+#define UPNP_ERR_NOIGDFOUND 2
+#define UPNP_ERR_ADDPORTMAPPING 3
+#define UPNP_ERR_GETPORTMAPPING 4
+#define UPNP_ERR_DELPORTMAPPING 5
+#define UPNP_ERR_GETEXTERNALIP 6
+#define UPNP_ERR_INVAL 7
+#define UPNP_ERR_OTHER 8
+#define UPNP_SUCCESS 1
+
+/** This hooks miniupnpc into our multi-backend API. */
+static tor_fw_backend_t tor_miniupnp_backend = {
+ "miniupnp",
+ sizeof(struct miniupnpc_state_t),
+ tor_upnp_init,
+ tor_upnp_cleanup,
+ tor_upnp_fetch_public_ip,
+ tor_upnp_add_tcp_mapping
+};
+
+/** Return the backend for miniupnp. */
+const tor_fw_backend_t *
+tor_fw_get_miniupnp_backend(void)
+{
+ return &tor_miniupnp_backend;
+}
+
+/** Initialize the UPnP backend and store the results in
+ * <b>backend_state</b>.*/
+int
+tor_upnp_init(tor_fw_options_t *options, void *backend_state)
+{
+ /*
+ This leaks the user agent from the client to the router - perhaps we don't
+ want to do that? eg:
+
+ User-Agent: Ubuntu/10.04, UPnP/1.0, MiniUPnPc/1.4
+
+ */
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ struct UPNPDev *devlist;
+ int r;
+
+ memset(&(state->urls), 0, sizeof(struct UPNPUrls));
+ memset(&(state->data), 0, sizeof(struct IGDdatas));
+ state->init = 0;
+
+ devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0);
+ if (NULL == devlist) {
+ fprintf(stderr, "E: upnpDiscover returned: NULL\n");
+ return UPNP_ERR_NODEVICESFOUND;
+ }
+
+ assert(options);
+ r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data),
+ state->lanaddr, UPNP_LANADDR_SZ);
+ fprintf(stdout, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r,
+ r==UPNP_SUCCESS?"SUCCESS":"FAILED");
+
+ freeUPNPDevlist(devlist);
+
+ if (r != 1 && r != 2)
+ return UPNP_ERR_NOIGDFOUND;
+
+ state->init = 1;
+ return UPNP_ERR_SUCCESS;
+}
+
+/** Tear down the UPnP connection stored in <b>backend_state</b>.*/
+int
+tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state)
+{
+
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ assert(options);
+
+ if (state->init)
+ FreeUPNPUrls(&(state->urls));
+ state->init = 0;
+
+ return UPNP_ERR_SUCCESS;
+}
+
+/** Fetch our likely public IP from our upstream UPnP IGD enabled NAT device.
+ * Use the connection context stored in <b>backend_state</b>. */
+int
+tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state)
+{
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ int r;
+ char externalIPAddress[16];
+
+ if (!state->init) {
+ r = tor_upnp_init(options, state);
+ if (r != UPNP_ERR_SUCCESS)
+ return r;
+ }
+
+ r = UPNP_GetExternalIPAddress(state->urls.controlURL,
+ state->data.first.servicetype,
+ externalIPAddress);
+
+ if (r != UPNPCOMMAND_SUCCESS)
+ goto err;
+
+ if (externalIPAddress[0]) {
+ fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n",
+ externalIPAddress); tor_upnp_cleanup(options, state);
+ options->public_ip_status = 1;
+ return UPNP_ERR_SUCCESS;
+ } else {
+ goto err;
+ }
+
+ err:
+ tor_upnp_cleanup(options, state);
+ return UPNP_ERR_GETEXTERNALIP;
+}
+
+/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
+ * and store the results in <b>backend_state</b>. */
+int
+tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state)
+{
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ int r;
+ char internal_port_str[6];
+ char external_port_str[6];
+
+ if (!state->init) {
+ r = tor_upnp_init(options, state);
+ if (r != UPNP_ERR_SUCCESS)
+ return r;
+ }
+
+ if (options->verbose)
+ fprintf(stdout, "V: internal port: %d, external port: %d\n",
+ (int)options->internal_port, (int)options->external_port);
+
+ tor_snprintf(internal_port_str, sizeof(internal_port_str),
+ "%d", (int)options->internal_port);
+ tor_snprintf(external_port_str, sizeof(external_port_str),
+ "%d", (int)options->external_port);
+
+ r = UPNP_AddPortMapping(state->urls.controlURL,
+ state->data.first.servicetype,
+ external_port_str, internal_port_str,
+ state->lanaddr, UPNP_DESC, "TCP", 0);
+ if (r != UPNPCOMMAND_SUCCESS)
+ return UPNP_ERR_ADDPORTMAPPING;
+
+ options->upnp_status = 1;
+ return UPNP_ERR_SUCCESS;
+}
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h
new file mode 100644
index 0000000000..021a8e0aac
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-upnp.h
+ * \brief The main header for our firewall helper.
+ **/
+
+#ifdef MINIUPNPC
+#ifndef _TOR_FW_HELPER_UPNP_H
+#define _TOR_FW_HELPER_UPNP_H
+
+#include <miniupnpc/miniwget.h>
+#include <miniupnpc/miniupnpc.h>
+#include <miniupnpc/upnpcommands.h>
+#include <miniupnpc/upnperrors.h>
+
+/** This is a magic number for miniupnpc lan address size. */
+#define UPNP_LANADDR_SZ 64
+
+/** This is our miniupnpc meta structure - it holds our request data,
+ * responses, and various miniupnpc parameters. */
+typedef struct miniupnpc_state_t {
+ struct UPNPUrls urls;
+ struct IGDdatas data;
+ char lanaddr[UPNP_LANADDR_SZ];
+ int init;
+} miniupnpc_state_t;
+
+const tor_fw_backend_t *tor_fw_get_miniupnp_backend(void);
+
+int tor_upnp_init(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state);
+
+#endif
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.c b/src/tools/tor-fw-helper/tor-fw-helper.c
new file mode 100644
index 0000000000..002239745a
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper.c
@@ -0,0 +1,396 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper.c
+ * \brief The main wrapper around our firewall helper logic.
+ **/
+
+/*
+ * tor-fw-helper is a tool for opening firewalls with NAT-PMP and UPnP; this
+ * tool is designed to be called by hand or by Tor by way of a exec() at a
+ * later date.
+ */
+
+#include "orconfig.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+#include <string.h>
+
+#ifdef MS_WINDOWS
+#include <winsock2.h>
+#endif
+
+#include "tor-fw-helper.h"
+#ifdef NAT_PMP
+#include "tor-fw-helper-natpmp.h"
+#endif
+#ifdef MINIUPNPC
+#include "tor-fw-helper-upnp.h"
+#endif
+
+/** This is our meta storage type - it holds information about each helper
+ including the total number of helper backends, function pointers, and helper
+ state. */
+typedef struct backends_t {
+ /** The total number of backends */
+ int n_backends;
+ /** The backend functions as an array */
+ tor_fw_backend_t backend_ops[MAX_BACKENDS];
+ /** The internal backend state */
+ void *backend_state[MAX_BACKENDS];
+} backends_t;
+
+/** Initalize each backend helper with the user input stored in <b>options</b>
+ * and put the results in the <b>backends</b> struct. */
+static int
+init_backends(tor_fw_options_t *options, backends_t *backends)
+{
+ int n_available = 0;
+ int i, r, n;
+ tor_fw_backend_t *backend_ops_list[MAX_BACKENDS];
+ void *data = NULL;
+ /* First, build a list of the working backends. */
+ n = 0;
+#ifdef MINIUPNPC
+ backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_miniupnp_backend();
+#endif
+#ifdef NAT_PMP
+ backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_natpmp_backend();
+#endif
+ n_available = n;
+
+ /* Now, for each backend that might work, try to initialize it.
+ * That's how we roll, initialized.
+ */
+ n = 0;
+ for (i=0; i<n_available; ++i) {
+ data = calloc(1, backend_ops_list[i]->state_len);
+ if (!data) {
+ perror("calloc");
+ exit(1);
+ }
+ r = backend_ops_list[i]->init(options, data);
+ if (r == 0) {
+ backends->backend_ops[n] = *backend_ops_list[i];
+ backends->backend_state[n] = data;
+ n++;
+ } else {
+ free(data);
+ }
+ }
+ backends->n_backends = n;
+
+ return n;
+}
+
+/** Return the proper commandline switches when the user needs information. */
+static void
+usage(void)
+{
+ fprintf(stderr, "tor-fw-helper usage:\n"
+ " [-h|--help]\n"
+ " [-T|--Test]\n"
+ " [-v|--verbose]\n"
+ " [-g|--fetch-public-ip]\n"
+ " -i|--internal-or-port [TCP port]\n"
+ " [-e|--external-or-port [TCP port]]\n"
+ " [-d|--internal-dir-port [TCP port]\n"
+ " [-p|--external-dir-port [TCP port]]]\n");
+}
+
+/** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the
+ * current working directory. */
+static int
+log_commandline_options(int argc, char **argv)
+{
+ int i, retval;
+ FILE *logfile;
+ time_t now;
+
+ /* Open the log file */
+ logfile = fopen("tor-fw-helper.log", "a");
+ if (NULL == logfile)
+ return -1;
+
+ /* Send all commandline arguments to the file */
+ now = time(NULL);
+ retval = fprintf(logfile, "START: %s\n", ctime(&now));
+ for (i = 0; i < argc; i++) {
+ retval = fprintf(logfile, "ARG: %d: %s\n", i, argv[i]);
+ if (retval < 0)
+ goto error;
+
+ retval = fprintf(stdout, "ARG: %d: %s\n", i, argv[i]);
+ if (retval < 0)
+ goto error;
+ }
+ now = time(NULL);
+ retval = fprintf(logfile, "END: %s\n", ctime(&now));
+
+ /* Close and clean up */
+ retval = fclose(logfile);
+ return retval;
+
+ /* If there was an error during writing */
+ error:
+ fclose(logfile);
+ return -1;
+}
+
+/** Iterate over over each of the supported <b>backends</b> and attempt to
+ * fetch the public ip. */
+static void
+tor_fw_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_fetch_public_ip\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (char *)(backends->backend_ops)[i].name);
+ }
+ r = backends->backend_ops[i].fetch_public_ip(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_fetch_public_ip backend %s "
+ " returned: %i\n", (char *)(backends->backend_ops)[i].name, r);
+ }
+}
+
+/** Iterate over each of the supported <b>backends</b> and attempt to add a
+ * port forward for the OR port stored in <b>tor_fw_options</b>. */
+static void
+tor_fw_add_or_port(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_add_or_port\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (const char *) backends->backend_ops[i].name);
+ }
+ r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_add_or_port backend %s "
+ "returned: %i\n", (const char *) backends->backend_ops[i].name, r);
+ }
+}
+
+/** Iterate over each of the supported <b>backends</b> and attempt to add a
+ * port forward for the Dir port stored in <b>tor_fw_options</b>. */
+static void
+tor_fw_add_dir_port(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_add_dir_port\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (char *)(backends->backend_ops)[i].name);
+ }
+ r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_add_dir_port backend %s "
+ "returned: %i\n", (const char *)backends->backend_ops[i].name, r);
+ }
+}
+
+/** Called before we make any calls to network-related functions.
+ * (Some operating systems require their network libraries to be
+ * initialized.) (from common/compat.c) */
+static int
+network_init(void)
+{
+#ifdef MS_WINDOWS
+ /* This silly exercise is necessary before windows will allow
+ * gethostbyname to work. */
+ WSADATA WSAData;
+ int r;
+ r = WSAStartup(0x101, &WSAData);
+ if (r) {
+ fprintf(stderr, "E: Error initializing Windows network layer "
+ "- code was %d", r);
+ return -1;
+ }
+ /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
+ * We might use it to complain if we're trying to be a server but have
+ * too few sockets available. */
+#endif
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int r = 0;
+ int c = 0;
+
+ tor_fw_options_t tor_fw_options;
+ backends_t backend_state;
+
+ memset(&tor_fw_options, 0, sizeof(tor_fw_options));
+ memset(&backend_state, 0, sizeof(backend_state));
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"verbose", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {"internal-or-port", 1, 0, 'i'},
+ {"external-or-port", 1, 0, 'e'},
+ {"internal-dir-port", 1, 0, 'd'},
+ {"external-dir-port", 1, 0, 'p'},
+ {"fetch-public-ip", 0, 0, 'g'},
+ {"test-commandline", 0, 0, 'T'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "vhi:e:d:p:gT",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'v': tor_fw_options.verbose = 1; break;
+ case 'h': tor_fw_options.help = 1; usage(); exit(1); break;
+ case 'i': sscanf(optarg, "%hu", &tor_fw_options.private_or_port);
+ break;
+ case 'e': sscanf(optarg, "%hu", &tor_fw_options.public_or_port);
+ break;
+ case 'd': sscanf(optarg, "%hu", &tor_fw_options.private_dir_port);
+ break;
+ case 'p': sscanf(optarg, "%hu", &tor_fw_options.public_dir_port);
+ break;
+ case 'g': tor_fw_options.fetch_public_ip = 1; break;
+ case 'T': tor_fw_options.test_commandline = 1; break;
+ case '?': break;
+ default : fprintf(stderr, "Unknown option!\n"); usage(); exit(1);
+ }
+ }
+
+ if (tor_fw_options.verbose) {
+ fprintf(stderr, "V: tor-fw-helper version %s\n"
+ "V: We were called with the following arguments:\n"
+ "V: verbose = %d, help = %d, pub or port = %u, "
+ "priv or port = %u\n"
+ "V: pub dir port = %u, priv dir port = %u\n"
+ "V: fetch_public_ip = %u\n",
+ tor_fw_version, tor_fw_options.verbose, tor_fw_options.help,
+ tor_fw_options.private_or_port, tor_fw_options.public_or_port,
+ tor_fw_options.private_dir_port, tor_fw_options.public_dir_port,
+ tor_fw_options.fetch_public_ip);
+ }
+
+ if (tor_fw_options.test_commandline) {
+ return log_commandline_options(argc, argv);
+ }
+
+ /* At the very least, we require an ORPort;
+ Given a private ORPort, we can ask for a mapping that matches the port
+ externally.
+ */
+ if (!tor_fw_options.private_or_port && !tor_fw_options.fetch_public_ip) {
+ fprintf(stderr, "E: We require an ORPort or fetch_public_ip"
+ " request!\n");
+ usage();
+ exit(1);
+ } else {
+ /* When we only have one ORPort, internal/external are
+ set to be the same.*/
+ if (!tor_fw_options.public_or_port && tor_fw_options.private_or_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We're setting public_or_port = "
+ "private_or_port.\n");
+ tor_fw_options.public_or_port = tor_fw_options.private_or_port;
+ }
+ }
+ if (!tor_fw_options.private_dir_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We have no DirPort; no hole punching for "
+ "DirPorts\n");
+
+ } else {
+ /* When we only have one DirPort, internal/external are
+ set to be the same.*/
+ if (!tor_fw_options.public_dir_port && tor_fw_options.private_dir_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We're setting public_or_port = "
+ "private_or_port.\n");
+
+ tor_fw_options.public_dir_port = tor_fw_options.private_dir_port;
+ }
+ }
+
+ if (tor_fw_options.verbose) {
+ fprintf(stdout, "V: pub or port = %u, priv or port = %u\n"
+ "V: pub dir port = %u, priv dir port = %u\n",
+ tor_fw_options.private_or_port, tor_fw_options.public_or_port,
+ tor_fw_options.private_dir_port,
+ tor_fw_options.public_dir_port);
+ }
+
+ // Initialize networking
+ if (network_init())
+ exit(1);
+
+ // Initalize the various fw-helper backend helpers
+ r = init_backends(&tor_fw_options, &backend_state);
+ if (r)
+ printf("tor-fw-helper: %i NAT traversal helper(s) loaded\n", r);
+
+ if (tor_fw_options.fetch_public_ip) {
+ tor_fw_fetch_public_ip(&tor_fw_options, &backend_state);
+ }
+
+ if (tor_fw_options.private_or_port) {
+ tor_fw_options.internal_port = tor_fw_options.private_or_port;
+ tor_fw_options.external_port = tor_fw_options.private_or_port;
+ tor_fw_add_or_port(&tor_fw_options, &backend_state);
+ }
+
+ if (tor_fw_options.private_dir_port) {
+ tor_fw_options.internal_port = tor_fw_options.private_dir_port;
+ tor_fw_options.external_port = tor_fw_options.private_dir_port;
+ tor_fw_add_dir_port(&tor_fw_options, &backend_state);
+ }
+
+ r = (((tor_fw_options.nat_pmp_status | tor_fw_options.upnp_status)
+ |tor_fw_options.public_ip_status));
+ if (r > 0) {
+ fprintf(stdout, "tor-fw-helper: SUCCESS\n");
+ } else {
+ fprintf(stderr, "tor-fw-helper: FAILURE\n");
+ }
+
+ exit(r);
+}
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.h b/src/tools/tor-fw-helper/tor-fw-helper.h
new file mode 100644
index 0000000000..39d852d212
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper.h
+ * \brief The main header for our firewall helper.
+ **/
+
+#ifndef _TOR_FW_HELPER_H
+#define _TOR_FW_HELPER_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+
+/** The current version of tor-fw-helper. */
+#define tor_fw_version "0.1"
+
+/** This is an arbitrary hard limit - We currently have two (NAT-PMP and UPnP).
+ We're likely going to add the Intel UPnP library but nothing else comes to
+ mind at the moment. */
+#define MAX_BACKENDS 23
+
+/** This is where we store parsed commandline options. */
+typedef struct {
+ int verbose;
+ int help;
+ int test_commandline;
+ uint16_t private_dir_port;
+ uint16_t private_or_port;
+ uint16_t public_dir_port;
+ uint16_t public_or_port;
+ uint16_t internal_port;
+ uint16_t external_port;
+ int fetch_public_ip;
+ int nat_pmp_status;
+ int upnp_status;
+ int public_ip_status;
+} tor_fw_options_t;
+
+/** This is our main structure that defines our backend helper API; each helper
+ * must conform to these public methods if it expects to be handled in a
+ * non-special way. */
+typedef struct tor_fw_backend_t {
+ const char *name;
+ size_t state_len;
+ int (*init)(tor_fw_options_t *options, void *backend_state);
+ int (*cleanup)(tor_fw_options_t *options, void *backend_state);
+ int (*fetch_public_ip)(tor_fw_options_t *options, void *backend_state);
+ int (*add_tcp_mapping)(tor_fw_options_t *options, void *backend_state);
+} tor_fw_backend_t;
+
+#endif
+
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index 7a516b4571..57f82b1bc7 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -153,7 +153,7 @@ parse_commandline(int argc, char **argv)
}
months_lifetime = atoi(argv[++i]);
if (months_lifetime > 24 || months_lifetime < 0) {
- fprintf(stderr, "Lifetime (in months) was out of range.");
+ fprintf(stderr, "Lifetime (in months) was out of range.\n");
return 1;
}
} else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--reuse")) {
@@ -169,7 +169,7 @@ parse_commandline(int argc, char **argv)
fprintf(stderr, "No argument to -a\n");
return 1;
}
- if (parse_addr_port(LOG_ERR, argv[++i], NULL, &addr, &port)<0)
+ if (addr_port_lookup(LOG_ERR, argv[++i], NULL, &addr, &port)<0)
return 1;
in.s_addr = htonl(addr);
tor_inet_ntoa(&in, b, sizeof(b));
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 8c4d3f6483..f1220d9d88 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -393,7 +393,7 @@ main(int argc, char **argv)
socksport = 9050; /* 9050 */
}
} else if (n_args == 2) {
- if (parse_addr_port(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) {
+ if (addr_port_lookup(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) {
fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]);
return 1;
}
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index b3cd1db50b..34d7c75b01 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -122,6 +122,7 @@
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H
@@ -233,5 +234,13 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.2.2.19-alpha"
+#define VERSION "0.2.3.8-alpha-dev"
+
+
+#define HAVE_STRUCT_SOCKADDR_IN6
+#define HAVE_STRUCT_IN6_ADDR
+#define RSHIFT_DOES_SIGN_EXTEND
+#define FLEXIBLE_ARRAY_MEMBER 0
+#define HAVE_EVENT2_EVENT_H
+#define SHARE_DATADIR ""