aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Makefile.am44
-rw-r--r--src/common/address.c15
-rw-r--r--src/common/address.h3
-rw-r--r--src/common/aes.c19
-rw-r--r--src/common/compat.c155
-rw-r--r--src/common/compat.h30
-rw-r--r--src/common/compat_libevent.c60
-rw-r--r--src/common/compat_libevent.h18
-rw-r--r--src/common/container.c6
-rw-r--r--src/common/crypto.c22
-rw-r--r--src/common/crypto.h4
-rw-r--r--src/common/log.c33
-rw-r--r--src/common/mempool.c2
-rw-r--r--src/common/procmon.c336
-rw-r--r--src/common/procmon.h30
-rw-r--r--src/common/torlog.h6
-rw-r--r--src/common/tortls.c372
-rw-r--r--src/common/tortls.h15
-rw-r--r--src/common/util.c541
-rw-r--r--src/common/util.h24
-rw-r--r--src/config/geoip5398
-rw-r--r--src/or/Makefile.am103
-rw-r--r--src/or/buffers.c634
-rw-r--r--src/or/buffers.h21
-rw-r--r--src/or/circuitbuild.c694
-rw-r--r--src/or/circuitbuild.h20
-rw-r--r--src/or/circuitlist.c30
-rw-r--r--src/or/circuituse.c95
-rw-r--r--src/or/circuituse.h6
-rw-r--r--src/or/command.c15
-rw-r--r--src/or/config.c645
-rw-r--r--src/or/config.h20
-rw-r--r--src/or/connection.c636
-rw-r--r--src/or/connection.h65
-rw-r--r--src/or/connection_edge.c148
-rw-r--r--src/or/connection_edge.h10
-rw-r--r--src/or/connection_or.c209
-rw-r--r--src/or/connection_or.h2
-rw-r--r--src/or/control.c543
-rw-r--r--src/or/control.h7
-rw-r--r--src/or/cpuworker.c19
-rw-r--r--src/or/directory.c347
-rw-r--r--src/or/directory.h7
-rw-r--r--src/or/dirserv.c373
-rw-r--r--src/or/dirserv.h35
-rw-r--r--src/or/dirvote.c32
-rw-r--r--src/or/dirvote.h5
-rw-r--r--src/or/dns.c10
-rw-r--r--src/or/dnsserv.c6
-rw-r--r--src/or/eventdns.c15
-rw-r--r--src/or/eventdns.h2
-rw-r--r--src/or/geoip.c38
-rw-r--r--src/or/geoip.h5
-rw-r--r--src/or/hibernate.c8
-rw-r--r--src/or/hibernate.h4
-rw-r--r--src/or/main.c382
-rw-r--r--src/or/main.h11
-rw-r--r--src/or/microdesc.c235
-rw-r--r--src/or/microdesc.h16
-rw-r--r--src/or/networkstatus.c460
-rw-r--r--src/or/networkstatus.h40
-rw-r--r--src/or/nodelist.c735
-rw-r--r--src/or/nodelist.h60
-rw-r--r--src/or/ntmain.c1
-rw-r--r--src/or/or.h367
-rw-r--r--src/or/policies.c242
-rw-r--r--src/or/policies.h22
-rw-r--r--src/or/relay.c89
-rw-r--r--src/or/relay.h4
-rw-r--r--src/or/rendclient.c106
-rw-r--r--src/or/rendclient.h5
-rw-r--r--src/or/rendcommon.c27
-rw-r--r--src/or/rendcommon.h4
-rw-r--r--src/or/rendservice.c110
-rw-r--r--src/or/rendservice.h2
-rw-r--r--src/or/rephist.c372
-rw-r--r--src/or/rephist.h8
-rw-r--r--src/or/router.c369
-rw-r--r--src/or/router.h63
-rw-r--r--src/or/routerlist.c1363
-rw-r--r--src/or/routerlist.h105
-rw-r--r--src/or/routerparse.c66
-rw-r--r--src/or/status.c115
-rw-r--r--src/or/status.h10
-rw-r--r--src/test/Makefile.am19
-rw-r--r--src/test/test-child.c18
-rw-r--r--src/test/test.c98
-rw-r--r--src/test/test.h3
-rw-r--r--src/test/test_addr.c7
-rw-r--r--src/test/test_crypto.c30
-rw-r--r--src/test/test_dir.c18
-rw-r--r--src/test/test_microdesc.c233
-rw-r--r--src/test/test_util.c235
-rw-r--r--src/test/tinytest.c17
-rw-r--r--src/test/tinytest_demo.c16
-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.c186
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-upnp.h43
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.c363
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.h57
-rw-r--r--src/tools/tor-resolve.c4
-rw-r--r--src/win32/orconfig.h3
106 files changed, 14279 insertions, 4777 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 2d009bd4f..48218491b 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -11,12 +11,48 @@ else
libor_extra_source=
endif
-libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
- memarea.c di_ops.c util_codedigest.c $(libor_extra_source)
-libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
+libor_a_SOURCES = \
+ address.c \
+ compat.c \
+ container.c \
+ di_ops.c \
+ log.c \
+ memarea.c \
+ mempool.c \
+ procmon.c \
+ util.c \
+ util_codedigest.c \
+ $(libor_extra_source)
+
+libor_crypto_a_SOURCES = \
+ aes.c \
+ crypto.c \
+ torgzip.c \
+ tortls.c
+
libor_event_a_SOURCES = compat_libevent.c
-noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h
+noinst_HEADERS = \
+ address.h \
+ aes.h \
+ ciphers.inc \
+ compat.h \
+ compat_libevent.h \
+ container.h \
+ crypto.h \
+ di_ops.h \
+ ht.h \
+ memarea.h \
+ mempool.h \
+ procmon.h \
+ strlcat.c \
+ strlcpy.c \
+ torgzip.h \
+ torint.h \
+ torlog.h \
+ tortls.h \
+ tortls_states.h \
+ util.h
common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
if test "@SHA1SUM@" != none; then \
diff --git a/src/common/address.c b/src/common/address.c
index 1c725393d..d0c2d5e15 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -343,7 +343,7 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
* brackets.
*/
const char *
-tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate)
+tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
{
const char *ptr;
tor_assert(addr && dest);
@@ -962,6 +962,19 @@ fmt_addr(const tor_addr_t *addr)
return buf;
}
+/** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4
+ * addresses. Also not thread-safe, also clobbers its return buffer on
+ * repeated calls. */
+const char *
+fmt_addr32(uint32_t addr)
+{
+ static char buf[INET_NTOA_BUF_LEN];
+ struct in_addr in;
+ in.s_addr = htonl(addr);
+ tor_inet_ntoa(&in, buf, sizeof(buf));
+ return buf;
+}
+
/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
* may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by
* square brackets.
diff --git a/src/common/address.h b/src/common/address.h
index 9a7656f69..e41e4c2ba 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -127,6 +127,7 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out);
char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
const char *fmt_addr(const tor_addr_t *addr);
+const char * fmt_addr32(uint32_t addr);
int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
/** Flag to specify how to do a comparison between addresses. In an "exact"
@@ -163,7 +164,7 @@ int tor_addr_port_parse(const char *s, tor_addr_t *addr_out,
int tor_addr_parse_mask_ports(const char *s,
tor_addr_t *addr_out, maskbits_t *mask_out,
uint16_t *port_min_out, uint16_t *port_max_out);
-const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int len,
+const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
int decorate);
int tor_addr_from_str(tor_addr_t *addr, const char *src);
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
diff --git a/src/common/aes.c b/src/common/aes.c
index c2fdeb594..81091e9f0 100644
--- a/src/common/aes.c
+++ b/src/common/aes.c
@@ -291,11 +291,20 @@ void
aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
char *output)
{
-
- /* XXXX This function is up to 5% of our runtime in some profiles;
- * we should look into unrolling some of the loops; taking advantage
- * of alignment, using a bigger buffer, and so on. Not till after 0.1.2.x,
- * though. */
+ /* This function alone is up to 5% of our runtime in some profiles; anything
+ * we could do to make it faster would be great.
+ *
+ * Experimenting suggests that unrolling the inner loop into a switch
+ * statement doesn't help. What does seem to help is making the input and
+ * output buffers word aligned, and never crypting anything besides an
+ * integer number of words at a time -- it shaves maybe 4-5% of the per-byte
+ * encryption time measured by bench_aes. We can't do that with the current
+ * Tor protocol, though: Tor really likes to crypt things in 509-byte
+ * chunks.
+ *
+ * If we were really ambitous, we'd force len to be a multiple of the block
+ * size, and shave maybe another 4-5% off.
+ */
int c = cipher->pos;
if (PREDICT_UNLIKELY(!len)) return;
diff --git a/src/common/compat.c b/src/common/compat.c
index fc066da68..330c43228 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -103,6 +103,35 @@
#include "strlcat.c"
#endif
+/** As open(path, flags, mode), but return an fd with the close-on-exec mode
+ * set. */
+int
+tor_open_cloexec(const char *path, int flags, unsigned mode)
+{
+#ifdef O_CLOEXEC
+ return open(path, flags|O_CLOEXEC, mode);
+#else
+ int fd = open(path, flags, mode);
+#ifdef FD_CLOEXEC
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+ return fd;
+#endif
+}
+
+/** DOCDOC */
+FILE *
+tor_fopen_cloexec(const char *path, const char *mode)
+{
+ FILE *result = fopen(path, mode);
+#ifdef FD_CLOEXEC
+ if (result != NULL)
+ fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
+#endif
+ return result;
+}
+
#ifdef HAVE_SYS_MMAN_H
/** Try to create a memory mapping for <b>filename</b> and return it. On
* failure, return NULL. Sets errno properly, using ERANGE to mean
@@ -118,7 +147,7 @@ tor_mmap_file(const char *filename)
tor_assert(filename);
- fd = open(filename, O_RDONLY, 0);
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
if (fd<0) {
int save_errno = errno;
int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
@@ -415,7 +444,7 @@ tor_vasprintf(char **strp, const char *fmt, va_list args)
*
* This function is <em>not</em> timing-safe.
*
- * Requires that nlen be greater than zero.
+ * Requires that <b>nlen</b> be greater than zero.
*/
const void *
tor_memmem(const void *_haystack, size_t hlen,
@@ -695,7 +724,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
*locked_out = 0;
log_info(LD_FS, "Locking \"%s\"", filename);
- fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
if (fd < 0) {
log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
strerror(errno));
@@ -841,7 +870,7 @@ socket_accounting_unlock(void)
* Windows, where close()ing a socket doesn't work. Returns 0 on success, -1
* on failure. */
int
-tor_close_socket(int s)
+tor_close_socket(tor_socket_t s)
{
int r = 0;
@@ -894,8 +923,10 @@ tor_close_socket(int s)
/** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is
* now an open socket. */
static INLINE void
-mark_socket_open(int s)
+mark_socket_open(tor_socket_t s)
{
+ /* XXXX This bitarray business will NOT work on windows: sockets aren't
+ small ints there. */
if (s > max_socket) {
if (max_socket == -1) {
open_sockets = bitarray_init_zero(s+128);
@@ -917,11 +948,19 @@ mark_socket_open(int s)
/** @} */
/** As socket(), but counts the number of open sockets. */
-int
+tor_socket_t
tor_open_socket(int domain, int type, int protocol)
{
- int s = socket(domain, type, protocol);
- if (s >= 0) {
+ tor_socket_t s;
+#ifdef SOCK_CLOEXEC
+#define LINUX_CLOEXEC_OPEN_SOCKET
+ type |= SOCK_CLOEXEC;
+#endif
+ s = socket(domain, type, protocol);
+ if (SOCKET_OK(s)) {
+#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -931,11 +970,20 @@ tor_open_socket(int domain, int type, int protocol)
}
/** As socket(), but counts the number of open sockets. */
-int
+tor_socket_t
tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
{
- int s = accept(sockfd, addr, len);
- if (s >= 0) {
+ tor_socket_t s;
+#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
+#define LINUX_CLOEXEC_ACCEPT
+ s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
+#else
+ s = accept(sockfd, addr, len);
+#endif
+ if (SOCKET_OK(s)) {
+#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -958,7 +1006,7 @@ get_n_open_sockets(void)
/** Turn <b>socket</b> into a nonblocking socket.
*/
void
-set_socket_nonblocking(int socket)
+set_socket_nonblocking(tor_socket_t socket)
{
#if defined(MS_WINDOWS)
unsigned long nonblocking = 1;
@@ -986,13 +1034,22 @@ set_socket_nonblocking(int socket)
**/
/* It would be nicer just to set errno, but that won't work for windows. */
int
-tor_socketpair(int family, int type, int protocol, int fd[2])
+tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
{
//don't use win32 socketpairs (they are always bad)
#if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
int r;
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
+#endif
r = socketpair(family, type, protocol, fd);
if (r == 0) {
+#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
+ if (fd[0] >= 0)
+ fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ if (fd[1] >= 0)
+ fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
if (fd[0] >= 0) {
++n_sockets_open;
@@ -1011,9 +1068,9 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
* for now, and really, when localhost is down sometimes, we
* have other problems too.
*/
- int listener = -1;
- int connector = -1;
- int acceptor = -1;
+ tor_socket_t listener = -1;
+ tor_socket_t connector = -1;
+ tor_socket_t acceptor = -1;
struct sockaddr_in listen_addr;
struct sockaddr_in connect_addr;
int size;
@@ -1223,7 +1280,8 @@ log_credential_status(void)
/* Read, effective and saved GIDs */
gid_t rgid, egid, sgid;
/* Supplementary groups */
- gid_t sup_gids[NGROUPS_MAX + 1];
+ gid_t *sup_gids = NULL;
+ int sup_gids_size;
/* Number of supplementary groups */
int ngids;
@@ -1269,9 +1327,19 @@ log_credential_status(void)
#endif
/* log supplementary groups */
- if ((ngids = getgroups(NGROUPS_MAX + 1, sup_gids)) < 0) {
+ sup_gids_size = 64;
+ sup_gids = tor_malloc(sizeof(gid_t) * 64);
+ while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 &&
+ errno == EINVAL &&
+ sup_gids_size < NGROUPS_MAX) {
+ sup_gids_size *= 2;
+ sup_gids = tor_realloc(sup_gids, sizeof(gid_t) * sup_gids_size);
+ }
+
+ if (ngids < 0) {
log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s",
strerror(errno));
+ tor_free(sup_gids);
return -1;
} else {
int i, retval = 0;
@@ -1301,6 +1369,7 @@ log_credential_status(void)
tor_free(cp);
});
smartlist_free(elts);
+ tor_free(sup_gids);
return retval;
}
@@ -1980,6 +2049,52 @@ spawn_exit(void)
#endif
}
+/** Implementation logic for compute_num_cpus(). */
+static int
+compute_num_cpus_impl(void)
+{
+#ifdef MS_WINDOWS
+ SYSTEM_INFO info;
+ memset(&info, 0, sizeof(info));
+ GetSystemInfo(&info);
+ if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
+ return (int)info.dwNumberOfProcessors;
+ else
+ return -1;
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+ long cpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (cpus >= 1 && cpus < INT_MAX)
+ return (int)cpus;
+ else
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+#define MAX_DETECTABLE_CPUS 16
+
+/** Return how many CPUs we are running with. We assume that nobody is
+ * using hot-swappable CPUs, so we don't recompute this after the first
+ * time. Return -1 if we don't know how to tell the number of CPUs on this
+ * system.
+ */
+int
+compute_num_cpus(void)
+{
+ static int num_cpus = -2;
+ if (num_cpus == -2) {
+ num_cpus = compute_num_cpus_impl();
+ tor_assert(num_cpus != -2);
+ if (num_cpus > MAX_DETECTABLE_CPUS)
+ log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
+ "will not autodetect any more than %d, though. If you "
+ "want to configure more, set NumCPUs in your torrc",
+ num_cpus, MAX_DETECTABLE_CPUS);
+ }
+ return num_cpus;
+}
+
/** Set *timeval to the current time of day. On error, log and terminate.
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
*/
@@ -2577,11 +2692,11 @@ in_main_thread(void)
*/
#if defined(MS_WINDOWS)
int
-tor_socket_errno(int sock)
+tor_socket_errno(tor_socket_t sock)
{
int optval, optvallen=sizeof(optval);
int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK && sock >= 0) {
+ if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
return err;
if (optval)
diff --git a/src/common/compat.h b/src/common/compat.h
index eff51ab30..094036dff 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -51,6 +51,8 @@
#include <netinet6/in6.h>
#endif
+#include <stdio.h>
+
#if defined (WINCE)
#include <fcntl.h>
#include <io.h>
@@ -367,6 +369,9 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
#endif
/* ===== File compatibility */
+int tor_open_cloexec(const char *path, int flags, unsigned mode);
+FILE *tor_fopen_cloexec(const char *path, const char *mode);
+
int replace_file(const char *from, const char *to);
int touch_file(const char *fname);
@@ -390,15 +395,24 @@ int tor_fd_seekend(int fd);
typedef int socklen_t;
#endif
-int tor_close_socket(int s);
-int tor_open_socket(int domain, int type, int protocol);
-int tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len);
+#ifdef MS_WINDOWS
+#define tor_socket_t intptr_t
+#define SOCKET_OK(s) ((s) != INVALID_SOCKET)
+#else
+#define tor_socket_t int
+#define SOCKET_OK(s) ((s) >= 0)
+#endif
+
+int tor_close_socket(tor_socket_t s);
+tor_socket_t tor_open_socket(int domain, int type, int protocol);
+tor_socket_t tor_accept_socket(int sockfd, struct sockaddr *addr,
+ socklen_t *len);
int get_n_open_sockets(void);
#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
-/** Implementatino of struct in6_addr for platforms that do not have it.
+/** Implementation of struct in6_addr for platforms that do not have it.
* Generally, these platforms are ones without IPv6 support, but we want to
* have a working in6_addr there anyway, so we can use it to parse IPv6
* addresses. */
@@ -464,8 +478,8 @@ int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
-void set_socket_nonblocking(int socket);
-int tor_socketpair(int family, int type, int protocol, int fd[2]);
+void set_socket_nonblocking(tor_socket_t socket);
+int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
int network_init(void);
/* For stupid historical reasons, windows sockets have an independent
@@ -492,7 +506,7 @@ int network_init(void);
((e) == WSAEMFILE || (e) == WSAENOBUFS)
/** Return true if e is EADDRINUSE or the local equivalent. */
#define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE)
-int tor_socket_errno(int sock);
+int tor_socket_errno(tor_socket_t sock);
const char *tor_socket_strerror(int e);
#else
#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN)
@@ -568,6 +582,8 @@ void spawn_exit(void) ATTR_NORETURN;
#undef TOR_IS_MULTITHREADED
#endif
+int compute_num_cpus(void);
+
/* Because we use threads instead of processes on most platforms (Windows,
* Linux, etc), we need locking for them. On platforms with poor thread
* support or broken gethostbyname_r, these functions are no-ops. */
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 3ad9be145..c338dd6c0 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -48,7 +48,7 @@ typedef uint32_t le_version_t;
* it is. */
#define LE_OLD V(0,0,0)
/** Represents a version of libevent so weird we can't figure out what version
- * it it. */
+ * it is. */
#define LE_OTHER V(0,0,99)
static le_version_t tor_get_libevent_version(const char **v_out);
@@ -165,9 +165,11 @@ struct event_base *the_event_base = NULL;
/** Initialize the Libevent library and set up the event base. */
void
-tor_libevent_initialize(void)
+tor_libevent_initialize(tor_libevent_cfg *torcfg)
{
tor_assert(the_event_base == NULL);
+ /* some paths below don't use torcfg, so avoid unused variable warnings */
+ (void)torcfg;
#ifdef __APPLE__
if (MACOSX_KQUEUE_IS_BROKEN ||
@@ -177,7 +179,29 @@ tor_libevent_initialize(void)
#endif
#ifdef HAVE_EVENT2_EVENT_H
- the_event_base = event_base_new();
+ {
+ struct event_config *cfg = event_config_new();
+
+#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS)
+ if (! torcfg->disable_iocp)
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
+#endif
+
+#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
+ if (torcfg->num_cpus > 0)
+ event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
+#endif
+
+#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
+ /* We can enable changelist support with epoll, since we don't give
+ * Libevent any dup'd fds. This lets us avoid some syscalls. */
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
+#endif
+
+ the_event_base = event_base_new_with_config(cfg);
+
+ event_config_free(cfg);
+ }
#else
the_event_base = event_init();
#endif
@@ -240,7 +264,7 @@ tor_decode_libevent_version(const char *v)
/* Try the new preferred "1.4.11-stable" format.
* Also accept "1.4.14b-stable". */
- fields = sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
+ fields = tor_sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
if (fields == 3 ||
((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
(fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
@@ -248,7 +272,7 @@ tor_decode_libevent_version(const char *v)
}
/* Try the old "1.3e" format. */
- fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
+ fields = tor_sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
if (fields == 3 && TOR_ISALPHA(c)) {
return V_OLD(major, minor, c);
} else if (fields == 2) {
@@ -552,3 +576,29 @@ periodic_timer_free(periodic_timer_t *timer)
tor_free(timer);
}
+#ifdef USE_BUFFEREVENTS
+static const struct timeval *one_tick = NULL;
+/**
+ * Return a special timeout to be passed whenever libevent's O(1) timeout
+ * implementation should be used. Only use this when the timer is supposed
+ * to fire after 1 / TOR_LIBEVENT_TICKS_PER_SECOND seconds have passed.
+*/
+const struct timeval *
+tor_libevent_get_one_tick_timeout(void)
+{
+ if (PREDICT_UNLIKELY(one_tick == NULL)) {
+ struct event_base *base = tor_libevent_get_base();
+ struct timeval tv;
+ if (TOR_LIBEVENT_TICKS_PER_SECOND == 1) {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000000 / TOR_LIBEVENT_TICKS_PER_SECOND;
+ }
+ one_tick = event_base_init_common_timeout(base, &tv);
+ }
+ return one_tick;
+}
+#endif
+
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index fdf5e0a18..8669fd4e0 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -8,10 +8,14 @@
struct event;
struct event_base;
+#ifdef USE_BUFFEREVENTS
+struct bufferevent;
+#endif
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/util.h>
-#else
+#elif !defined(EVUTIL_SOCKET_DEFINED)
+#define EVUTIL_SOCKET_DEFINED
#define evutil_socket_t int
#endif
@@ -53,7 +57,12 @@ struct timeval;
int tor_event_base_loopexit(struct event_base *base, struct timeval *tv);
#endif
-void tor_libevent_initialize(void);
+typedef struct tor_libevent_cfg {
+ int disable_iocp;
+ int num_cpus;
+} tor_libevent_cfg;
+
+void tor_libevent_initialize(tor_libevent_cfg *cfg);
struct event_base *tor_libevent_get_base(void);
const char *tor_libevent_get_method(void);
void tor_check_libevent_version(const char *m, int server,
@@ -61,5 +70,10 @@ void tor_check_libevent_version(const char *m, int server,
void tor_check_libevent_header_compatibility(void);
const char *tor_libevent_get_version_str(void);
+#ifdef USE_BUFFEREVENTS
+#define TOR_LIBEVENT_TICKS_PER_SECOND 3
+const struct timeval *tor_libevent_get_one_tick_timeout(void);
+#endif
+
#endif
diff --git a/src/common/container.c b/src/common/container.c
index da44b7fe6..92bfd2ec8 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -287,7 +287,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
/** Remove the <b>idx</b>th element of sl; if idx is not the last
* element, swap the last element of sl into the <b>idx</b>th space.
- * Return the old value of the <b>idx</b>th element.
*/
void
smartlist_del(smartlist_t *sl, int idx)
@@ -338,7 +337,8 @@ smartlist_insert(smartlist_t *sl, int idx, void *val)
/**
* Split a string <b>str</b> along all occurrences of <b>sep</b>,
- * adding the split strings, in order, to <b>sl</b>.
+ * appending the (newly allocated) split strings, in order, to
+ * <b>sl</b>. Return the number of strings added to <b>sl</b>.
*
* If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
* trailing space from each entry.
@@ -347,7 +347,7 @@ smartlist_insert(smartlist_t *sl, int idx, void *val)
* If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
* split string.
*
- * If max>0, divide the string into no more than <b>max</b> pieces. If
+ * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If
* <b>sep</b> is NULL, split on any sequence of horizontal space.
*/
int
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 1ecc24ce2..05c1ce9ea 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -777,6 +777,17 @@ crypto_pk_keysize(crypto_pk_env_t *env)
return (size_t) RSA_size(env->key);
}
+/** Return the size of the public key modulus of <b>env</b>, in bits. */
+int
+crypto_pk_num_bits(crypto_pk_env_t *env)
+{
+ tor_assert(env);
+ tor_assert(env->key);
+ tor_assert(env->key->n);
+
+ return BN_num_bits(env->key->n);
+}
+
/** Increase the reference count of <b>env</b>, and return it.
*/
crypto_pk_env_t *
@@ -937,7 +948,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data,
log_warn(LD_BUG, "couldn't compute digest");
return -1;
}
- buflen = crypto_pk_keysize(env)+1;
+ buflen = crypto_pk_keysize(env);
buf = tor_malloc(buflen);
r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
if (r != DIGEST_LEN) {
@@ -1122,8 +1133,8 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env,
warnOnFailure);
}
- buf = tor_malloc(pkeylen+1);
- outlen = crypto_pk_private_decrypt(env,buf,pkeylen+1,from,pkeylen,padding,
+ buf = tor_malloc(pkeylen);
+ outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
warnOnFailure);
if (outlen<0) {
log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
@@ -2134,13 +2145,14 @@ crypto_rand(char *to, size_t n)
}
/** Return a pseudorandom integer, chosen uniformly from the values
- * between 0 and <b>max</b>-1. */
+ * between 0 and <b>max</b>-1 inclusive. <b>max</b> must be between 1 and
+ * INT_MAX+1, inclusive. */
int
crypto_rand_int(unsigned int max)
{
unsigned int val;
unsigned int cutoff;
- tor_assert(max < UINT_MAX);
+ tor_assert(max <= ((unsigned int)INT_MAX)+1);
tor_assert(max > 0); /* don't div by 0 */
/* We ignore any values that are >= 'cutoff,' to avoid biasing the
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 54c7a67a3..9b4eee622 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -119,6 +119,7 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
size_t crypto_pk_keysize(crypto_pk_env_t *env);
+int crypto_pk_num_bits(crypto_pk_env_t *env);
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
crypto_pk_env_t *crypto_pk_copy_full(crypto_pk_env_t *orig);
int crypto_pk_key_is_private(const crypto_pk_env_t *key);
@@ -244,7 +245,8 @@ void secret_to_key(char *key_out, size_t key_out_len, const char *secret,
size_t secret_len, const char *s2k_specifier);
#ifdef CRYPTO_PRIVATE
-/* Prototypes for private functions only used by tortls.c and crypto.c */
+/* Prototypes for private functions only used by tortls.c, crypto.c, and the
+ * unit tests. */
struct rsa_st;
struct evp_pkey_st;
struct dh_st;
diff --git a/src/common/log.c b/src/common/log.c
index d14563c88..97400623e 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -154,6 +154,17 @@ log_set_application_name(const char *name)
appname = name ? tor_strdup(name) : NULL;
}
+/** Log time granularity in milliseconds. */
+static int log_time_granularity = 1;
+
+/** Define log time granularity for all logs to be <b>granularity_msec</b>
+ * milliseconds. */
+void
+set_log_time_granularity(int granularity_msec)
+{
+ log_time_granularity = granularity_msec;
+}
+
/** Helper: Write the standard prefix for log lines to a
* <b>buf_len</b> character buffer in <b>buf</b>.
*/
@@ -164,14 +175,22 @@ _log_prefix(char *buf, size_t buf_len, int severity)
struct timeval now;
struct tm tm;
size_t n;
- int r;
+ int r, ms;
tor_gettimeofday(&now);
t = (time_t)now.tv_sec;
+ ms = (int)now.tv_usec / 1000;
+ if (log_time_granularity >= 1000) {
+ t -= t % (log_time_granularity / 1000);
+ ms = 0;
+ } else {
+ ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
+ }
n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
- r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ",
- (int)now.tv_usec / 1000, sev_to_string(severity));
+ r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
+ sev_to_string(severity));
+
if (r<0)
return buf_len-1;
else
@@ -390,7 +409,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
/** Output a message to the log. It gets logged to all logfiles that
* care about messages with <b>severity</b> in <b>domain</b>. The content
- * is formatted printf style basedc on <b>format</b> and extra arguments.
+ * is formatted printf-style based on <b>format</b> and extra arguments.
* */
void
tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
@@ -703,7 +722,7 @@ change_callback_log_severity(int loglevelMin, int loglevelMax,
UNLOCK_LOGS();
}
-/** If there are any log messages that were genered with LD_NOCB waiting to
+/** If there are any log messages that were generated with LD_NOCB waiting to
* be sent to callback-based loggers, send them now. */
void
flush_pending_log_callbacks(void)
@@ -803,7 +822,7 @@ add_file_log(const log_severity_list_t *severity, const char *filename)
int fd;
logfile_t *lf;
- fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
if (fd<0)
return -1;
if (tor_fd_seekend(fd)<0)
@@ -880,7 +899,7 @@ log_level_to_string(int level)
static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
"HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
- "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", NULL
+ "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL
};
/** Return a bitmask for the log domain for which <b>domain</b> is the name,
diff --git a/src/common/mempool.c b/src/common/mempool.c
index c44492318..30d778804 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -137,7 +137,7 @@ struct mp_chunk_t {
int capacity; /**< Number of items that can be fit into this chunk. */
size_t mem_size; /**< Number of usable bytes in mem. */
char *next_mem; /**< Pointer into part of <b>mem</b> not yet carved up. */
- char mem[1]; /**< Storage for this chunk. (Not actual size.) */
+ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< Storage for this chunk. */
};
/** Number of extra bytes needed beyond mem_size to allocate a chunk. */
diff --git a/src/common/procmon.c b/src/common/procmon.c
new file mode 100644
index 000000000..5c10e9a22
--- /dev/null
+++ b/src/common/procmon.c
@@ -0,0 +1,336 @@
+
+/**
+ * \file procmon.c
+ * \brief Process-termination monitor functions
+ **/
+
+#include "procmon.h"
+
+#include "util.h"
+
+#ifdef HAVE_EVENT2_EVENT_H
+#include <event2/event.h>
+#else
+#include <event.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef MS_WINDOWS
+#include <windows.h>
+
+/* Windows does not define pid_t, but _getpid() returns an int. */
+typedef int pid_t;
+#endif
+
+/* Define to 1 if process-termination monitors on this OS and Libevent
+ version must poll for process termination themselves. */
+#define PROCMON_POLLS 1
+/* Currently we need to poll in some way on all systems. */
+
+#ifdef PROCMON_POLLS
+static void tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
+ void *procmon_);
+#endif
+
+/* This struct may contain pointers into the original process
+ * specifier string, but it should *never* contain anything which
+ * needs to be freed. */
+struct parsed_process_specifier_t {
+ pid_t pid;
+};
+
+/** Parse the process specifier given in <b>process_spec</b> into
+ * *<b>ppspec</b>. Return 0 on success; return -1 and store an error
+ * message into *<b>msg</b> on failure. The caller must not free the
+ * returned error message. */
+static int
+parse_process_specifier(const char *process_spec,
+ struct parsed_process_specifier_t *ppspec,
+ const char **msg)
+{
+ long pid_l;
+ int pid_ok = 0;
+ char *pspec_next;
+
+ /* If we're lucky, long will turn out to be large enough to hold a
+ * PID everywhere that Tor runs. */
+ pid_l = tor_parse_long(process_spec, 0, 1, LONG_MAX, &pid_ok, &pspec_next);
+
+ /* Reserve room in the ‘process specifier’ for additional
+ * (platform-specific) identifying information beyond the PID, to
+ * make our process-existence checks a bit less racy in a future
+ * version. */
+ if ((*pspec_next != 0) && (*pspec_next != ' ') && (*pspec_next != ':')) {
+ pid_ok = 0;
+ }
+
+ ppspec->pid = (pid_t)(pid_l);
+ if (!pid_ok || (pid_l != (long)(ppspec->pid))) {
+ *msg = "invalid PID";
+ goto err;
+ }
+
+ return 0;
+ err:
+ return -1;
+}
+
+struct tor_process_monitor_t {
+ /** Log domain for warning messages. */
+ log_domain_mask_t log_domain;
+
+ /** All systems: The best we can do in general is poll for the
+ * process's existence by PID periodically, and hope that the kernel
+ * doesn't reassign the same PID to another process between our
+ * polls. */
+ pid_t pid;
+
+#ifdef MS_WINDOWS
+ /** Windows-only: Should we poll hproc? If false, poll pid
+ * instead. */
+ int poll_hproc;
+
+ /** Windows-only: Get a handle to the process (if possible) and
+ * periodically check whether the process we have a handle to has
+ * ended. */
+ HANDLE hproc;
+ /* XXX023 We can and should have Libevent watch hproc for us,
+ * if/when some version of Libevent 2.x can be told to do so. */
+#endif
+
+ /* XXX023 On Linux, we can and should receive the 22nd
+ * (space-delimited) field (‘starttime’) of /proc/$PID/stat from the
+ * owning controller and store it, and poll once in a while to see
+ * whether it has changed -- if so, the kernel has *definitely*
+ * reassigned the owning controller's PID and we should exit. On
+ * FreeBSD, we can do the same trick using either the 8th
+ * space-delimited field of /proc/$PID/status on the seven FBSD
+ * systems whose admins have mounted procfs, or the start-time field
+ * of the process-information structure returned by kvmgetprocs() on
+ * any system. The latter is ickier. */
+ /* XXX023 On FreeBSD (and possibly other kqueue systems), we can and
+ * should arrange to receive EVFILT_PROC NOTE_EXIT notifications for
+ * pid, so we don't have to do such a heavyweight poll operation in
+ * order to avoid the PID-reassignment race condition. (We would
+ * still need to poll our own kqueue periodically until some version
+ * of Libevent 2.x learns to receive these events for us.) */
+
+ /** A Libevent event structure, to either poll for the process's
+ * existence or receive a notification when the process ends. */
+ struct event *e;
+
+ /** A callback to be called when the process ends. */
+ tor_procmon_callback_t cb;
+ void *cb_arg; /**< A user-specified pointer to be passed to cb. */
+};
+
+/** Verify that the process specifier given in <b>process_spec</b> is
+ * syntactically valid. Return 0 on success; return -1 and store an
+ * error message into *<b>msg</b> on failure. The caller must not
+ * free the returned error message. */
+int
+tor_validate_process_specifier(const char *process_spec,
+ const char **msg)
+{
+ struct parsed_process_specifier_t ppspec;
+
+ tor_assert(msg != NULL);
+ *msg = NULL;
+
+ return parse_process_specifier(process_spec, &ppspec, msg);
+}
+
+#ifdef HAVE_EVENT2_EVENT_H
+#define PERIODIC_TIMER_FLAGS EV_PERSIST
+#else
+#define PERIODIC_TIMER_FLAGS (0)
+#endif
+
+static struct timeval poll_interval_tv = {15, 0};
+/* Note: If you port this file to plain Libevent 2, you can make
+ * poll_interval_tv const. It has to be non-const here because in
+ * libevent 1.x, event_add expects a pointer to a non-const struct
+ * timeval. */
+
+/** Create a process-termination monitor for the process specifier
+ * given in <b>process_spec</b>. Return a newly allocated
+ * tor_process_monitor_t on success; return NULL and store an error
+ * message into *<b>msg</b> on failure. The caller must not free
+ * the returned error message.
+ *
+ * When the monitored process terminates, call
+ * <b>cb</b>(<b>cb_arg</b>).
+ */
+tor_process_monitor_t *
+tor_process_monitor_new(struct event_base *base,
+ const char *process_spec,
+ log_domain_mask_t log_domain,
+ tor_procmon_callback_t cb, void *cb_arg,
+ const char **msg)
+{
+ tor_process_monitor_t *procmon = tor_malloc(sizeof(tor_process_monitor_t));
+ struct parsed_process_specifier_t ppspec;
+
+ tor_assert(msg != NULL);
+ *msg = NULL;
+
+ if (procmon == NULL) {
+ *msg = "out of memory";
+ goto err;
+ }
+
+ procmon->log_domain = log_domain;
+
+ if (parse_process_specifier(process_spec, &ppspec, msg))
+ goto err;
+
+ procmon->pid = ppspec.pid;
+
+#ifdef MS_WINDOWS
+ procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
+ FALSE,
+ procmon->pid);
+
+ if (procmon->hproc != NULL) {
+ procmon->poll_hproc = 1;
+ log_info(procmon->log_domain, "Successfully opened handle to process %d; "
+ "monitoring it.",
+ (int)(procmon->pid));
+ } else {
+ /* If we couldn't get a handle to the process, we'll try again the
+ * first time we poll. */
+ log_info(procmon->log_domain, "Failed to open handle to process %d; will "
+ "try again later.",
+ (int)(procmon->pid));
+ }
+#endif
+
+ procmon->cb = cb;
+ procmon->cb_arg = cb_arg;
+
+#ifdef PROCMON_POLLS
+ procmon->e = tor_event_new(base, -1 /* no FD */, PERIODIC_TIMER_FLAGS,
+ tor_process_monitor_poll_cb, procmon);
+ /* Note: If you port this file to plain Libevent 2, check that
+ * procmon->e is non-NULL. We don't need to here because
+ * tor_evtimer_new never returns NULL. */
+
+ evtimer_add(procmon->e, &poll_interval_tv);
+#else
+#error OOPS?
+#endif
+
+ return procmon;
+ err:
+ tor_process_monitor_free(procmon);
+ return NULL;
+}
+
+#ifdef PROCMON_POLLS
+/** Libevent callback to poll for the existence of the process
+ * monitored by <b>procmon_</b>. */
+static void
+tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
+ void *procmon_)
+{
+ tor_process_monitor_t *procmon = (tor_process_monitor_t *)(procmon_);
+ int its_dead_jim;
+
+ (void)unused1; (void)unused2;
+
+ tor_assert(procmon != NULL);
+
+#ifdef MS_WINDOWS
+ if (procmon->poll_hproc) {
+ DWORD exit_code;
+ if (!GetExitCodeProcess(procmon->hproc, &exit_code)) {
+ char *errmsg = format_win32_error(GetLastError());
+ log_warn(procmon->log_domain, "Error \"%s\" occurred while polling "
+ "handle for monitored process %d; assuming it's dead.",
+ errmsg, procmon->pid);
+ tor_free(errmsg);
+ its_dead_jim = 1;
+ } else {
+ its_dead_jim = (exit_code != STILL_ACTIVE);
+ }
+ } else {
+ /* All we can do is try to open the process, and look at the error
+ * code if it fails again. */
+ procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
+ FALSE,
+ procmon->pid);
+
+ if (procmon->hproc != NULL) {
+ log_info(procmon->log_domain, "Successfully opened handle to monitored "
+ "process %d.",
+ procmon->pid);
+ its_dead_jim = 0;
+ procmon->poll_hproc = 1;
+ } else {
+ DWORD err_code = GetLastError();
+ char *errmsg = format_win32_error(err_code);
+
+ /* When I tested OpenProcess's error codes on Windows 7, I
+ * received error code 5 (ERROR_ACCESS_DENIED) for PIDs of
+ * existing processes that I could not open and error code 87
+ * (ERROR_INVALID_PARAMETER) for PIDs that were not in use.
+ * Since the nonexistent-process error code is sane, I'm going
+ * to assume that all errors other than ERROR_INVALID_PARAMETER
+ * mean that the process we are monitoring is still alive. */
+ its_dead_jim = (err_code == ERROR_INVALID_PARAMETER);
+
+ if (!its_dead_jim)
+ log_info(procmon->log_domain, "Failed to open handle to monitored "
+ "process %d, and error code %lu (%s) is not 'invalid "
+ "parameter' -- assuming the process is still alive.",
+ procmon->pid,
+ err_code, errmsg);
+
+ tor_free(errmsg);
+ }
+ }
+#else
+ /* Unix makes this part easy, if a bit racy. */
+ its_dead_jim = kill(procmon->pid, 0);
+ its_dead_jim = its_dead_jim && (errno == ESRCH);
+#endif
+
+ log(its_dead_jim ? LOG_NOTICE : LOG_INFO,
+ procmon->log_domain, "Monitored process %d is %s.",
+ (int)procmon->pid,
+ its_dead_jim ? "dead" : "still alive");
+
+ if (its_dead_jim) {
+ procmon->cb(procmon->cb_arg);
+#ifndef HAVE_EVENT2_EVENT_H
+ } else {
+ evtimer_add(procmon->e, &poll_interval_tv);
+#endif
+ }
+}
+#endif
+
+/** Free the process-termination monitor <b>procmon</b>. */
+void
+tor_process_monitor_free(tor_process_monitor_t *procmon)
+{
+ if (procmon == NULL)
+ return;
+
+#ifdef MS_WINDOWS
+ if (procmon->hproc != NULL)
+ CloseHandle(procmon->hproc);
+#endif
+
+ if (procmon->e != NULL)
+ tor_event_free(procmon->e);
+
+ tor_free(procmon);
+}
+
diff --git a/src/common/procmon.h b/src/common/procmon.h
new file mode 100644
index 000000000..02eb2da61
--- /dev/null
+++ b/src/common/procmon.h
@@ -0,0 +1,30 @@
+
+/**
+ * \file procmon.h
+ * \brief Headers for procmon.c
+ **/
+
+#ifndef TOR_PROCMON_H
+#define TOR_PROCMON_H
+
+#include "compat.h"
+#include "compat_libevent.h"
+
+#include "torlog.h"
+
+typedef struct tor_process_monitor_t tor_process_monitor_t;
+
+typedef void (*tor_procmon_callback_t)(void *);
+
+int tor_validate_process_specifier(const char *process_spec,
+ const char **msg);
+tor_process_monitor_t *tor_process_monitor_new(struct event_base *base,
+ const char *process_spec,
+ log_domain_mask_t log_domain,
+ tor_procmon_callback_t cb,
+ void *cb_arg,
+ const char **msg);
+void tor_process_monitor_free(tor_process_monitor_t *procmon);
+
+#endif
+
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 000e32dda..4c5729ef5 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -92,8 +92,10 @@
#define LD_HIST (1u<<18)
/** OR handshaking */
#define LD_HANDSHAKE (1u<<19)
+/** Heartbeat messages */
+#define LD_HEARTBEAT (1u<<20)
/** Number of logging domains in the code. */
-#define N_LOGGING_DOMAINS 20
+#define N_LOGGING_DOMAINS 21
/** This log message is not safe to send to a callback-based logger
* immediately. Used as a flag, not a log domain. */
@@ -145,8 +147,8 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
log_callback cb);
void flush_pending_log_callbacks(void);
void log_set_application_name(const char *name);
+void set_log_time_granularity(int granularity_msec);
-/* Outputs a message to stdout */
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
CHECK_PRINTF(3,4);
#define log tor_log /* hack it so we don't conflict with log() as much */
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 10f4440cb..94ca81ba4 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -44,14 +44,20 @@
#error "We require OpenSSL >= 0.9.7"
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#include <event2/buffer.h>
+#include "compat_libevent.h"
+#endif
+
#define CRYPTO_PRIVATE /* to import prototypes from crypto.h */
+#define TORTLS_PRIVATE
#include "crypto.h"
#include "tortls.h"
#include "util.h"
#include "torlog.h"
#include "container.h"
-#include "ht.h"
#include <string.h>
/* Enable the "v2" TLS handshake.
@@ -97,11 +103,13 @@ typedef struct tor_tls_context_t {
crypto_pk_env_t *key;
} tor_tls_context_t;
+#define TOR_TLS_MAGIC 0x71571571
+
/** Holds a SSL object and its associated data. Members are only
* accessed from within tortls.c.
*/
struct tor_tls_t {
- HT_ENTRY(tor_tls_t) node;
+ uint32_t magic;
tor_tls_context_t *context; /** A link to the context object for this tls. */
SSL *ssl; /**< An OpenSSL SSL object. */
int socket; /**< The underlying file descriptor for this TLS connection. */
@@ -109,6 +117,7 @@ struct tor_tls_t {
enum {
TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE,
+ TOR_TLS_ST_BUFFEREVENT
} state : 3; /**< The current SSL state, depending on which operations have
* completed successfully. */
unsigned int isServer:1; /**< True iff this is a server-side connection */
@@ -117,8 +126,10 @@ struct tor_tls_t {
* of the connection protocol (client sends
* different cipher list, server sends only
* one certificate). */
- /** True iff we should call negotiated_callback when we're done reading. */
+ /** True iff we should call negotiated_callback when we're done reading. */
unsigned int got_renegotiate:1;
+ /** Incremented every time we start the server side of a handshake. */
+ uint8_t server_handshake_count;
size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
* time. */
/** Last values retrieved from BIO_number_read()/write(); see
@@ -143,42 +154,29 @@ static SSL_CIPHER *CLIENT_CIPHER_DUMMIES = NULL;
static STACK_OF(SSL_CIPHER) *CLIENT_CIPHER_STACK = NULL;
#endif
-/** Helper: compare tor_tls_t objects by its SSL. */
-static INLINE int
-tor_tls_entries_eq(const tor_tls_t *a, const tor_tls_t *b)
-{
- return a->ssl == b->ssl;
-}
+/** The ex_data index in which we store a pointer to an SSL object's
+ * corresponding tor_tls_t object. */
+static int tor_tls_object_ex_data_index = -1;
-/** Helper: return a hash value for a tor_tls_t by its SSL. */
-static INLINE unsigned int
-tor_tls_entry_hash(const tor_tls_t *a)
+/** Helper: Allocate tor_tls_object_ex_data_index. */
+static void
+tor_tls_allocate_tor_tls_object_ex_data_index(void)
{
-#if SIZEOF_INT == SIZEOF_VOID_P
- return ((unsigned int)(uintptr_t)a->ssl);
-#else
- return (unsigned int) ((((uint64_t)a->ssl)>>2) & UINT_MAX);
-#endif
+ if (tor_tls_object_ex_data_index == -1) {
+ tor_tls_object_ex_data_index =
+ SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ tor_assert(tor_tls_object_ex_data_index != -1);
+ }
}
-/** Map from SSL* pointers to tor_tls_t objects using those pointers.
- */
-static HT_HEAD(tlsmap, tor_tls_t) tlsmap_root = HT_INITIALIZER();
-
-HT_PROTOTYPE(tlsmap, tor_tls_t, node, tor_tls_entry_hash,
- tor_tls_entries_eq)
-HT_GENERATE(tlsmap, tor_tls_t, node, tor_tls_entry_hash,
- tor_tls_entries_eq, 0.6, malloc, realloc, free)
-
/** Helper: given a SSL* pointer, return the tor_tls_t object using that
* pointer. */
static INLINE tor_tls_t *
tor_tls_get_by_ssl(const SSL *ssl)
{
- tor_tls_t search, *result;
- memset(&search, 0, sizeof(search));
- search.ssl = (SSL*)ssl;
- result = HT_FIND(tlsmap, &tlsmap_root, &search);
+ tor_tls_t *result = SSL_get_ex_data(ssl, tor_tls_object_ex_data_index);
+ if (result)
+ tor_assert(result->magic == TOR_TLS_MAGIC);
return result;
}
@@ -189,7 +187,7 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
const char *cname,
const char *cname_sign,
unsigned int lifetime);
-static void tor_tls_unblock_renegotiation(tor_tls_t *tls);
+
static int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
crypto_pk_env_t *identity,
unsigned int key_lifetime);
@@ -200,6 +198,7 @@ static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity,
* to touch them. */
static tor_tls_context_t *server_tls_context = NULL;
static tor_tls_context_t *client_tls_context = NULL;
+
/** True iff tor_tls_init() has been called. */
static int tls_library_is_initialized = 0;
@@ -223,36 +222,46 @@ ssl_state_to_string(int ssl_state)
return buf;
}
+void
+tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
+ int severity, int domain, const char *doing)
+{
+ const char *state = NULL, *addr;
+ const char *msg, *lib, *func;
+ int st;
+
+ st = (tls && tls->ssl) ? tls->ssl->state : -1;
+ state = (st>=0)?ssl_state_to_string(st):"---";
+
+ addr = tls ? tls->address : NULL;
+
+ msg = (const char*)ERR_reason_error_string(err);
+ lib = (const char*)ERR_lib_error_string(err);
+ func = (const char*)ERR_func_error_string(err);
+ if (!msg) msg = "(null)";
+ if (!lib) lib = "(null)";
+ if (!func) func = "(null)";
+ if (doing) {
+ log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
+ doing, addr?" with ":"", addr?addr:"",
+ msg, lib, func, state);
+ } else {
+ log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
+ addr?" with ":"", addr?addr:"",
+ msg, lib, func, state);
+ }
+}
+
/** Log all pending tls errors at level <b>severity</b>. Use
* <b>doing</b> to describe our current activities.
*/
static void
tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
{
- const char *state = NULL;
- int st;
unsigned long err;
- const char *msg, *lib, *func, *addr;
- addr = tls ? tls->address : NULL;
- st = (tls && tls->ssl) ? tls->ssl->state : -1;
+
while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!state)
- state = (st>=0)?ssl_state_to_string(st):"---";
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (doing) {
- log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
- doing, addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- } else {
- log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
- addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- }
+ tor_tls_log_one_error(tls, err, severity, domain, doing);
}
}
@@ -427,6 +436,8 @@ tor_tls_init(void)
SSLeay_version(SSLEAY_VERSION), version);
}
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
tls_library_is_initialized = 1;
}
}
@@ -445,10 +456,6 @@ tor_tls_free_all(void)
client_tls_context = NULL;
tor_tls_context_decref(ctx);
}
- if (!HT_EMPTY(&tlsmap_root)) {
- log_warn(LD_MM, "Still have entries in the tlsmap at shutdown.");
- }
- HT_CLEAR(tlsmap, &tlsmap_root);
#ifdef V2_HANDSHAKE_CLIENT
if (CLIENT_CIPHER_DUMMIES)
tor_free(CLIENT_CIPHER_DUMMIES);
@@ -892,6 +899,13 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address)
return 1;
}
+static void
+tor_tls_debug_state_callback(const SSL *ssl, int type, int val)
+{
+ log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].",
+ ssl, ssl_state_to_string(ssl->state), type, val);
+}
+
/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
* changes state. We use this:
* <ul><li>To alter the state of the handshake partway through, so we
@@ -903,6 +917,9 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
{
tor_tls_t *tls;
(void) val;
+
+ tor_tls_debug_state_callback(ssl, type, val);
+
if (type != SSL_CB_ACCEPT_LOOP)
return;
if (ssl->state != SSL3_ST_SW_SRVR_HELLO_A)
@@ -913,8 +930,11 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
/* Check whether we're watching for renegotiates. If so, this is one! */
if (tls->negotiated_callback)
tls->got_renegotiate = 1;
+ if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/
+ ++tls->server_handshake_count;
} else {
log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
+ return;
}
/* Now check the cipher list. */
@@ -931,6 +951,10 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
if (tls) {
tls->wasV2Handshake = 1;
+#ifdef USE_BUFFEREVENTS
+ if (use_unsafe_renegotiation_flag)
+ tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+#endif
} else {
log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
}
@@ -1018,6 +1042,7 @@ tor_tls_new(int sock, int isServer)
tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
tor_tls_context_t *context = isServer ? server_tls_context :
client_tls_context;
+ result->magic = TOR_TLS_MAGIC;
tor_assert(context); /* make sure somebody made it first */
if (!(result->ssl = SSL_new(context->ctx))) {
@@ -1058,7 +1083,14 @@ tor_tls_new(int sock, int isServer)
tor_free(result);
return NULL;
}
- HT_INSERT(tlsmap, &tlsmap_root, result);
+ {
+ int set_worked =
+ SSL_set_ex_data(result->ssl, tor_tls_object_ex_data_index, result);
+ if (!set_worked) {
+ log_warn(LD_BUG,
+ "Couldn't set the tls for an SSL*; connection will fail");
+ }
+ }
SSL_set_bio(result->ssl, bio, bio);
tor_tls_context_incref(context);
result->context = context;
@@ -1074,8 +1106,11 @@ tor_tls_new(int sock, int isServer)
#ifdef V2_HANDSHAKE_SERVER
if (isServer) {
SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
- }
+ } else
#endif
+ {
+ SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
+ }
/* Not expected to get called. */
tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object");
@@ -1109,7 +1144,7 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
if (cb) {
SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
} else {
- SSL_set_info_callback(tls->ssl, NULL);
+ SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback);
}
#endif
}
@@ -1117,7 +1152,7 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
/** If this version of openssl requires it, turn on renegotiation on
* <b>tls</b>.
*/
-static void
+void
tor_tls_unblock_renegotiation(tor_tls_t *tls)
{
/* Yes, we know what we are doing here. No, we do not treat a renegotiation
@@ -1141,6 +1176,19 @@ tor_tls_block_renegotiation(tor_tls_t *tls)
tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
}
+void
+tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
+{
+ if (use_unsafe_renegotiation_flag) {
+ tor_assert(0 != (tls->ssl->s3->flags &
+ SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+ }
+ if (use_unsafe_renegotiation_op) {
+ long options = SSL_get_options(tls->ssl);
+ tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+ }
+}
+
/** Return whether this tls initiated the connect (client) or
* received it (server). */
int
@@ -1156,14 +1204,9 @@ tor_tls_is_server(tor_tls_t *tls)
void
tor_tls_free(tor_tls_t *tls)
{
- tor_tls_t *removed;
if (!tls)
return;
tor_assert(tls->ssl);
- removed = HT_REMOVE(tlsmap, &tlsmap_root, tls);
- if (!removed) {
- log_warn(LD_BUG, "Freeing a TLS that was not in the ssl->tls map.");
- }
#ifdef SSL_set_tlsext_host_name
SSL_set_tlsext_host_name(tls->ssl, NULL);
#endif
@@ -1173,6 +1216,7 @@ tor_tls_free(tor_tls_t *tls)
if (tls->context)
tor_tls_context_decref(tls->context);
tor_free(tls->address);
+ tls->magic = 0x99999999;
tor_free(tls);
}
@@ -1285,56 +1329,86 @@ tor_tls_handshake(tor_tls_t *tls)
}
if (r == TOR_TLS_DONE) {
tls->state = TOR_TLS_ST_OPEN;
- if (tls->isServer) {
- SSL_set_info_callback(tls->ssl, NULL);
- SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
- /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
- tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
+ return tor_tls_finish_handshake(tls);
+ }
+ return r;
+}
+
+/** Perform the final part of the intial TLS handshake on <b>tls</b>. This
+ * should be called for the first handshake only: it determines whether the v1
+ * or the v2 handshake was used, and adjusts things for the renegotiation
+ * handshake as appropriate.
+ *
+ * tor_tls_handshake() calls this on its own; you only need to call this if
+ * bufferevent is doing the handshake for you.
+ */
+int
+tor_tls_finish_handshake(tor_tls_t *tls)
+{
+ int r = TOR_TLS_DONE;
+ if (tls->isServer) {
+ SSL_set_info_callback(tls->ssl, NULL);
+ SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
+ /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
+ tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
#ifdef V2_HANDSHAKE_SERVER
- if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
- /* This check is redundant, but back when we did it in the callback,
- * we might have not been able to look up the tor_tls_t if the code
- * was buggy. Fixing that. */
- if (!tls->wasV2Handshake) {
- log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
- " get set. Fixing that.");
- }
- tls->wasV2Handshake = 1;
- log_debug(LD_HANDSHAKE,
- "Completed V2 TLS handshake with client; waiting "
- "for renegotiation.");
- } else {
- tls->wasV2Handshake = 0;
+ if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
+ /* This check is redundant, but back when we did it in the callback,
+ * we might have not been able to look up the tor_tls_t if the code
+ * was buggy. Fixing that. */
+ if (!tls->wasV2Handshake) {
+ log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
+ " get set. Fixing that.");
}
-#endif
+ tls->wasV2Handshake = 1;
+ log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
+ " for renegotiation.");
} else {
+ tls->wasV2Handshake = 0;
+ }
+#endif
+ } else {
#ifdef V2_HANDSHAKE_CLIENT
- /* If we got no ID cert, we're a v2 handshake. */
- X509 *cert = SSL_get_peer_certificate(tls->ssl);
- STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
- int n_certs = sk_X509_num(chain);
- if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
- log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
- "looks like a v1 handshake on %p", tls);
- tls->wasV2Handshake = 0;
- } else {
- log_debug(LD_HANDSHAKE,
- "Server sent back a single certificate; looks like "
- "a v2 handshake on %p.", tls);
- tls->wasV2Handshake = 1;
- }
- if (cert)
- X509_free(cert);
+ /* If we got no ID cert, we're a v2 handshake. */
+ X509 *cert = SSL_get_peer_certificate(tls->ssl);
+ STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
+ int n_certs = sk_X509_num(chain);
+ if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
+ log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
+ "looks like a v1 handshake on %p", tls);
+ tls->wasV2Handshake = 0;
+ } else {
+ log_debug(LD_HANDSHAKE,
+ "Server sent back a single certificate; looks like "
+ "a v2 handshake on %p.", tls);
+ tls->wasV2Handshake = 1;
+ }
+ if (cert)
+ X509_free(cert);
#endif
- if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
- tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
- r = TOR_TLS_ERROR_MISC;
- }
+ if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
+ tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
+ r = TOR_TLS_ERROR_MISC;
}
}
return r;
}
+#ifdef USE_BUFFEREVENTS
+/** Put <b>tls</b>, which must be a client connection, into renegotiation
+ * mode. */
+int
+tor_tls_start_renegotiating(tor_tls_t *tls)
+{
+ int r = SSL_renegotiate(tls->ssl);
+ if (r <= 0) {
+ return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN,
+ LD_HANDSHAKE);
+ }
+ return 0;
+}
+#endif
+
/** Client only: Renegotiate a TLS session. When finished, returns
* TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or
* TOR_TLS_WANTWRITE.
@@ -1551,6 +1625,8 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key)
log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
goto done;
}
+ tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");
+
if (!(id_pkey = X509_get_pubkey(id_cert)) ||
X509_verify(cert, id_pkey) <= 0) {
log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
@@ -1700,6 +1776,22 @@ tor_tls_used_v1_handshake(tor_tls_t *tls)
return 1;
}
+/** Return the number of server handshakes that we've noticed doing on
+ * <b>tls</b>. */
+int
+tor_tls_get_num_server_handshakes(tor_tls_t *tls)
+{
+ return tls->server_handshake_count;
+}
+
+/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
+ * request it was waiting for. */
+int
+tor_tls_server_got_renegotiate(tor_tls_t *tls)
+{
+ return tls->got_renegotiate;
+}
+
/** Examine the amount of memory used and available for buffers in <b>tls</b>.
* Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
* buffer and *<b>rbuf_bytes</b> to the amount actually used.
@@ -1722,3 +1814,71 @@ tor_tls_get_buffer_sizes(tor_tls_t *tls,
*wbuf_bytes = tls->ssl->s3->wbuf.left;
}
+#ifdef USE_BUFFEREVENTS
+/** Construct and return an TLS-encrypting bufferevent to send data over
+ * <b>socket</b>, which must match the socket of the underlying bufferevent
+ * <b>bufev_in</b>. The TLS object <b>tls</b> is used for encryption.
+ *
+ * This function will either create a filtering bufferevent that wraps around
+ * <b>bufev_in</b>, or it will free bufev_in and return a new bufferevent that
+ * uses the <b>tls</b> to talk to the network directly. Do not use
+ * <b>bufev_in</b> after calling this function.
+ *
+ * The connection will start out doing a server handshake if <b>receiving</b>
+ * is strue, and a client handshake otherwise.
+ *
+ * Returns NULL on failure.
+ */
+struct bufferevent *
+tor_tls_init_bufferevent(tor_tls_t *tls, struct bufferevent *bufev_in,
+ evutil_socket_t socket, int receiving,
+ int filter)
+{
+ struct bufferevent *out;
+ const enum bufferevent_ssl_state state = receiving ?
+ BUFFEREVENT_SSL_ACCEPTING : BUFFEREVENT_SSL_CONNECTING;
+
+ if (filter) {
+ /* Grab an extra reference to the SSL, since BEV_OPT_CLOSE_ON_FREE
+ means that the SSL will get freed too.
+
+ This increment makes our SSL usage not-threadsafe, BTW. We should
+ see if we're allowed to use CRYPTO_add from outside openssl. */
+ tls->ssl->references += 1;
+ out = bufferevent_openssl_filter_new(tor_libevent_get_base(),
+ bufev_in,
+ tls->ssl,
+ state,
+ BEV_OPT_DEFER_CALLBACKS|
+ BEV_OPT_CLOSE_ON_FREE);
+ } else {
+ if (bufev_in) {
+ evutil_socket_t s = bufferevent_getfd(bufev_in);
+ tor_assert(s == -1 || s == socket);
+ tor_assert(evbuffer_get_length(bufferevent_get_input(bufev_in)) == 0);
+ tor_assert(evbuffer_get_length(bufferevent_get_output(bufev_in)) == 0);
+ tor_assert(BIO_number_read(SSL_get_rbio(tls->ssl)) == 0);
+ tor_assert(BIO_number_written(SSL_get_rbio(tls->ssl)) == 0);
+ bufferevent_free(bufev_in);
+ }
+
+ /* Current versions (as of 2.0.x) of Libevent need to defer
+ * bufferevent_openssl callbacks, or else our callback functions will
+ * get called reentrantly, which is bad for us.
+ */
+ out = bufferevent_openssl_socket_new(tor_libevent_get_base(),
+ socket,
+ tls->ssl,
+ state,
+ BEV_OPT_DEFER_CALLBACKS);
+ }
+ tls->state = TOR_TLS_ST_BUFFEREVENT;
+
+ /* Unblock _after_ creating the bufferevent, since accept/connect tend to
+ * clear flags. */
+ tor_tls_unblock_renegotiation(tls);
+
+ return out;
+}
+#endif
+
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 55fee81ae..ecb5bd2fb 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -67,8 +67,11 @@ int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance);
int tor_tls_read(tor_tls_t *tls, char *cp, size_t len);
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
int tor_tls_handshake(tor_tls_t *tls);
+int tor_tls_finish_handshake(tor_tls_t *tls);
int tor_tls_renegotiate(tor_tls_t *tls);
+void tor_tls_unblock_renegotiation(tor_tls_t *tls);
void tor_tls_block_renegotiation(tor_tls_t *tls);
+void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls);
int tor_tls_shutdown(tor_tls_t *tls);
int tor_tls_get_pending_bytes(tor_tls_t *tls);
size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
@@ -81,12 +84,24 @@ void tor_tls_get_buffer_sizes(tor_tls_t *tls,
size_t *wbuf_capacity, size_t *wbuf_bytes);
int tor_tls_used_v1_handshake(tor_tls_t *tls);
+int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
+int tor_tls_server_got_renegotiate(tor_tls_t *tls);
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
*/
#define check_no_tls_errors() _check_no_tls_errors(__FILE__,__LINE__)
void _check_no_tls_errors(const char *fname, int line);
+void tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
+ int severity, int domain, const char *doing);
+
+#ifdef USE_BUFFEREVENTS
+int tor_tls_start_renegotiating(tor_tls_t *tls);
+struct bufferevent *tor_tls_init_bufferevent(tor_tls_t *tls,
+ struct bufferevent *bufev_in,
+ evutil_socket_t socket, int receiving,
+ int filter);
+#endif
#endif
diff --git a/src/common/util.c b/src/common/util.c
index 7ffe0a98c..b95ee3a61 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE
#include "orconfig.h"
+#define UTIL_PRIVATE
#include "util.h"
#include "torlog.h"
#undef log
@@ -775,13 +776,17 @@ tor_digest256_is_zero(const char *digest)
if (next) *next = endptr; \
return 0
-/** Extract a long from the start of s, in the given numeric base. If
- * there is unconverted data and next is provided, set *next to the
- * first unconverted character. An error has occurred if no characters
- * are converted; or if there are unconverted characters and next is NULL; or
- * if the parsed value is not between min and max. When no error occurs,
- * return the parsed value and set *ok (if provided) to 1. When an error
- * occurs, return 0 and set *ok (if provided) to 0.
+/** Extract a long from the start of <b>s</b>, in the given numeric
+ * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
+ * octal, or hex number in the syntax of a C integer literal. If
+ * there is unconverted data and <b>next</b> is provided, set
+ * *<b>next</b> to the first unconverted character. An error has
+ * occurred if no characters are converted; or if there are
+ * unconverted characters and <b>next</b> is NULL; or if the parsed
+ * value is not between <b>min</b> and <b>max</b>. When no error
+ * occurs, return the parsed value and set *<b>ok</b> (if provided) to
+ * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
+ * to 0.
*/
long
tor_parse_long(const char *s, int base, long min, long max,
@@ -948,7 +953,7 @@ esc_for_log(const char *s)
char *result, *outp;
size_t len = 3;
if (!s) {
- return tor_strdup("");
+ return tor_strdup("(null)");
}
for (cp = s; *cp; ++cp) {
@@ -1568,7 +1573,7 @@ rate_limit_log(ratelim_t *lim, time_t now)
* was returned by open(). Return the number of bytes written, or -1
* on error. Only use if fd is a blocking fd. */
ssize_t
-write_all(int fd, const char *buf, size_t count, int isSocket)
+write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket)
{
size_t written = 0;
ssize_t result;
@@ -1578,7 +1583,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket)
if (isSocket)
result = tor_socket_send(fd, buf+written, count-written, 0);
else
- result = write(fd, buf+written, count-written);
+ result = write((int)fd, buf+written, count-written);
if (result<0)
return -1;
written += result;
@@ -1592,7 +1597,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket)
* open(). Return the number of bytes read, or -1 on error. Only use
* if fd is a blocking fd. */
ssize_t
-read_all(int fd, char *buf, size_t count, int isSocket)
+read_all(tor_socket_t fd, char *buf, size_t count, int isSocket)
{
size_t numread = 0;
ssize_t result;
@@ -1604,7 +1609,7 @@ read_all(int fd, char *buf, size_t count, int isSocket)
if (isSocket)
result = tor_socket_recv(fd, buf+numread, count-numread, 0);
else
- result = read(fd, buf+numread, count-numread);
+ result = read((int)fd, buf+numread, count-numread);
if (result<0)
return -1;
else if (result == 0)
@@ -1673,15 +1678,21 @@ file_status(const char *fname)
* is group-readable, but in all cases we create the directory mode 0700.
* If CPD_CHECK_MODE_ONLY is set, then we don't alter the directory permissions
* if they are too permissive: we just return -1.
+ * When effective_user is not NULL, check permissions against the given user
+ * and its primary group.
*/
int
-check_private_dir(const char *dirname, cpd_check_t check)
+check_private_dir(const char *dirname, cpd_check_t check,
+ const char *effective_user)
{
int r;
struct stat st;
char *f;
#ifndef MS_WINDOWS
int mask;
+ struct passwd *pw = NULL;
+ uid_t running_uid;
+ gid_t running_gid;
#endif
tor_assert(dirname);
@@ -1720,33 +1731,49 @@ check_private_dir(const char *dirname, cpd_check_t check)
return -1;
}
#ifndef MS_WINDOWS
- if (st.st_uid != getuid()) {
+ if (effective_user) {
+ /* Look up the user and group information.
+ * If we have a problem, bail out. */
+ pw = getpwnam(effective_user);
+ if (pw == NULL) {
+ log_warn(LD_CONFIG, "Error setting configured user: %s not found",
+ effective_user);
+ return -1;
+ }
+ running_uid = pw->pw_uid;
+ running_gid = pw->pw_gid;
+ } else {
+ running_uid = getuid();
+ running_gid = getgid();
+ }
+
+ if (st.st_uid != running_uid) {
struct passwd *pw = NULL;
char *process_ownername = NULL;
- pw = getpwuid(getuid());
+ pw = getpwuid(running_uid);
process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>");
pw = getpwuid(st.st_uid);
log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
"%s (%d). Perhaps you are running Tor as the wrong user?",
- dirname, process_ownername, (int)getuid(),
+ dirname, process_ownername, (int)running_uid,
pw ? pw->pw_name : "<unknown>", (int)st.st_uid);
tor_free(process_ownername);
return -1;
}
- if ((check & CPD_GROUP_OK) && st.st_gid != getgid()) {
+ if ((check & CPD_GROUP_OK) && st.st_gid != running_gid) {
struct group *gr;
char *process_groupname = NULL;
- gr = getgrgid(getgid());
+ gr = getgrgid(running_gid);
process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>");
gr = getgrgid(st.st_gid);
log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group "
"%s (%d). Are you running Tor as the wrong user?",
- dirname, process_groupname, (int)getgid(),
+ dirname, process_groupname, (int)running_gid,
gr ? gr->gr_name : "<unknown>", (int)st.st_gid);
tor_free(process_groupname);
@@ -1865,7 +1892,7 @@ start_writing_to_file(const char *fname, int open_flags, int mode,
if (open_flags & O_BINARY)
new_file->binary = 1;
- new_file->fd = open(open_name, open_flags, mode);
+ new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
if (new_file->fd < 0) {
log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
open_name, fname, strerror(errno));
@@ -2086,7 +2113,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
tor_assert(filename);
- fd = open(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
+ fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
if (fd<0) {
int severity = LOG_WARN;
int save_errno = errno;
@@ -2472,18 +2499,21 @@ digit_to_num(char d)
* success, store the result in <b>out</b>, advance bufp to the next
* character, and return 0. On failure, return -1. */
static int
-scan_unsigned(const char **bufp, unsigned *out, int width)
+scan_unsigned(const char **bufp, unsigned *out, int width, int base)
{
unsigned result = 0;
int scanned_so_far = 0;
+ const int hex = base==16;
+ tor_assert(base == 10 || base == 16);
if (!bufp || !*bufp || !out)
return -1;
if (width<0)
width=MAX_SCANF_WIDTH;
- while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
- int digit = digit_to_num(*(*bufp)++);
- unsigned new_result = result * 10 + digit;
+ while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
+ && scanned_so_far < width) {
+ int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
+ unsigned new_result = result * base + digit;
if (new_result > UINT32_MAX || new_result < result)
return -1; /* over/underflow. */
result = new_result;
@@ -2545,11 +2575,12 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
if (!width) /* No zero-width things. */
return -1;
}
- if (*pattern == 'u') {
+ if (*pattern == 'u' || *pattern == 'x') {
unsigned *u = va_arg(ap, unsigned *);
+ const int base = (*pattern == 'u') ? 10 : 16;
if (!*buf)
return n_matched;
- if (scan_unsigned(&buf, u, width)<0)
+ if (scan_unsigned(&buf, u, width, base)<0)
return n_matched;
++pattern;
++n_matched;
@@ -2586,9 +2617,9 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b>
* and store the results in the corresponding argument fields. Differs from
- * sscanf in that it: Only handles %u and %Ns. Does not handle arbitrarily
- * long widths. %u does not consume any space. Is locale-independent.
- * Returns -1 on malformed patterns.
+ * sscanf in that it: Only handles %u and %x and %Ns. Does not handle
+ * arbitrarily long widths. %u and %x do not consume any space. Is
+ * locale-independent. Returns -1 on malformed patterns.
*
* (As with other locale-independent functions, we need this to parse data that
* is in ASCII without worrying that the C library's locale-handling will make
@@ -2782,7 +2813,7 @@ finish_daemon(const char *desired_cwd)
exit(1);
}
- nullfd = open("/dev/null", O_RDWR);
+ nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
if (nullfd < 0) {
log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
exit(1);
@@ -2853,3 +2884,451 @@ load_windows_system_library(const TCHAR *library_name)
}
#endif
+/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
+ * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
+ * safe.
+ *
+ * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE bytes available.
+ *
+ * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
+ * with spaces. Note that there is no trailing \0. CHILD_STATE indicates where
+ * in the processs of starting the child process did the failure occur (see
+ * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
+ * errno when the failure occurred.
+ */
+
+void
+format_helper_exit_status(unsigned char child_state, int saved_errno,
+ char *hex_errno)
+{
+ unsigned int unsigned_errno;
+ char *cur;
+ size_t i;
+
+ /* Fill hex_errno with spaces, and a trailing newline (memset may
+ not be signal handler safe, so we can't use it) */
+ for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
+ hex_errno[i] = ' ';
+ hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
+
+ /* Convert errno to be unsigned for hex conversion */
+ if (saved_errno < 0) {
+ unsigned_errno = (unsigned int) -saved_errno;
+ } else {
+ unsigned_errno = (unsigned int) saved_errno;
+ }
+
+ /* Convert errno to hex (start before \n) */
+ cur = hex_errno + HEX_ERRNO_SIZE - 2;
+
+ /* Check for overflow on first iteration of the loop */
+ if (cur < hex_errno)
+ return;
+
+ do {
+ *cur-- = "0123456789ABCDEF"[unsigned_errno % 16];
+ unsigned_errno /= 16;
+ } while (unsigned_errno != 0 && cur >= hex_errno);
+
+ /* Prepend the minus sign if errno was negative */
+ if (saved_errno < 0 && cur >= hex_errno)
+ *cur-- = '-';
+
+ /* Leave a gap */
+ if (cur >= hex_errno)
+ *cur-- = '/';
+
+ /* Check for overflow on first iteration of the loop */
+ if (cur < hex_errno)
+ return;
+
+ /* Convert child_state to hex */
+ do {
+ *cur-- = "0123456789ABCDEF"[child_state % 16];
+ child_state /= 16;
+ } while (child_state != 0 && cur >= hex_errno);
+}
+
+/* Maximum number of file descriptors, if we cannot get it via sysconf() */
+#define DEFAULT_MAX_FD 256
+
+#define CHILD_STATE_INIT 0
+#define CHILD_STATE_PIPE 1
+#define CHILD_STATE_MAXFD 2
+#define CHILD_STATE_FORK 3
+#define CHILD_STATE_DUPOUT 4
+#define CHILD_STATE_DUPERR 5
+#define CHILD_STATE_REDIRECT 6
+#define CHILD_STATE_CLOSEFD 7
+#define CHILD_STATE_EXEC 8
+#define CHILD_STATE_FAILEXEC 9
+
+#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code "
+
+/** Start a program in the background. If <b>filename</b> contains a '/',
+ * then it will be treated as an absolute or relative path. Otherwise the
+ * system path will be searched for <b>filename</b>. The strings in
+ * <b>argv</b> will be passed as the command line arguments of the child
+ * program (following convention, argv[0] should normally be the filename of
+ * the executable). The last element of argv must be NULL. If the child
+ * program is launched, the PID will be returned and <b>stdout_read</b> and
+ * <b>stdout_err</b> will be set to file descriptors from which the stdout
+ * and stderr, respectively, output of the child program can be read, and the
+ * stdin of the child process shall be set to /dev/null. Otherwise returns
+ * -1. Some parts of this code are based on the POSIX subprocess module from
+ * Python.
+ */
+int
+tor_spawn_background(const char *const filename, int *stdout_read,
+ int *stderr_read, const char **argv)
+{
+#ifdef MS_WINDOWS
+ (void) filename; (void) stdout_read; (void) stderr_read; (void) argv;
+ log_warn(LD_BUG, "not yet implemented on Windows.");
+ return -1;
+#else
+ pid_t pid;
+ int stdout_pipe[2];
+ int stderr_pipe[2];
+ int fd, retval;
+ ssize_t nbytes;
+
+ const char *error_message = SPAWN_ERROR_MESSAGE;
+ size_t error_message_length;
+
+ /* Represents where in the process of spawning the program is;
+ this is used for printing out the error message */
+ unsigned char child_state = CHILD_STATE_INIT;
+
+ char hex_errno[HEX_ERRNO_SIZE];
+
+ static int max_fd = -1;
+
+ /* We do the strlen here because strlen() is not signal handler safe,
+ and we are not allowed to use unsafe functions between fork and exec */
+ error_message_length = strlen(error_message);
+
+ child_state = CHILD_STATE_PIPE;
+
+ /* Set up pipe for redirecting stdout and stderr of child */
+ retval = pipe(stdout_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stdout communication with child process: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ retval = pipe(stderr_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stderr communication with child process: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ child_state = CHILD_STATE_MAXFD;
+
+#ifdef _SC_OPEN_MAX
+ if (-1 != max_fd) {
+ max_fd = (int) sysconf(_SC_OPEN_MAX);
+ if (max_fd == -1)
+ max_fd = DEFAULT_MAX_FD;
+ log_warn(LD_GENERAL,
+ "Cannot find maximum file descriptor, assuming %d", max_fd);
+ }
+#else
+ max_fd = DEFAULT_MAX_FD;
+#endif
+
+ child_state = CHILD_STATE_FORK;
+
+ pid = fork();
+ if (0 == pid) {
+ /* In child */
+
+ child_state = CHILD_STATE_DUPOUT;
+
+ /* Link child stdout to the write end of the pipe */
+ retval = dup2(stdout_pipe[1], STDOUT_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_DUPERR;
+
+ /* Link child stderr to the write end of the pipe */
+ retval = dup2(stderr_pipe[1], STDERR_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_REDIRECT;
+
+ /* Link stdin to /dev/null */
+ fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */
+ if (fd != -1)
+ dup2(fd, STDIN_FILENO);
+ else
+ goto error;
+
+ child_state = CHILD_STATE_CLOSEFD;
+
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(fd);
+
+ /* Close all other fds, including the read end of the pipe */
+ /* XXX: We should now be doing enough FD_CLOEXEC setting to make
+ * this needless. */
+ for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
+ close(fd);
+ }
+
+ child_state = CHILD_STATE_EXEC;
+
+ /* Call the requested program. We need the cast because
+ execvp doesn't define argv as const, even though it
+ does not modify the arguments */
+ execvp(filename, (char *const *) argv);
+
+ /* If we got here, the exec or open(/dev/null) failed */
+
+ child_state = CHILD_STATE_FAILEXEC;
+
+ error:
+ /* XXX: are we leaking fds from the pipe? */
+
+ format_helper_exit_status(child_state, errno, hex_errno);
+
+ /* Write the error message. GCC requires that we check the return
+ value, but there is nothing we can do if it fails */
+ nbytes = write(STDOUT_FILENO, error_message, error_message_length);
+ nbytes = write(STDOUT_FILENO, hex_errno, sizeof(hex_errno));
+
+ (void) nbytes;
+
+ _exit(255);
+ return -1; /* Never reached, but avoids compiler warning */
+ }
+
+ /* In parent */
+
+ if (-1 == pid) {
+ log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ return -1;
+ }
+
+ /* Return read end of the pipes to caller, and close write end */
+ *stdout_read = stdout_pipe[0];
+ retval = close(stdout_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stdout pipe in parent process: %s",
+ strerror(errno));
+ /* Do not return -1, because the child is running, so the parent
+ needs to know about the pid in order to reap it later */
+ }
+
+ *stderr_read = stderr_pipe[0];
+ retval = close(stderr_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stderr pipe in parent process: %s",
+ strerror(errno));
+ /* Do not return -1, because the child is running, so the parent
+ needs to know about the pid in order to reap it later */
+ }
+
+ return pid;
+#endif
+}
+
+/** Read from stream, and send lines to log at the specified log level.
+ * Returns 1 if stream is closed normally, -1 if there is a error reading, and
+ * 0 otherwise. Handles lines from tor-fw-helper and
+ * tor_spawn_background() specially.
+ */
+static int
+log_from_pipe(FILE *stream, int severity, const char *executable,
+ int *child_status)
+{
+ char buf[256];
+
+ for (;;) {
+ char *retval;
+ retval = fgets(buf, sizeof(buf), stream);
+
+ if (NULL == retval) {
+ if (feof(stream)) {
+ /* Program has closed stream (probably it exited) */
+ /* TODO: check error */
+ fclose(stream);
+ return 1;
+ } else {
+ if (EAGAIN == errno) {
+ /* Nothing more to read, try again next time */
+ return 0;
+ } else {
+ /* There was a problem, abandon this child process */
+ fclose(stream);
+ return -1;
+ }
+ }
+ } else {
+ /* We have some data, log it and keep asking for more */
+ size_t len;
+
+ len = strlen(buf);
+ if (buf[len - 1] == '\n') {
+ /* Remove the trailing newline */
+ buf[len - 1] = '\0';
+ } else {
+ /* No newline; check whether we overflowed the buffer */
+ if (!feof(stream))
+ log_warn(LD_GENERAL,
+ "Line from port forwarding helper was truncated: %s", buf);
+ /* TODO: What to do with this error? */
+ }
+
+ /* Check if buf starts with SPAWN_ERROR_MESSAGE */
+ if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) {
+ /* Parse error message */
+ int retval, child_state, saved_errno;
+ retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x",
+ &child_state, &saved_errno);
+ if (retval == 2) {
+ log_warn(LD_GENERAL,
+ "Failed to start child process \"%s\" in state %d: %s",
+ executable, child_state, strerror(saved_errno));
+ if (child_status)
+ *child_status = 1;
+ } else {
+ /* Failed to parse message from child process, log it as a
+ warning */
+ log_warn(LD_GENERAL,
+ "Unexpected message from port forwarding helper \"%s\": %s",
+ executable, buf);
+ }
+ } else {
+ log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf);
+ }
+ }
+ }
+
+ /* We should never get here */
+ return -1;
+}
+
+void
+tor_check_port_forwarding(const char *filename, int dir_port, int or_port,
+ time_t now)
+{
+#ifdef MS_WINDOWS
+ (void) filename; (void) dir_port; (void) or_port; (void) now;
+ (void) tor_spawn_background;
+ (void) log_from_pipe;
+ log_warn(LD_GENERAL, "Sorry, port forwarding is not yet supported "
+ "on windows.");
+#else
+/* When fw-helper succeeds, how long do we wait until running it again */
+#define TIME_TO_EXEC_FWHELPER_SUCCESS 300
+/* When fw-helper fails, how long do we wait until running it again */
+#define TIME_TO_EXEC_FWHELPER_FAIL 60
+
+ static int child_pid = -1;
+ static FILE *stdout_read = NULL;
+ static FILE *stderr_read = NULL;
+ static time_t time_to_run_helper = 0;
+ int stdout_status, stderr_status, retval;
+ const char *argv[10];
+ char s_dirport[6], s_orport[6];
+
+ tor_assert(filename);
+
+ /* Set up command line for tor-fw-helper */
+ snprintf(s_dirport, sizeof s_dirport, "%d", dir_port);
+ snprintf(s_orport, sizeof s_orport, "%d", or_port);
+
+ /* TODO: Allow different internal and external ports */
+ argv[0] = filename;
+ argv[1] = "--internal-or-port";
+ argv[2] = s_orport;
+ argv[3] = "--external-or-port";
+ argv[4] = s_orport;
+ argv[5] = "--internal-dir-port";
+ argv[6] = s_dirport;
+ argv[7] = "--external-dir-port";
+ argv[8] = s_dirport;
+ argv[9] = NULL;
+
+ /* Start the child, if it is not already running */
+ if (-1 == child_pid &&
+ time_to_run_helper < now) {
+ int fd_out=-1, fd_err=-1;
+
+ /* Assume tor-fw-helper will succeed, start it later*/
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS;
+
+ child_pid = tor_spawn_background(filename, &fd_out, &fd_err, argv);
+ if (child_pid < 0) {
+ log_warn(LD_GENERAL, "Failed to start port forwarding helper %s",
+ filename);
+ child_pid = -1;
+ return;
+ }
+ /* Set stdout/stderr pipes to be non-blocking */
+ fcntl(fd_out, F_SETFL, O_NONBLOCK);
+ fcntl(fd_err, F_SETFL, O_NONBLOCK);
+ /* Open the buffered IO streams */
+ stdout_read = fdopen(fd_out, "r");
+ stderr_read = fdopen(fd_err, "r");
+
+ log_info(LD_GENERAL,
+ "Started port forwarding helper (%s) with pid %d", filename, child_pid);
+ }
+
+ /* If child is running, read from its stdout and stderr) */
+ if (child_pid > 0) {
+ /* Read from stdout/stderr and log result */
+ retval = 0;
+ stdout_status = log_from_pipe(stdout_read, LOG_INFO, filename, &retval);
+ stderr_status = log_from_pipe(stderr_read, LOG_WARN, filename, &retval);
+ if (retval) {
+ /* There was a problem in the child process */
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
+ }
+
+ /* Combine the two statuses in order of severity */
+ if (-1 == stdout_status || -1 == stderr_status)
+ /* There was a failure */
+ retval = -1;
+ else if (1 == stdout_status || 1 == stderr_status)
+ /* stdout or stderr was closed */
+ retval = 1;
+ else
+ /* Both are fine */
+ retval = 0;
+
+ /* If either pipe indicates a failure, act on it */
+ if (0 != retval) {
+ if (1 == retval) {
+ log_info(LD_GENERAL, "Port forwarding helper terminated");
+ } else {
+ log_warn(LD_GENERAL, "Failed to read from port forwarding helper");
+ }
+
+ /* TODO: The child might not actually be finished (maybe it failed or
+ closed stdout/stderr), so maybe we shouldn't start another? */
+ child_pid = -1;
+ }
+ }
+#endif
+}
+
diff --git a/src/common/util.h b/src/common/util.h
index f32709acc..6496c42db 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -276,8 +276,8 @@ typedef struct ratelim_t {
char *rate_limit_log(ratelim_t *lim, time_t now);
/* File helpers */
-ssize_t write_all(int fd, const char *buf, size_t count, int isSocket);
-ssize_t read_all(int fd, char *buf, size_t count, int isSocket);
+ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket);
+ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket);
/** Return values from file_status(); see that function's documentation
* for details. */
@@ -292,7 +292,8 @@ typedef unsigned int cpd_check_t;
#define CPD_CHECK 2
#define CPD_GROUP_OK 4
#define CPD_CHECK_MODE_ONLY 8
-int check_private_dir(const char *dirname, cpd_check_t check);
+int check_private_dir(const char *dirname, cpd_check_t check,
+ const char *effective_user);
#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
typedef struct open_file_t open_file_t;
@@ -336,10 +337,27 @@ void start_daemon(void);
void finish_daemon(const char *desired_cwd);
void write_pidfile(char *filename);
+/* Port forwarding */
+void tor_check_port_forwarding(const char *filename,
+ int dir_port, int or_port, time_t now);
+
#ifdef MS_WINDOWS
HANDLE load_windows_system_library(const TCHAR *library_name);
#endif
+#ifdef UTIL_PRIVATE
+/* Prototypes for private functions only used by util.c (and unit tests) */
+int tor_spawn_background(const char *const filename, int *stdout_read,
+ int *stderr_read, const char **argv);
+void format_helper_exit_status(unsigned char child_state,
+ int saved_errno, char *hex_errno);
+
+/* Space for hex values of child state, a slash, saved_errno (with
+ leading minus) and newline (no null) */
+#define HEX_ERRNO_SIZE (sizeof(char) * 2 + 1 + \
+ 1 + sizeof(int) * 2 + 1)
+#endif
+
const char *libor_get_digests(void);
#endif
diff --git a/src/config/geoip b/src/config/geoip
index 465c13be7..8d64d312d 100644
--- a/src/config/geoip
+++ b/src/config/geoip
@@ -1,4 +1,4 @@
-# Last updated based on May 1 2011 Maxmind GeoLite Country
+# Last updated based on June 1 2011 Maxmind GeoLite Country
# wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
# cut -d, -f3-5 < GeoIPCountryWhois.csv|sed 's/"//g' > geoip
16777216,16777471,AU
@@ -104,17 +104,26 @@
34928384,34928639,DE
34928640,34930687,EU
34930688,34938879,DE
-34938880,34952703,EU
-34952704,34953215,ES
+34938880,34947071,FR
+34947072,34952703,EU
+34952704,34953215,SE
34953216,34954751,AT
34954752,34955263,NL
34955264,34959359,AT
34959360,34963455,NL
34963456,34992127,EU
34992128,34993151,NL
-34993152,34993663,EU
+34993152,34993663,FR
34993664,34993919,AT
-34993920,35127295,EU
+34993920,34994175,DE
+34994176,34995711,FR
+34995712,34995967,EU
+34995968,34996223,NL
+34996224,35000319,EU
+35000320,35002367,SE
+35002368,35069951,EU
+35069952,35078143,SE
+35078144,35127295,EU
35127296,35651583,GB
35651584,36700159,IT
36700160,36962303,AE
@@ -371,8 +380,12 @@
210439560,210439567,PR
210439568,210784255,US
210784256,210784383,BO
-210784384,210784767,US
-210784768,210786303,BO
+210784384,210785023,US
+210785024,210785575,BO
+210785576,210785583,US
+210785584,210785599,BO
+210785600,210785663,US
+210785664,210786303,BO
210786304,210970847,US
210970848,210970855,PR
210970856,211051199,US
@@ -928,7 +941,6 @@
452997120,453001215,IN
453001216,453009407,AU
453009408,453017599,BD
-453017600,453050367,JP
453050368,453115903,KR
453115904,453246975,VN
453246976,453509119,IN
@@ -1378,7 +1390,9 @@
522715136,522717183,IR
522717184,522719231,RU
522719232,522721279,UA
-522721280,522739711,RU
+522721280,522741759,RU
+522741760,522743807,UA
+522743808,522747903,RU
522747904,522780671,UA
522780672,522782719,RU
522782720,522784767,UA
@@ -1468,7 +1482,20 @@
528605184,528613375,UA
528613376,528637951,RU
528637952,528642047,PL
-528642048,528646143,RU
+528642048,528654335,RU
+528654336,528656383,SK
+528656384,528658431,CZ
+528658432,528662527,IR
+528662528,528664575,RU
+528664576,528666623,BY
+528666624,528668671,RU
+528668672,528670719,PL
+528670720,528674815,CH
+528674816,528676863,RO
+528676864,528678911,RU
+528678912,528680959,MD
+528680960,528683007,RO
+528683008,528689151,UA
528809984,528812031,PL
528812032,528814079,CZ
528814080,528816127,PL
@@ -1478,11 +1505,18 @@
528836608,528838655,RU
528838656,528840703,UA
528840704,528842751,RU
-528875520,528887807,RU
+528842752,528859135,CH
+528863232,528867327,KZ
+528867328,528887807,RU
528887808,528891903,PL
528891904,528900095,UA
528900096,528902143,SK
528902144,528908287,UA
+528908288,528926719,RU
+528926720,528928767,NL
+528928768,528930815,UA
+528930816,528932863,CZ
+528932864,528941055,RU
529006592,529268735,NL
529268736,529530879,TR
529530880,529596415,UA
@@ -1528,7 +1562,8 @@
530972672,531103743,SA
531103744,531169279,IL
531169280,531177471,KZ
-531177472,531183615,GB
+531177472,531179519,GB
+531181568,531183615,GB
531183616,531185663,NL
531185664,531193855,TR
531193856,531195903,IE
@@ -1549,15 +1584,18 @@
531263488,531265535,RU
531265536,531267583,GB
531267584,531275775,UA
-531275776,531277823,LT
+531275776,531277823,US
531277824,531279871,RU
531281920,531283967,RU
531283968,531292159,DE
531292160,531333119,AZ
531333120,531333599,NL
531333600,531333631,RU
-531333632,531334399,NL
-531334400,531334655,SE
+531333632,531334143,NL
+531334144,531334207,US
+531334208,531334399,NL
+531334400,531334463,US
+531334464,531334655,NL
531334656,531335167,US
531335168,531337215,IT
531337216,531339263,CH
@@ -1573,7 +1611,8 @@
531369984,531371007,CH
531371008,531371519,US
531371520,531372031,JP
-531372032,531398655,CH
+531372032,531380223,CH
+531380224,531398655,DE
531398656,531400703,RU
531400704,531402751,UA
531402752,531404799,LU
@@ -1642,7 +1681,9 @@
532414464,532676607,IT
532676608,532692991,GE
532692992,532701183,CZ
-532703232,532705279,RU
+532703232,532704511,RU
+532704512,532704767,IN
+532704768,532705279,RU
532705280,532709375,NL
532709376,532725759,RU
532725760,532729855,SE
@@ -1652,7 +1693,15 @@
532736000,532738047,RU
532738048,532740095,GB
532740096,532742143,KG
-532742144,532746239,GB
+532742144,532742655,GB
+532742656,532742783,CN
+532742784,532743167,GB
+532743168,532743423,CN
+532743424,532743679,GB
+532743680,532743807,DE
+532743808,532744095,GB
+532744096,532744127,CN
+532744128,532746239,GB
532746240,532750335,IT
532750336,532752383,SM
532752384,532754431,BE
@@ -1684,18 +1733,330 @@
533250048,533262335,RU
533262336,533264383,ES
533264384,533266431,RU
-533266432,533331967,FR
+533266432,533266687,NL
+533266688,533266943,DE
+533266944,533267199,NL
+533267200,533267455,AX
+533267456,533267711,AL
+533267712,533267967,AD
+533267968,533268223,AM
+533268224,533268479,AT
+533268480,533268735,AZ
+533268736,533268991,BH
+533268992,533269247,BY
+533269248,533269503,BE
+533269504,533269759,BA
+533269760,533270015,BG
+533270016,533270271,HR
+533270272,533270527,CY
+533270528,533270783,CZ
+533270784,533271039,DK
+533271040,533271295,EE
+533271296,533271551,FO
+533271552,533271807,GE
+533271808,533272063,FR
+533272064,533272319,DE
+533272320,533272575,GI
+533272576,533272831,GR
+533272832,533273087,GL
+533273088,533273343,GG
+533273344,533273599,VA
+533273600,533273855,HU
+533273856,533274111,IS
+533274112,533274367,IR
+533274368,533274623,IQ
+533274624,533274879,IE
+533274880,533275135,IM
+533275136,533275391,IL
+533275392,533275647,IT
+533275648,533275903,JE
+533275904,533276159,JO
+533276160,533276415,KZ
+533276416,533276671,KW
+533276672,533276927,KG
+533276928,533277183,LV
+533277184,533277439,LB
+533277440,533277695,LI
+533277696,533277951,LT
+533277952,533278207,LU
+533278208,533278463,MT
+533278464,533278719,MC
+533278720,533278975,ME
+533278976,533279231,NL
+533279232,533279487,NO
+533279488,533279743,OM
+533279744,533279999,PS
+533280000,533280255,PL
+533280256,533280511,PT
+533280512,533280767,RO
+533280768,533281023,RU
+533281024,533281279,SM
+533281280,533281535,SA
+533281536,533281791,RS
+533281792,533282047,SK
+533282048,533282303,SI
+533282304,533282559,ES
+533282560,533282815,SE
+533282816,533283071,CH
+533283072,533283327,SY
+533283328,533283583,TJ
+533283584,533283839,TR
+533283840,533284095,TM
+533284096,533284351,UA
+533284352,533284607,AE
+533284608,533284863,GB
+533284864,533285119,UZ
+533285120,533285375,YE
+533285376,533285631,AX
+533285632,533285887,AL
+533285888,533286143,AD
+533286144,533286399,AM
+533286400,533286655,AT
+533286656,533286911,AZ
+533286912,533287167,BH
+533287168,533287423,BY
+533287424,533287679,BE
+533287680,533287935,BA
+533287936,533288191,BG
+533288192,533288447,HR
+533288448,533288703,CY
+533288704,533288959,CZ
+533288960,533289215,DK
+533289216,533289471,EE
+533289472,533289727,FO
+533289728,533289983,GE
+533289984,533290239,FR
+533290240,533290495,DE
+533290496,533290751,GI
+533290752,533291007,GR
+533291008,533291263,GL
+533291264,533291519,GG
+533291520,533291775,VA
+533291776,533292031,HU
+533292032,533292287,IS
+533292288,533292543,IR
+533292544,533292799,IQ
+533292800,533293055,IE
+533293056,533293311,IM
+533293312,533293567,IL
+533293568,533293823,IT
+533293824,533294079,JE
+533294080,533294335,JO
+533294336,533294591,KZ
+533294592,533294847,KW
+533294848,533295103,KG
+533295104,533295359,LV
+533295360,533295615,LB
+533295616,533295871,LI
+533295872,533296127,LT
+533296128,533296383,LU
+533296384,533296639,MT
+533296640,533296895,MC
+533296896,533297151,ME
+533297152,533297407,NL
+533297408,533297663,NO
+533297664,533297919,OM
+533297920,533298175,PT
+533298176,533298431,RO
+533298432,533298687,RU
+533298688,533298943,SM
+533298944,533299199,SA
+533299200,533299455,RS
+533299456,533299711,SK
+533299712,533299967,SI
+533299968,533300223,ES
+533300224,533300479,SE
+533300480,533300735,CH
+533300736,533300991,SY
+533300992,533301247,TJ
+533301248,533301503,TM
+533301504,533301759,UA
+533301760,533302015,AE
+533302016,533302271,GB
+533302272,533302527,UZ
+533302528,533302783,AX
+533302784,533303039,AL
+533303040,533303295,AD
+533303296,533303551,AM
+533303552,533303807,AT
+533303808,533304063,AZ
+533304064,533304319,BH
+533304320,533304575,BY
+533304576,533304831,BE
+533304832,533305087,BA
+533305088,533305343,BG
+533305344,533305599,HR
+533305600,533305855,FR
+533305856,533306111,CZ
+533306112,533306367,FR
+533306368,533306623,EE
+533306624,533306879,FO
+533306880,533307135,GE
+533307136,533307391,FR
+533307392,533307647,DE
+533307648,533307903,GI
+533307904,533308159,GR
+533308160,533308415,GL
+533308416,533308671,GG
+533308672,533308927,VA
+533308928,533309183,HU
+533309184,533309439,IS
+533309440,533309695,IR
+533309696,533309951,IQ
+533309952,533310207,IE
+533310208,533310463,IM
+533310464,533310719,IL
+533310720,533310975,IT
+533310976,533311231,JE
+533311232,533311487,JO
+533311488,533311743,KZ
+533311744,533311999,KW
+533312000,533312255,KG
+533312256,533312511,LV
+533312512,533312767,LB
+533312768,533313023,LI
+533313024,533313279,LT
+533313280,533313535,LU
+533313536,533313791,MT
+533313792,533314047,MC
+533314048,533314303,ME
+533314304,533314559,NL
+533314560,533314815,NO
+533314816,533315071,OM
+533315072,533315327,PT
+533315328,533315583,RO
+533315584,533315839,RU
+533315840,533316095,SM
+533316096,533316351,SA
+533316352,533316607,RS
+533316608,533316863,SK
+533316864,533317119,SI
+533317120,533317375,ES
+533317376,533317631,SE
+533317632,533317887,CH
+533317888,533318143,SY
+533318144,533318399,TJ
+533318400,533318655,TR
+533318656,533318911,TM
+533318912,533319167,UA
+533319168,533319423,AE
+533319424,533319679,GB
+533319680,533319935,UZ
+533319936,533320191,YE
+533320192,533320447,AX
+533320448,533320703,AL
+533320704,533320959,AD
+533320960,533321215,AM
+533321216,533321471,AT
+533321472,533321727,AZ
+533321728,533321983,BH
+533321984,533322495,BE
+533322496,533331967,FR
533331968,533397503,UA
533397504,533463039,KW
533463040,533479423,RU
533481472,533483519,NO
533483520,533485567,FR
+533485568,533487615,LU
533487616,533491711,RU
533491712,533495807,DE
533495808,533503999,NL
+533504000,533512191,RU
533512192,533528575,ME
533528576,533594111,GB
533594112,533659647,TR
+533659648,533676031,CZ
+533676032,533680127,RU
+533680128,533682175,TR
+533682176,533684223,ES
+533684224,533692415,IT
+533692416,533725183,RU
+533725184,533807103,SE
+533807104,533811199,LT
+533811200,533815295,DE
+533815296,533819391,TR
+533819392,533823487,DE
+533823488,533825535,BE
+533827584,533831679,IS
+533831680,533835775,DE
+533835776,533837823,SE
+533837824,533839871,DE
+533839872,533856255,IS
+533856256,533858303,FR
+533858304,533860351,HU
+533860352,533860607,DE
+533860608,533862399,NL
+533862400,533864447,GB
+533864448,533889023,TR
+533889024,533891071,GB
+533891072,533893119,RU
+533893120,533895167,ES
+533895168,533897215,TR
+533897216,533899263,DE
+533899264,533901311,RU
+533901312,533905407,IL
+533905408,533913599,RU
+533913600,533915647,ES
+533915648,533919743,GB
+533919744,533921791,SE
+533921792,533954559,RU
+533954560,533962751,BG
+533962752,533964799,GB
+533964800,533966847,NO
+533966848,533968895,DE
+533968896,533970943,ES
+533970944,533987327,SE
+533987328,534118399,DE
+534118400,534151167,KW
+534151168,534183935,DE
+534183936,534249471,RO
+534249472,534253567,GB
+534253568,534257663,FR
+534257664,534259711,SE
+534259712,534261759,CH
+534261760,534263807,GB
+534263808,534265855,PL
+534265856,534282239,CY
+534282240,534284287,IT
+534284288,534286335,SE
+534286336,534288383,LU
+534288384,534290431,IT
+534290432,534296575,RU
+534296576,534298623,BA
+534298624,534306815,HR
+534306816,534308863,SE
+534308864,534310911,IE
+534310912,534315007,IT
+534315008,534347775,HR
+534380544,534511615,AE
+534511616,534544383,DE
+534544384,534546431,RO
+534546432,534548479,DE
+534548480,534550527,PL
+534550528,534560767,RU
+534560768,534609919,GB
+534609920,534642687,ES
+534642688,534646783,CZ
+534646784,534648831,PL
+534648832,534650879,CH
+534650880,534652927,RU
+534652928,534654975,AL
+534654976,534663167,GB
+534663168,534675455,ES
+534675456,534691839,GB
+534691840,534693887,FR
+534693888,534695935,GB
+534700032,534708223,JO
+534708224,534740991,TR
+534740992,534749183,BA
+534749184,534753279,NL
+534753280,534757375,PS
+534757376,534761471,KZ
+534761472,534765567,BA
+534765568,534767615,UA
+534767616,534769663,HU
+534769664,534773759,IT
+534773760,536870911,DE
536870912,539624567,US
539624568,539624575,IE
539624576,539624703,US
@@ -1986,6 +2347,8 @@
692922368,692924415,NG
692924416,692928511,ZA
692928512,692930559,GH
+692930560,692932607,UG
+692932608,692934655,CM
692969472,692971519,TZ
692973568,692975615,MZ
692975616,692977663,EG
@@ -2050,6 +2413,13 @@
693045248,693046271,KE
693046272,693047295,ZW
693047296,693049343,ZA
+693049344,693050367,SD
+693050368,693051391,ZW
+693051392,693052415,BW
+693052416,693054463,ZA
+693054464,693055487,BI
+693055488,693056511,GQ
+693056512,693057535,NA
693101568,693102591,KE
693102592,693103615,CD
693103616,693104639,GN
@@ -2533,7 +2903,9 @@
772057728,772057735,IT
772057736,772076095,DE
772076096,772076103,IT
-772076104,772145151,DE
+772076104,772076127,DE
+772076128,772076159,EG
+772076160,772145151,DE
772145152,772210687,ES
772210688,772276223,IE
772276224,772341759,RU
@@ -2680,9 +3052,11 @@
773048320,773050367,LV
773050368,773052415,IE
773052416,773054463,NL
-773054464,773055487,AL
-773055488,773055743,RS
-773055744,773056511,AL
+773054464,773054655,AL
+773054656,773054719,RS
+773054720,773055487,AL
+773055488,773055999,RS
+773056000,773056511,AL
773056512,773058559,IT
773058560,773060607,BE
773060608,773062655,DK
@@ -2723,16 +3097,14 @@
773152768,773153791,SE
773153792,773154815,US
773154816,773156863,SE
-773156864,773160447,FR
-773160448,773160703,ES
-773160704,773165055,FR
-773165056,773168127,NL
-773168128,773168639,US
-773168640,773168895,NL
-773168896,773169151,US
-773169152,773169375,NL
-773169376,773169407,BE
-773169408,773171343,NL
+773156864,773157887,FR
+773157888,773158911,DE
+773158912,773160447,FR
+773160448,773160959,ES
+773160960,773165055,FR
+773165056,773167615,NL
+773167616,773169151,US
+773169152,773171343,NL
773171344,773171359,BE
773171360,773172223,NL
773172224,773172287,BE
@@ -2755,8 +3127,9 @@
773234688,773238783,PL
773238784,773242879,NL
773242880,773246975,FR
-773246976,773247999,EE
-773248000,773251071,US
+773246976,773247871,EE
+773247872,773247999,US
+773248000,773251071,EE
773251072,773255167,AZ
773255168,773259263,RU
773259264,773263359,SI
@@ -2796,7 +3169,6 @@
773621760,773623807,PS
773623808,773625855,SE
773625856,773627903,IS
-773627904,773629951,TR
773629952,773631999,FR
773632000,773634047,CY
773634048,773636095,DE
@@ -2807,7 +3179,9 @@
773646336,773648383,TR
773648384,773650431,PL
773650432,773652479,GB
-773652480,773654527,SK
+773652480,773653759,SK
+773653760,773653791,CZ
+773653792,773654527,SK
773654528,773656575,RU
773656576,773658623,PL
773658624,773660671,DE
@@ -2849,8 +3223,7 @@
773709824,773711871,CZ
773711872,773713919,RU
773713920,773715967,NL
-773715968,773716479,EE
-773716480,773716991,SE
+773715968,773716991,SE
773716992,773718015,US
773718016,773720063,DE
773720064,773722111,GB
@@ -2875,12 +3248,10 @@
773763072,773765119,TR
773765120,773767167,NL
773767168,773769215,GB
-773769216,773771263,SE
773771264,773773311,DK
773773312,773775359,IT
773775360,773777407,IQ
773777408,773779455,CZ
-773779456,773781503,ME
773781504,773783551,IT
773783552,773785599,RU
773785600,773787647,NL
@@ -2925,7 +3296,8 @@
773898240,773906431,PS
773906432,773922815,GB
773922816,773931007,UA
-773931008,773939199,FR
+773931008,773934847,DE
+773934848,773939199,FR
773939200,773947391,CZ
773947392,773955583,GB
773955584,773963775,FR
@@ -2945,11 +3317,16 @@
774029312,774037503,RO
774037504,774045695,SK
774045696,774053887,FR
-774053888,774055935,DE
+774053888,774054015,HR
+774054016,774055935,DE
774055936,774057983,US
774057984,774058359,DE
774058360,774058367,HR
-774058368,774059215,DE
+774058368,774058599,DE
+774058600,774058603,HR
+774058604,774059207,DE
+774059208,774059211,HR
+774059212,774059215,DE
774059216,774059223,ZA
774059224,774060031,DE
774060032,774060047,ES
@@ -3154,7 +3531,26 @@
774162174,774162176,VA
774162177,774162181,LK
774162182,774162186,IE
-774162187,774168575,VA
+774162187,774162196,EH
+774162197,774162206,NA
+774162207,774162216,CX
+774162217,774162226,LA
+774162227,774162236,GB
+774162237,774162246,CH
+774162247,774162266,US
+774162267,774162276,PT
+774162277,774162286,AE
+774162287,774162296,IO
+774162297,774162306,GU
+774162307,774162316,RE
+774162317,774162326,TK
+774162327,774162336,CV
+774162337,774162432,VA
+774162433,774162442,GB
+774162443,774162452,BA
+774162453,774162462,WS
+774162463,774162472,SR
+774162473,774168575,VA
774168576,774176767,PL
774176768,774184959,IT
774184960,774193151,GB
@@ -3243,8 +3639,10 @@
774219776,774219839,CN
774219840,774219847,UA
774219848,774219855,CN
-774219856,774219871,GB
-774219872,774219887,CN
+774219856,774219863,GB
+774219864,774219871,IT
+774219872,774219879,RU
+774219880,774219887,CN
774219888,774219895,RU
774219896,774219903,LK
774219904,774219967,US
@@ -3261,8 +3659,7 @@
774221568,774221823,US
774221824,774222079,GB
774222080,774222335,US
-774222336,774222463,GB
-774222464,774222495,CN
+774222336,774222495,GB
774222496,774222511,FI
774222512,774222527,CN
774222528,774222591,GB
@@ -3271,20 +3668,22 @@
774222720,774222783,CN
774222784,774222847,GB
774222848,774222863,UA
-774222864,774222879,TR
+774222864,774222879,IT
774222880,774222895,US
774222896,774222911,GB
774222912,774222943,MA
774222944,774222951,GB
774222952,774222967,CN
-774222968,774222975,GB
+774222968,774222975,GR
774222976,774223039,CN
774223040,774223071,IT
774223072,774223103,CN
774223104,774223119,UA
774223120,774223151,CN
-774223152,774223167,TR
-774223168,774223215,GB
+774223152,774223167,PK
+774223168,774223183,GB
+774223184,774223199,PK
+774223200,774223215,GB
774223216,774223231,BE
774223232,774223239,CN
774223240,774223247,ME
@@ -3303,8 +3702,8 @@
774223352,774223359,GB
774223360,774223375,UA
774223376,774223391,RU
-774223392,774223423,TR
-774223424,774223743,GB
+774223392,774223407,PK
+774223408,774223743,GB
774223744,774223807,US
774223808,774223839,CN
774223840,774223871,US
@@ -3346,7 +3745,7 @@
774224832,774224847,UA
774224848,774224967,GB
774224968,774224975,UA
-774224976,774224983,TR
+774224976,774224983,RU
774224984,774224991,CN
774224992,774224999,LK
774225000,774225007,CN
@@ -3381,10 +3780,10 @@
774225616,774225647,TR
774225648,774225663,UA
774225664,774225671,LK
-774225672,774225679,RU
-774225680,774225687,GB
-774225688,774225695,CA
-774225696,774225727,GB
+774225672,774225687,RU
+774225688,774225695,PK
+774225696,774225703,CN
+774225704,774225727,GB
774225728,774225743,LT
774225744,774225791,GB
774225792,774225807,UA
@@ -3560,7 +3959,7 @@
778666392,778666399,PL
778666400,778666479,FR
778666480,778666495,DE
-778666496,778666751,FR
+778666496,778666751,BE
778666752,778666783,CZ
778666784,778666815,FR
778666816,778666847,GB
@@ -3645,15 +4044,16 @@
778668736,778668799,IT
778668800,778669103,FR
778669104,778669107,PL
-778669108,778669119,GB
+778669108,778669111,GB
+778669112,778669119,NL
778669120,778669151,FI
-778669152,778669183,FR
-778669184,778669191,DE
-778669192,778669199,FR
+778669152,778669199,FR
778669200,778669207,PL
778669208,778669211,CH
778669212,778669215,ES
-778669216,778669247,GB
+778669216,778669223,IE
+778669224,778669231,NL
+778669232,778669247,PL
778669248,778669295,FR
778669296,778669303,PL
778669304,778669439,FR
@@ -3719,10 +4119,9 @@
778670356,778670359,FR
778670360,778670383,DE
778670384,778670387,PL
-778670388,778670395,GB
-778670396,778670399,CZ
+778670388,778670399,GB
778670400,778670407,PL
-778670408,778670411,GB
+778670408,778670411,DE
778670412,778670415,NL
778670416,778670431,FR
778670432,778670435,NL
@@ -3817,7 +4216,29 @@
778672920,778672923,FR
778672924,778672927,ES
778672928,778672959,DE
-778672960,778698751,FR
+778672960,778673071,FR
+778673072,778673079,DE
+778673080,778673087,GB
+778673088,778673119,FR
+778673120,778673151,ES
+778673152,778673215,FR
+778673216,778673247,FI
+778673248,778673263,FR
+778673264,778673279,IT
+778673280,778673343,FR
+778673344,778673359,PL
+778673360,778673391,GB
+778673392,778673407,FR
+778673408,778673663,PL
+778673664,778673711,FR
+778673712,778673715,CH
+778673716,778673719,NL
+778673720,778673723,PT
+778673724,778673727,PL
+778673728,778673791,FR
+778673792,778673919,GB
+778673920,778674175,NL
+778674176,778698751,FR
778698752,778764287,TR
778764288,778829823,HU
778829824,778895359,RO
@@ -4094,7 +4515,13 @@
780729600,780729855,JM
780729856,780730111,JO
780730112,780730367,JP
-780730368,780795903,IE
+780730368,780779519,IE
+780779520,780783615,NL
+780783616,780785663,GB
+780785664,780787711,DE
+780787712,780791807,FR
+780791808,780793855,SE
+780793856,780795903,DE
780795904,780861439,RU
780861440,780926975,HU
780926976,780992511,CH
@@ -4195,9 +4622,14 @@
782664448,782664703,LU
782664704,782664704,GB
782664705,782665471,NL
-782665472,782667519,GB
+782665472,782666495,US
+782666496,782667007,GB
+782667008,782667519,RU
782667520,782667775,LU
-782667776,782680063,GB
+782667776,782668287,FR
+782668288,782668799,RU
+782668800,782669567,NL
+782669568,782680063,GB
782680064,782696447,RU
782696448,782712831,DE
782712832,782729215,RU
@@ -4600,7 +5032,13 @@
787709952,787724287,RU
787724288,787726335,UA
787726336,787742719,RU
-787742720,787775487,NL
+787742720,787758847,NL
+787758848,787759871,GB
+787759872,787760895,NL
+787760896,787761919,DE
+787761920,787762943,NL
+787762944,787763967,ES
+787763968,787775487,NL
787775488,787808255,DE
787808256,787841023,IR
787841024,787843071,RU
@@ -4891,11 +5329,7 @@
839095808,839096063,CA
839096064,839101695,US
839101696,839102207,CA
-839102208,839103999,US
-839104000,839104255,CA
-839104256,839110143,US
-839110144,839110399,CA
-839110400,839112447,US
+839102208,839112447,US
839112448,839112703,CA
839112704,839113215,US
839113216,839113471,CA
@@ -4910,8 +5344,8 @@
843644928,844890111,US
844890112,844988415,CA
844988416,845283327,US
-845283328,845414399,CA
-845545472,846200831,US
+845283328,845545471,CA
+845545472,846331903,US
847249408,855638015,US
855638016,872415231,GB
872415232,889192447,US
@@ -5450,7 +5884,9 @@
1040470400,1040470431,DE
1040470432,1040471487,EU
1040471488,1040471519,NL
-1040471520,1040474111,EU
+1040471520,1040472575,EU
+1040472576,1040472831,DE
+1040472832,1040474111,EU
1040474112,1040482303,CZ
1040482304,1040515071,BE
1040515072,1040547839,GB
@@ -5499,7 +5935,6 @@
1041253376,1041268735,RU
1041268736,1041301503,NO
1041301504,1041367039,IE
-1041367040,1041498111,GB
1041498112,1041563647,SE
1041563648,1041596415,PL
1041596416,1041629183,NL
@@ -5549,8 +5984,8 @@
1041699768,1041699807,GB
1041699808,1041700423,FR
1041700424,1041700535,GB
-1041700536,1041700551,FR
-1041700552,1041700607,GB
+1041700536,1041700559,FR
+1041700560,1041700607,GB
1041700608,1041700983,FR
1041700984,1041700991,GB
1041700992,1041701175,FR
@@ -5567,7 +6002,9 @@
1041701720,1041701727,GB
1041701728,1041701863,FR
1041701864,1041701871,GB
-1041701872,1041701967,FR
+1041701872,1041701887,FR
+1041701888,1041701919,GB
+1041701920,1041701967,FR
1041701968,1041701975,GB
1041701976,1041702167,FR
1041702168,1041702175,GB
@@ -5579,9 +6016,7 @@
1041702352,1041702399,GB
1041702400,1041703575,FR
1041703576,1041703583,GB
-1041703584,1041703783,FR
-1041703784,1041703791,GB
-1041703792,1041704119,FR
+1041703584,1041704119,FR
1041704120,1041704127,GB
1041704128,1041704159,FR
1041704160,1041704175,GB
@@ -5619,8 +6054,8 @@
1041705392,1041705439,GB
1041705440,1041705447,FR
1041705448,1041705455,GB
-1041705456,1041705471,FR
-1041705472,1041705479,GB
+1041705456,1041705463,FR
+1041705464,1041705479,GB
1041705480,1041705487,FR
1041705488,1041705519,GB
1041705520,1041705631,FR
@@ -5647,9 +6082,7 @@
1041706112,1041706143,GB
1041706144,1041706191,FR
1041706192,1041706239,GB
-1041706240,1041706359,FR
-1041706360,1041706367,GB
-1041706368,1041706447,FR
+1041706240,1041706447,FR
1041706448,1041706463,GB
1041706464,1041706479,FR
1041706480,1041706487,GB
@@ -5785,9 +6218,7 @@
1041714096,1041714103,GB
1041714104,1041714111,FR
1041714112,1041714175,GB
-1041714176,1041714631,FR
-1041714632,1041714639,GB
-1041714640,1041714655,FR
+1041714176,1041714655,FR
1041714656,1041714687,GB
1041714688,1041714775,FR
1041714776,1041714783,GB
@@ -5797,8 +6228,8 @@
1041714856,1041714879,GB
1041714880,1041714911,FR
1041714912,1041714919,GB
-1041714920,1041714999,FR
-1041715000,1041715015,GB
+1041714920,1041715007,FR
+1041715008,1041715015,GB
1041715016,1041715079,FR
1041715080,1041715087,GB
1041715088,1041715095,FR
@@ -5831,9 +6262,7 @@
1041716048,1041716095,GB
1041716096,1041716111,FR
1041716112,1041716223,GB
-1041716224,1041716231,FR
-1041716232,1041716239,GB
-1041716240,1041716311,FR
+1041716224,1041716311,FR
1041716312,1041716319,GB
1041716320,1041716439,FR
1041716440,1041716447,GB
@@ -5917,7 +6346,9 @@
1041719920,1041719935,GB
1041719936,1041720015,FR
1041720016,1041720031,GB
-1041720032,1041720551,FR
+1041720032,1041720479,FR
+1041720480,1041720511,GB
+1041720512,1041720551,FR
1041720552,1041720559,GB
1041720560,1041720567,FR
1041720568,1041720607,GB
@@ -5925,7 +6356,9 @@
1041720632,1041720639,GB
1041720640,1041720687,FR
1041720688,1041720703,GB
-1041720704,1041720903,FR
+1041720704,1041720831,FR
+1041720832,1041720839,GB
+1041720840,1041720903,FR
1041720904,1041720927,GB
1041720928,1041721039,FR
1041721040,1041721055,GB
@@ -6163,7 +6596,11 @@
1041737456,1041737463,GB
1041737464,1041737487,FR
1041737488,1041737495,GB
-1041737496,1041737583,FR
+1041737496,1041737503,FR
+1041737504,1041737511,GB
+1041737512,1041737527,FR
+1041737528,1041737535,GB
+1041737536,1041737583,FR
1041737584,1041737599,GB
1041737600,1041737607,FR
1041737608,1041737615,GB
@@ -6208,9 +6645,7 @@
1041738752,1041739079,FR
1041739080,1041739087,GB
1041739088,1041739167,FR
-1041739168,1041739207,GB
-1041739208,1041739215,FR
-1041739216,1041739231,GB
+1041739168,1041739231,GB
1041739232,1041739295,FR
1041739296,1041739299,BE
1041739300,1041739303,GB
@@ -6228,7 +6663,9 @@
1041739744,1041739751,GB
1041739752,1041740031,FR
1041740032,1041740039,GB
-1041740040,1041740135,FR
+1041740040,1041740103,FR
+1041740104,1041740119,GB
+1041740120,1041740135,FR
1041740136,1041740143,GB
1041740144,1041740263,FR
1041740264,1041740271,GB
@@ -6242,7 +6679,9 @@
1041740672,1041740687,GB
1041740688,1041740703,FR
1041740704,1041740719,GB
-1041740720,1041741063,FR
+1041740720,1041740807,FR
+1041740808,1041740831,GB
+1041740832,1041741063,FR
1041741064,1041741087,GB
1041741088,1041741135,FR
1041741136,1041741151,GB
@@ -6298,8 +6737,8 @@
1041743744,1041743759,GB
1041743760,1041743767,FR
1041743768,1041743775,GB
-1041743776,1041743791,FR
-1041743792,1041743799,GB
+1041743776,1041743783,FR
+1041743784,1041743799,GB
1041743800,1041743807,FR
1041743808,1041743823,GB
1041743824,1041743831,FR
@@ -6732,9 +7171,7 @@
1043466576,1043466583,NL
1043466584,1043466607,GB
1043466608,1043466887,NL
-1043466888,1043466895,GB
-1043466896,1043466911,NL
-1043466912,1043466927,GB
+1043466888,1043466927,GB
1043466928,1043466943,NL
1043466944,1043466991,GB
1043466992,1043467007,NL
@@ -6869,7 +7306,104 @@
1043480352,1043480359,GB
1043480360,1043480363,DE
1043480364,1043480575,GB
-1043480576,1043488767,CH
+1043480576,1043480687,CH
+1043480688,1043480695,GB
+1043480696,1043480831,CH
+1043480832,1043481855,GB
+1043481856,1043482007,CH
+1043482008,1043482015,GB
+1043482016,1043482079,CH
+1043482080,1043482623,GB
+1043482624,1043482647,CH
+1043482648,1043482667,GB
+1043482668,1043482671,CH
+1043482672,1043482687,GB
+1043482688,1043482719,CH
+1043482720,1043482735,GB
+1043482736,1043482759,CH
+1043482760,1043482783,GB
+1043482784,1043482791,CH
+1043482792,1043482807,GB
+1043482808,1043482895,CH
+1043482896,1043482911,GB
+1043482912,1043482951,CH
+1043482952,1043482959,GB
+1043482960,1043482975,CH
+1043482976,1043482995,GB
+1043482996,1043483039,CH
+1043483040,1043483047,GB
+1043483048,1043483059,CH
+1043483060,1043483063,GB
+1043483064,1043483103,CH
+1043483104,1043483111,GB
+1043483112,1043483231,CH
+1043483232,1043483235,GB
+1043483236,1043483279,CH
+1043483280,1043483295,GB
+1043483296,1043483311,CH
+1043483312,1043483319,GB
+1043483320,1043483327,CH
+1043483328,1043483335,GB
+1043483336,1043483391,CH
+1043483392,1043483655,GB
+1043483656,1043483679,CH
+1043483680,1043483687,GB
+1043483688,1043483759,CH
+1043483760,1043483775,GB
+1043483776,1043483839,CH
+1043483840,1043483871,GB
+1043483872,1043483911,CH
+1043483912,1043484159,GB
+1043484160,1043484191,CH
+1043484192,1043484199,GB
+1043484200,1043484215,CH
+1043484216,1043484223,GB
+1043484224,1043484351,CH
+1043484352,1043484383,GB
+1043484384,1043484431,CH
+1043484432,1043484463,GB
+1043484464,1043484551,CH
+1043484552,1043484559,GB
+1043484560,1043484575,CH
+1043484576,1043484583,GB
+1043484584,1043484623,CH
+1043484624,1043484631,GB
+1043484632,1043484671,CH
+1043484672,1043484679,GB
+1043484680,1043484751,CH
+1043484752,1043484767,GB
+1043484768,1043484799,CH
+1043484800,1043484927,GB
+1043484928,1043484935,CH
+1043484936,1043484943,GB
+1043484944,1043484959,CH
+1043484960,1043484991,GB
+1043484992,1043485055,CH
+1043485056,1043485191,GB
+1043485192,1043485195,CH
+1043485196,1043485439,GB
+1043485440,1043485567,CH
+1043485568,1043485695,GB
+1043485696,1043486239,CH
+1043486240,1043486463,GB
+1043486464,1043486487,CH
+1043486488,1043486719,GB
+1043486720,1043486723,CH
+1043486724,1043486975,GB
+1043486976,1043487039,CH
+1043487040,1043487055,GB
+1043487056,1043487103,CH
+1043487104,1043487231,GB
+1043487232,1043487443,CH
+1043487444,1043487447,GB
+1043487448,1043487455,CH
+1043487456,1043487487,GB
+1043487488,1043487623,CH
+1043487624,1043487631,GB
+1043487632,1043487679,CH
+1043487680,1043487743,GB
+1043487744,1043487751,CH
+1043487752,1043488767,GB
1043488768,1043496959,DE
1043496960,1043497055,FR
1043497056,1043497079,GB
@@ -7311,7 +7845,9 @@
1044578304,1044580607,DE
1044580608,1044580735,GB
1044580736,1044580767,DE
-1044580768,1044586495,GB
+1044580768,1044580863,GB
+1044580864,1044581119,DE
+1044581120,1044586495,GB
1044586496,1044587007,DE
1044587008,1044587519,GB
1044587520,1044587775,DE
@@ -7337,7 +7873,9 @@
1044592192,1044592255,DE
1044592256,1044592639,GB
1044592640,1044592655,DE
-1044592656,1044592831,GB
+1044592656,1044592671,GB
+1044592672,1044592703,DE
+1044592704,1044592831,GB
1044592832,1044594431,DE
1044594432,1044625407,GB
1044625408,1044625463,DE
@@ -7350,8 +7888,8 @@
1044628480,1044629503,GB
1044629504,1044629759,DE
1044629760,1044631551,GB
-1044631552,1044631871,DE
-1044631872,1044631951,GB
+1044631552,1044631903,DE
+1044631904,1044631951,GB
1044631952,1044631967,DE
1044631968,1044632063,GB
1044632064,1044633855,DE
@@ -7798,9 +8336,7 @@
1045742116,1045742175,GB
1045742176,1045742191,SE
1045742192,1045742335,GB
-1045742336,1045742339,SE
-1045742340,1045742343,GB
-1045742344,1045742351,SE
+1045742336,1045742351,SE
1045742352,1045742367,GB
1045742368,1045742383,SE
1045742384,1045742395,GB
@@ -7814,8 +8350,8 @@
1045742760,1045742831,GB
1045742832,1045742839,SE
1045742840,1045742847,GB
-1045742848,1045742975,SE
-1045742976,1045743031,GB
+1045742848,1045742983,SE
+1045742984,1045743031,GB
1045743032,1045743039,SE
1045743040,1045743063,GB
1045743064,1045743071,SE
@@ -8427,8 +8963,8 @@
1046896384,1046897663,GB
1046897664,1046898431,BE
1046898432,1046898687,EU
-1046898688,1046898943,BE
-1046898944,1046899167,EU
+1046898688,1046898975,BE
+1046898976,1046899167,EU
1046899168,1046904831,BE
1046904832,1046908927,SK
1046908928,1046910975,SE
@@ -8490,19 +9026,11 @@
1047527424,1047535615,BE
1047535616,1047551999,DE
1047552000,1047560191,RU
-1047560192,1047560875,DE
-1047560876,1047560879,AU
-1047560880,1047561159,DE
-1047561160,1047561167,AU
-1047561168,1047561367,DE
-1047561368,1047561371,CN
-1047561372,1047561747,DE
+1047560192,1047561747,DE
1047561748,1047561751,ES
1047561752,1047561887,DE
1047561888,1047561891,US
-1047561892,1047563227,DE
-1047563228,1047563231,CH
-1047563232,1047563287,DE
+1047561892,1047563287,DE
1047563288,1047563295,CH
1047563296,1047563303,DE
1047563304,1047563311,CH
@@ -8527,9 +9055,9 @@
1047563468,1047563471,CH
1047563472,1047565131,DE
1047565132,1047565135,GB
-1047565136,1047565311,DE
-1047565312,1047565315,CH
-1047565316,1047566363,DE
+1047565136,1047565343,DE
+1047565344,1047565359,CH
+1047565360,1047566363,DE
1047566364,1047566367,CH
1047566368,1047566403,DE
1047566404,1047566415,CH
@@ -9498,7 +10026,9 @@
1049017984,1049018047,GE
1049018048,1049020127,DE
1049020128,1049020135,FR
-1049020136,1049026559,DE
+1049020136,1049021343,DE
+1049021344,1049021375,US
+1049021376,1049026559,DE
1049026560,1049026815,EU
1049026816,1049031871,DE
1049031872,1049031903,EU
@@ -9625,8 +10155,7 @@
1049757600,1049757631,LU
1049757632,1049757647,DE
1049757648,1049757663,CA
-1049757664,1049757671,BA
-1049757672,1049758063,DE
+1049757664,1049758063,DE
1049758064,1049758071,PL
1049758072,1049758095,DE
1049758096,1049758103,ES
@@ -10027,7 +10556,9 @@
1052004000,1052004671,EU
1052004672,1052004687,DE
1052004688,1052004703,EU
-1052004704,1052004759,DE
+1052004704,1052004735,DE
+1052004736,1052004751,EU
+1052004752,1052004759,DE
1052004760,1052004767,EU
1052004768,1052004783,DE
1052004784,1052004815,EU
@@ -10105,7 +10636,9 @@
1052013964,1052014015,EU
1052014016,1052014079,DE
1052014080,1052014111,EU
-1052014112,1052014303,DE
+1052014112,1052014239,DE
+1052014240,1052014271,EU
+1052014272,1052014303,DE
1052014304,1052015367,EU
1052015368,1052015375,DE
1052015376,1052015423,EU
@@ -11788,8 +12321,7 @@
1055253056,1055253087,ES
1055253088,1055256447,EU
1055256448,1055256463,ES
-1055256464,1055260671,EU
-1055260672,1055326207,SE
+1055256464,1055326207,EU
1055326208,1055334399,RU
1055334400,1055342591,IE
1055342592,1055358975,RO
@@ -12103,7 +12635,9 @@
1066584064,1066586111,PE
1066586112,1066604927,US
1066604928,1066604959,CA
-1066604960,1067473471,US
+1066604960,1066606295,US
+1066606296,1066606303,GB
+1066606304,1067473471,US
1067473472,1067473535,CA
1067473536,1067474751,US
1067474752,1067474767,NL
@@ -12268,7 +12802,9 @@
1071309696,1071309727,HK
1071309728,1071318783,US
1071318784,1071319039,IN
-1071319040,1071362079,US
+1071319040,1071321487,US
+1071321488,1071321503,HK
+1071321504,1071362079,US
1071362080,1071362111,HK
1071362112,1071362207,US
1071362208,1071362239,HK
@@ -12359,7 +12895,8 @@
1072931584,1072931839,SY
1072931840,1072932607,CA
1072932608,1072932863,NG
-1072932864,1072934399,CA
+1072932864,1072933887,US
+1072933888,1072934399,CA
1072934400,1072934655,US
1072934656,1072934783,CA
1072934784,1072934847,AU
@@ -12827,10 +13364,8 @@
1075972352,1075973887,US
1075973888,1075974143,CA
1075974144,1075975167,US
-1075975168,1075976031,CA
-1075976032,1075976063,US
-1075976064,1075976127,CA
-1075976128,1075976191,US
+1075975168,1075976175,CA
+1075976176,1075976191,US
1075976192,1075976511,CA
1075976512,1075976543,US
1075976544,1075976647,CA
@@ -12993,9 +13528,7 @@
1076007248,1076007263,US
1076007264,1076007947,CA
1076007948,1076007951,US
-1076007952,1076007967,CA
-1076007968,1076007983,US
-1076007984,1076008063,CA
+1076007952,1076008063,CA
1076008064,1076008191,US
1076008192,1076009631,CA
1076009632,1076009639,US
@@ -14163,7 +14696,9 @@
1077936598,1077936601,CA
1077936602,1077936605,TH
1077936606,1077936609,JO
-1077936610,1077936621,US
+1077936610,1077936613,US
+1077936614,1077936617,UY
+1077936618,1077936621,US
1077936622,1077936622,AU
1077936623,1077936630,US
1077936631,1077936634,PE
@@ -14472,7 +15007,8 @@
1077938802,1077938805,US
1077938806,1077938809,DK
1077938810,1077938813,HK
-1077938814,1077938831,US
+1077938814,1077938829,US
+1077938830,1077938831,ES
1077938832,1077938835,CA
1077938836,1077938848,US
1077938849,1077938852,IT
@@ -14527,12 +15063,15 @@
1077939211,1077939218,US
1077939219,1077939219,NL
1077939220,1077939223,CA
-1077939224,1077939240,US
+1077939224,1077939228,BR
+1077939229,1077939240,US
1077939241,1077939244,NL
1077939245,1077939251,US
1077939252,1077939255,BR
1077939256,1077939259,FR
-1077939260,1077939304,US
+1077939260,1077939263,US
+1077939264,1077939267,MY
+1077939268,1077939304,US
1077939305,1077939308,GB
1077939309,1077939321,US
1077939322,1077939329,CA
@@ -14549,9 +15088,15 @@
1077939388,1077939391,PK
1077939392,1077939395,US
1077939396,1077939399,SE
-1077939400,1077939415,US
+1077939400,1077939410,US
+1077939411,1077939414,CN
+1077939415,1077939415,US
1077939416,1077939423,BE
-1077939424,1077939491,US
+1077939424,1077939439,US
+1077939440,1077939443,IS
+1077939444,1077939447,US
+1077939448,1077939451,IN
+1077939452,1077939491,US
1077939492,1077939495,GB
1077939496,1077939523,US
1077939524,1077939533,CA
@@ -15327,7 +15872,9 @@
1079411456,1079411711,PK
1079411712,1079413311,CA
1079413312,1079413343,US
-1079413344,1079414783,CA
+1079413344,1079413535,CA
+1079413536,1079413567,US
+1079413568,1079414783,CA
1079414784,1079415039,US
1079415040,1079415295,HN
1079415296,1079415807,CA
@@ -15881,9 +16428,7 @@
1081912576,1081912639,DE
1081912640,1081927135,US
1081927136,1081927143,GB
-1081927144,1081955839,US
-1081955840,1081956095,CA
-1081956096,1081966871,US
+1081927144,1081966871,US
1081966872,1081966879,AS
1081966880,1082091263,US
1082091264,1082091271,CN
@@ -15905,7 +16450,19 @@
1082344785,1082344786,HN
1082344787,1082345733,US
1082345734,1082345737,CA
-1082345738,1082348319,US
+1082345738,1082346510,US
+1082346511,1082346514,IN
+1082346515,1082347740,US
+1082347741,1082347744,IN
+1082347745,1082347760,US
+1082347761,1082347763,MX
+1082347764,1082347882,US
+1082347883,1082347886,IN
+1082347887,1082347892,US
+1082347893,1082347896,IN
+1082347897,1082348005,US
+1082348006,1082348009,IN
+1082348010,1082348319,US
1082348320,1082348327,GB
1082348328,1082348335,US
1082348336,1082348351,GB
@@ -16102,9 +16659,7 @@
1085685670,1085685685,CA
1085685686,1085698199,US
1085698200,1085698207,AS
-1085698208,1085823775,US
-1085823776,1085823807,DE
-1085823808,1085849599,US
+1085698208,1085849599,US
1085849600,1085857791,CA
1085857792,1085915135,US
1085915136,1085923327,PR
@@ -16668,16 +17223,14 @@
1093056144,1093056159,SY
1093056160,1093056167,US
1093056168,1093056175,RO
-1093056176,1093056319,US
-1093056320,1093056335,CA
-1093056336,1093056447,US
+1093056176,1093056447,US
1093056448,1093056463,FR
1093056464,1093056479,CA
1093056480,1093056511,US
1093056512,1093056519,GB
1093056520,1093056591,US
-1093056592,1093056607,CA
-1093056608,1093056959,US
+1093056592,1093056599,CA
+1093056600,1093056959,US
1093056960,1093056975,SA
1093056976,1093057103,US
1093057104,1093057119,JP
@@ -17948,7 +18501,9 @@
1106349600,1106349607,UM
1106349608,1106428959,US
1106428960,1106428975,UM
-1106428976,1106443623,US
+1106428976,1106441615,US
+1106441616,1106441623,A2
+1106441624,1106443623,US
1106443624,1106443631,CA
1106443632,1106469695,US
1106469696,1106469759,CO
@@ -18937,9 +19492,7 @@
1117829376,1117829631,GR
1117829632,1117831359,US
1117831360,1117831423,A2
-1117831424,1117832191,US
-1117832192,1117832447,IT
-1117832448,1117978623,US
+1117831424,1117978623,US
1117978624,1117979503,CA
1117979504,1117979519,US
1117979520,1117982639,CA
@@ -19200,7 +19753,9 @@
1118793824,1118793839,CA
1118793840,1118793935,US
1118793936,1118793951,ES
-1118793952,1118794287,US
+1118793952,1118793967,US
+1118793968,1118793983,HT
+1118793984,1118794287,US
1118794288,1118794303,BR
1118794304,1118794799,US
1118794800,1118794815,PR
@@ -21004,7 +21559,8 @@
1125455616,1125455871,A2
1125455872,1125456131,US
1125456132,1125456135,NO
-1125456136,1125456151,US
+1125456136,1125456139,A2
+1125456140,1125456151,US
1125456152,1125456155,NL
1125456156,1125456163,US
1125456164,1125456167,NO
@@ -22397,12 +22953,16 @@
1138271088,1138271103,TN
1138271104,1138337167,US
1138337168,1138337183,GB
-1138337184,1138417663,US
+1138337184,1138337199,US
+1138337200,1138337207,SG
+1138337208,1138417663,US
1138417664,1138417695,CA
1138417696,1138417727,DE
1138417728,1138421759,US
1138421760,1138421791,DE
-1138421792,1138425855,US
+1138421792,1138422783,US
+1138422784,1138423039,PA
+1138423040,1138425855,US
1138425856,1138427519,KN
1138427520,1138427647,US
1138427648,1138429951,KN
@@ -22821,8 +23381,8 @@
1145333864,1145333871,EG
1145333872,1145333879,US
1145333880,1145333903,CN
-1145333904,1145334143,US
-1145334144,1145334167,CN
+1145333904,1145334151,US
+1145334152,1145334167,CN
1145334168,1145334175,US
1145334176,1145334223,CN
1145334224,1145334231,US
@@ -22933,7 +23493,9 @@
1157670432,1157670463,CA
1157670464,1157713663,US
1157713664,1157713791,CA
-1157713792,1157755247,US
+1157713792,1157753087,US
+1157753088,1157753343,GB
+1157753344,1157755247,US
1157755248,1157755263,GR
1157755264,1157758207,US
1157758208,1157758463,RU
@@ -24165,8 +24727,7 @@
1161628648,1161628663,US
1161628664,1161628671,AR
1161628672,1161629199,US
-1161629200,1161629207,SI
-1161629208,1161629215,HR
+1161629200,1161629215,SI
1161629216,1161629223,US
1161629224,1161629231,GB
1161629232,1161629239,US
@@ -24180,8 +24741,9 @@
1161629392,1161629399,IE
1161629400,1161629407,IL
1161629408,1161629415,GB
-1161629416,1161629423,HR
-1161629424,1161629439,MY
+1161629416,1161629423,SI
+1161629424,1161629431,US
+1161629432,1161629439,MY
1161629440,1161629519,US
1161629520,1161629527,GB
1161629528,1161629535,MY
@@ -24194,14 +24756,17 @@
1161629952,1161630263,US
1161630264,1161630271,AR
1161630272,1161630335,US
-1161630336,1161630343,PL
-1161630344,1161630367,US
+1161630336,1161630343,AR
+1161630344,1161630351,IL
+1161630352,1161630367,US
1161630368,1161630375,GB
1161630376,1161630383,US
1161630384,1161630391,AR
1161630392,1161630399,US
1161630400,1161630431,GB
-1161630432,1161630727,US
+1161630432,1161630455,US
+1161630456,1161630463,NL
+1161630464,1161630727,US
1161630728,1161630735,EG
1161630736,1161630743,AU
1161630744,1161630751,GB
@@ -24507,7 +25072,7 @@
1161653760,1161653791,US
1161653792,1161653799,SI
1161653800,1161653831,US
-1161653832,1161653839,HR
+1161653832,1161653839,SI
1161653840,1161653847,US
1161653848,1161653855,SI
1161653856,1161653887,US
@@ -24851,10 +25416,14 @@
1163403264,1163407359,US
1163407360,1163411455,CA
1163411456,1163468799,US
-1163468800,1163472895,PR
+1163468800,1163469055,PR
+1163469056,1163469311,US
+1163469312,1163472895,PR
1163472896,1163477695,US
1163477696,1163477727,JP
-1163477728,1163526143,US
+1163477728,1163478047,US
+1163478048,1163478063,JP
+1163478064,1163526143,US
1163526144,1163526463,CA
1163526464,1163526655,US
1163526656,1163527023,CA
@@ -24869,8 +25438,8 @@
1163527776,1163527791,US
1163527792,1163529215,CA
1163529216,1163530239,US
-1163530240,1163530399,CA
-1163530400,1163530431,US
+1163530240,1163530415,CA
+1163530416,1163530431,US
1163530432,1163530639,CA
1163530640,1163530655,US
1163530656,1163530839,CA
@@ -25147,7 +25716,9 @@
1163876472,1163876479,PA
1163876480,1163878399,US
1163878400,1163878407,CN
-1163878408,1167321959,US
+1163878408,1167319111,US
+1167319112,1167319119,ZA
+1167319120,1167321959,US
1167321960,1167321967,GB
1167321968,1167322695,US
1167322696,1167322703,IN
@@ -25242,7 +25813,9 @@
1168954016,1168954047,IN
1168954048,1168954075,US
1168954076,1168954079,CA
-1168954080,1168955647,US
+1168954080,1168954623,US
+1168954624,1168954687,IN
+1168954688,1168955647,US
1168955648,1168956159,CA
1168956160,1168957439,US
1168957440,1168958047,CA
@@ -25260,7 +25833,9 @@
1168958232,1168958423,CA
1168958424,1168958463,US
1168958464,1168958479,CA
-1168958480,1168960543,US
+1168958480,1168958495,US
+1168958496,1168958559,IN
+1168958560,1168960543,US
1168960544,1168960591,CA
1168960592,1168960607,US
1168960608,1168960623,CA
@@ -25379,14 +25954,12 @@
1170539911,1170539911,KH
1170539912,1170539969,US
1170539970,1170539970,KH
-1170539971,1170539971,TR
-1170539972,1170540036,US
+1170539971,1170540036,US
1170540037,1170540037,TR
1170540038,1170540038,US
1170540039,1170540039,PH
1170540040,1170540096,US
-1170540097,1170540097,CN
-1170540098,1170540098,TR
+1170540097,1170540098,TR
1170540099,1170540105,US
1170540106,1170540106,CN
1170540107,1170540163,US
@@ -25499,7 +26072,9 @@
1170554496,1170554683,US
1170554684,1170554687,TR
1170554688,1170573375,US
-1170573376,1170573439,RU
+1170573376,1170573391,RU
+1170573392,1170573392,US
+1170573393,1170573439,RU
1170573440,1175977983,US
1175977984,1176068167,CA
1176068168,1176068175,US
@@ -25516,7 +26091,9 @@
1176108560,1176502271,CA
1176502272,1176512151,US
1176512152,1176512159,GB
-1176512160,1176513879,US
+1176512160,1176512703,US
+1176512704,1176512711,ZA
+1176512712,1176513879,US
1176513880,1176513887,GB
1176513888,1176514271,US
1176514272,1176514303,IN
@@ -25549,12 +26126,16 @@
1176620992,1176620999,US
1176621000,1176621599,CA
1176621600,1176621631,US
-1176621632,1176621679,CA
-1176621680,1176621823,US
+1176621632,1176621695,CA
+1176621696,1176621727,US
+1176621728,1176621759,CA
+1176621760,1176621823,US
1176621824,1176621855,CA
-1176621856,1176621887,US
-1176621888,1176621951,CA
-1176621952,1176622079,US
+1176621856,1176621863,US
+1176621864,1176621871,CA
+1176621872,1176621887,US
+1176621888,1176622047,CA
+1176622048,1176622079,US
1176622080,1176622335,GB
1176622336,1176622591,US
1176622592,1176623359,CA
@@ -25595,7 +26176,9 @@
1176686592,1176686599,PK
1176686600,1176686623,US
1176686624,1176686631,IL
-1176686632,1176686719,US
+1176686632,1176686639,US
+1176686640,1176686647,DE
+1176686648,1176686719,US
1176686720,1176686751,CA
1176686752,1176686847,US
1176686848,1176687103,AN
@@ -25852,10 +26435,8 @@
1177053696,1177053951,GB
1177053952,1177059327,US
1177059328,1177061375,CA
-1177061376,1177062399,US
-1177062400,1177074943,CA
-1177074944,1177075199,US
-1177075200,1177075455,CA
+1177061376,1177062143,US
+1177062144,1177075455,CA
1177075456,1177164255,US
1177164256,1177164263,CA
1177164264,1177164415,US
@@ -26690,9 +27271,7 @@
1209270584,1209270607,US
1209270608,1209270611,KR
1209270612,1209270615,CN
-1209270616,1209270783,US
-1209270784,1209270787,TR
-1209270788,1209271067,US
+1209270616,1209271067,US
1209271068,1209271071,VN
1209271072,1209271083,US
1209271084,1209271087,BR
@@ -28161,14 +28740,76 @@
1247070816,1247070831,CA
1247070832,1247072719,US
1247072720,1247072735,NL
-1247072736,1248864255,US
+1247072736,1247481855,US
+1247481856,1247481863,CN
+1247481864,1247481871,CO
+1247481872,1247481879,TR
+1247481880,1247481887,US
+1247481888,1247481903,CN
+1247481904,1247481911,BO
+1247481912,1247481927,CN
+1247481928,1247481951,US
+1247481952,1247481967,CN
+1247481968,1247481983,US
+1247481984,1247482015,GB
+1247482016,1247482047,CN
+1247482048,1247482063,CA
+1247482064,1247482071,BO
+1247482072,1247482079,US
+1247482080,1247482175,CN
+1247482176,1247482239,US
+1247482240,1247482255,GB
+1247482256,1247482319,CN
+1247482320,1247482335,US
+1247482336,1247482351,CN
+1247482352,1247482367,US
+1247482368,1247482383,GB
+1247482384,1247482543,CN
+1247482544,1247482551,US
+1247482552,1247482559,CN
+1247482560,1247482567,US
+1247482568,1247482583,CN
+1247482584,1247482607,US
+1247482608,1247482623,CN
+1247482624,1247482687,US
+1247482688,1247482751,CA
+1247482752,1247482815,US
+1247482816,1247482879,CN
+1247482880,1247482927,US
+1247482928,1247482951,BO
+1247482952,1247482967,US
+1247482968,1247482975,CN
+1247482976,1247483015,US
+1247483016,1247483039,CN
+1247483040,1247483047,CA
+1247483048,1247483079,US
+1247483080,1247483095,CN
+1247483096,1247483111,US
+1247483112,1247483119,CN
+1247483120,1247483647,US
+1247483648,1247484671,CN
+1247484672,1247484927,US
+1247484928,1247485191,CN
+1247485192,1247485231,US
+1247485232,1247485263,CN
+1247485264,1247485439,US
+1247485440,1247485543,CN
+1247485544,1247485615,US
+1247485616,1247485639,CN
+1247485640,1247485647,US
+1247485648,1247485951,CN
+1247485952,1248864255,US
1248864256,1248866303,CA
1248866304,1248885759,US
1248885760,1248886783,CA
1248886784,1248899071,US
1248899072,1248900095,CA
-1248900096,1248913407,US
-1248913408,1248915455,GP
+1248900096,1248903695,US
+1248903696,1248903711,ZA
+1248903712,1248903775,US
+1248903776,1248903791,FR
+1248903792,1248913407,US
+1248913408,1248915455,MF
1248915456,1248919551,US
1248919552,1248920575,CA
1248920576,1248921599,US
@@ -28189,7 +28830,9 @@
1249019904,1249020927,CA
1249020928,1249026423,US
1249026424,1249026431,CA
-1249026432,1249026703,US
+1249026432,1249026455,US
+1249026456,1249026463,ES
+1249026464,1249026703,US
1249026704,1249026711,ZA
1249026712,1249026719,CA
1249026720,1249026767,US
@@ -28234,7 +28877,8 @@
1249092608,1249099775,US
1249099776,1249101823,CA
1249101824,1249102847,PR
-1249102848,1249103871,CA
+1249102848,1249103103,US
+1249103104,1249103871,CA
1249103872,1249103887,TW
1249103888,1249103951,US
1249103952,1249103967,TW
@@ -28292,12 +28936,50 @@
1249217536,1249218559,CA
1249218560,1249221887,US
1249221888,1249222655,RO
-1249222656,1249236991,US
+1249222656,1249227007,US
+1249227008,1249227071,CY
+1249227072,1249227135,VG
+1249227136,1249227167,US
+1249227168,1249227199,VG
+1249227200,1249227263,HK
+1249227264,1249227519,VG
+1249227520,1249228031,US
+1249228032,1249228063,CZ
+1249228064,1249228095,US
+1249228096,1249228223,UA
+1249228224,1249228239,CZ
+1249228240,1249228287,US
+1249228288,1249228351,SC
+1249228352,1249229007,US
+1249229008,1249229008,CA
+1249229009,1249229087,US
+1249229088,1249229095,CA
+1249229096,1249229216,US
+1249229217,1249229217,CA
+1249229218,1249229289,US
+1249229290,1249229291,CA
+1249229292,1249236991,US
1249236992,1249239039,KY
1249239040,1249245183,US
1249245184,1249247231,CA
1249247232,1249256447,US
-1249256448,1249257471,CA
+1249256448,1249256500,CA
+1249256501,1249256542,GB
+1249256543,1249256713,CA
+1249256714,1249256773,US
+1249256774,1249256988,CA
+1249256989,1249256998,US
+1249256999,1249256999,CA
+1249257000,1249257009,LB
+1249257010,1249257017,CA
+1249257018,1249257042,US
+1249257043,1249257052,CA
+1249257053,1249257062,US
+1249257063,1249257121,CA
+1249257122,1249257131,LB
+1249257132,1249257348,CA
+1249257349,1249257412,US
+1249257413,1249257471,CA
1249257472,1249260543,US
1249260544,1249261567,CA
1249261568,1249272831,US
@@ -28310,7 +28992,13 @@
1249335296,1249337343,CA
1249337344,1249359871,US
1249359872,1249361919,CA
-1249361920,1249384447,US
+1249361920,1249381503,US
+1249381504,1249381519,DE
+1249381520,1249381759,US
+1249381760,1249381775,DE
+1249381776,1249382287,US
+1249382288,1249382303,DE
+1249382304,1249384447,US
1249384448,1249386495,PR
1249386496,1249391615,US
1249391616,1249392639,CA
@@ -28332,7 +29020,9 @@
1249474560,1249475583,CA
1249475584,1249484799,US
1249484800,1249486847,CA
-1249486848,1249506303,US
+1249486848,1249492735,US
+1249492736,1249492991,CA
+1249492992,1249506303,US
1249506304,1249507327,CA
1249507328,1249522687,US
1249522688,1249523711,CA
@@ -28340,15 +29030,17 @@
1249531904,1249533951,GD
1249533952,1249542143,US
1249542144,1249544191,CA
-1249544192,1249562623,US
+1249544192,1249550367,US
+1249550368,1249550375,HK
+1249550376,1249562623,US
1249562624,1249564671,CA
1249564672,1249568319,US
1249568320,1249568327,NL
1249568328,1249571839,US
1249571840,1249572863,CA
1249572864,1249577087,US
-1249577088,1249577279,CA
-1249577280,1249577343,US
+1249577088,1249577232,CA
+1249577233,1249577343,US
1249577344,1249577480,CA
1249577481,1249577545,US
1249577546,1249577730,CA
@@ -28429,15 +29121,15 @@
1254604192,1254604199,IE
1254604200,1254621183,US
1254621184,1254629375,CA
-1254629376,1254704383,US
+1254629376,1254688511,US
+1254688512,1254688543,CA
+1254688544,1254704383,US
1254704384,1254704639,PH
1254704640,1254704903,US
1254704904,1254704911,PH
1254704912,1254713359,US
1254713360,1254713407,CA
-1254713408,1254725119,US
-1254725120,1254725151,GB
-1254725152,1254924687,US
+1254713408,1254924687,US
1254924688,1254924703,RO
1254924704,1254948927,US
1254948928,1254948935,SG
@@ -28450,9 +29142,7 @@
1254950208,1254950671,US
1254950672,1254950679,RU
1254950680,1254950687,CA
-1254950688,1254950719,US
-1254950720,1254950727,SG
-1254950728,1254950751,US
+1254950688,1254950751,US
1254950752,1254950759,IL
1254950760,1254950767,US
1254950768,1254950775,GR
@@ -28545,7 +29235,9 @@
1254954664,1254954671,GB
1254954672,1254954887,US
1254954888,1254954895,IL
-1254954896,1254955599,US
+1254954896,1254955103,US
+1254955104,1254955111,GB
+1254955112,1254955599,US
1254955600,1254955607,GB
1254955608,1254955735,US
1254955736,1254955743,GB
@@ -28676,7 +29368,9 @@
1254964344,1254964351,PR
1254964352,1254964391,US
1254964392,1254964399,AU
-1254964400,1254964799,US
+1254964400,1254964639,US
+1254964640,1254964671,AU
+1254964672,1254964799,US
1254964800,1254964815,CA
1254964816,1254964927,US
1254964928,1254964943,CA
@@ -28986,7 +29680,8 @@
1255059168,1255059327,US
1255059328,1255059343,NL
1255059344,1255059359,US
-1255059360,1255059407,CA
+1255059360,1255059391,CA
+1255059392,1255059407,US
1255059408,1255059423,AR
1255059424,1255060159,US
1255060160,1255060191,NL
@@ -29004,9 +29699,7 @@
1255061984,1255062015,CA
1255062016,1255062463,US
1255062464,1255062527,PA
-1255062528,1255062591,US
-1255062592,1255062607,CA
-1255062608,1255062847,US
+1255062528,1255062847,US
1255062848,1255062863,CA
1255062864,1255063551,US
1255063552,1255071743,PR
@@ -29036,13 +29729,19 @@
1255750240,1255750271,AU
1255750272,1255753215,US
1255753216,1255753471,GB
-1255753472,1255768063,US
+1255753472,1255756799,US
+1255756800,1255756815,CA
+1255756816,1255768063,US
1255768064,1255768575,CA
1255768576,1255770367,US
1255770368,1255770623,CA
-1255770624,1255780351,US
+1255770624,1255776431,US
+1255776432,1255776439,LB
+1255776440,1255780351,US
1255780352,1255782399,CA
-1255782400,1255796743,US
+1255782400,1255792127,US
+1255792128,1255792383,IL
+1255792384,1255796743,US
1255796744,1255796751,GB
1255796752,1255972863,US
1255972864,1255981055,CA
@@ -29062,7 +29761,9 @@
1263264000,1263264127,CA
1263264128,1263264305,US
1263264306,1263264321,PK
-1263264322,1263266623,US
+1263264322,1263264511,US
+1263264512,1263264767,CA
+1263264768,1263266623,US
1263266624,1263266655,CA
1263266656,1263267327,US
1263267328,1263267583,CA
@@ -29587,7 +30288,9 @@
1279962912,1279962927,CN
1279962928,1279962943,US
1279962944,1279962975,CN
-1279962976,1279963935,US
+1279962976,1279963135,US
+1279963136,1279963391,IN
+1279963392,1279963935,US
1279963936,1279963967,CA
1279963968,1279965183,US
1279965184,1279966207,CA
@@ -29881,7 +30584,8 @@
1296238592,1296239103,NL
1296239104,1296239231,FR
1296239232,1296239359,NL
-1296239360,1296240127,FR
+1296239360,1296239615,DE
+1296239616,1296240127,FR
1296240128,1296241151,BE
1296241152,1296241407,IT
1296241408,1296242175,NL
@@ -29912,7 +30616,9 @@
1296248384,1296248447,IT
1296248448,1296248575,US
1296248576,1296248703,IE
-1296248704,1296249855,FR
+1296248704,1296248959,FR
+1296248960,1296249024,DE
+1296249025,1296249855,FR
1296249856,1296249887,US
1296249888,1296249951,FR
1296249952,1296250015,DE
@@ -29936,7 +30642,9 @@
1296251328,1296251359,IE
1296251360,1296251391,DE
1296251392,1296251775,NL
-1296251776,1296252039,FR
+1296251776,1296252015,FR
+1296252016,1296252031,US
+1296252032,1296252039,FR
1296252040,1296252055,DE
1296252056,1296252063,BE
1296252064,1296252079,IT
@@ -29992,7 +30700,7 @@
1296258048,1296258303,TW
1296258304,1296259071,NL
1296259072,1296259583,US
-1296259584,1296259839,FR
+1296259584,1296259839,DE
1296259840,1296260351,NL
1296260352,1296260607,US
1296260608,1296262143,DE
@@ -30048,9 +30756,7 @@
1296465920,1296466239,NG
1296466240,1296466303,NO
1296466304,1296466335,BF
-1296466336,1296466367,NO
-1296466368,1296466383,AO
-1296466384,1296466399,NO
+1296466336,1296466399,NO
1296466400,1296466415,AO
1296466416,1296466431,NG
1296466432,1296466447,TZ
@@ -30078,8 +30784,8 @@
1296472416,1296473087,NO
1296473088,1296474623,LT
1296474624,1296476159,US
-1296476160,1296480255,LT
-1296480256,1296482303,NO
+1296476160,1296479743,LT
+1296479744,1296482303,NO
1296482304,1296498687,LT
1296498688,1296531455,BG
1296531456,1296564223,MT
@@ -30172,9 +30878,7 @@
1296678152,1296678159,A2
1296678160,1296678215,NG
1296678216,1296678223,A2
-1296678224,1296678319,NG
-1296678320,1296678327,A2
-1296678328,1296678351,NG
+1296678224,1296678351,NG
1296678352,1296678367,A2
1296678368,1296678415,NG
1296678416,1296678431,A2
@@ -30187,7 +30891,10 @@
1296678792,1296678831,NG
1296678832,1296678839,A2
1296678840,1296678911,NG
-1296678912,1296680959,SA
+1296678912,1296680191,SA
+1296680192,1296680447,AE
+1296680448,1296680703,KW
+1296680704,1296680959,SA
1296680960,1296683007,ES
1296683008,1296685055,IE
1296685056,1296687103,TR
@@ -30232,7 +30939,6 @@
1296754688,1296756735,DE
1296756736,1296758783,FR
1296758784,1296760831,RS
-1296760832,1296762879,GB
1296762880,1296764927,RU
1296764928,1296769023,AT
1296769024,1296771071,TR
@@ -30712,8 +31418,16 @@
1307803648,1307807743,DK
1307807744,1307811839,SE
1307811840,1307815935,NL
-1307815936,1307819791,BE
-1307819792,1307820031,EU
+1307815936,1307816191,EU
+1307816192,1307816447,GB
+1307816448,1307818239,EU
+1307818240,1307818495,GB
+1307818496,1307818751,DE
+1307818752,1307819007,ES
+1307819008,1307819263,DE
+1307819264,1307819519,NL
+1307819520,1307819775,BE
+1307819776,1307820031,IT
1307820032,1307824127,ES
1307824128,1307828223,HU
1307828224,1307830128,NL
@@ -30826,9 +31540,7 @@
1308073984,1308078079,RU
1308078080,1308078879,NL
1308078880,1308078911,FR
-1308078912,1308079519,NL
-1308079520,1308079535,DE
-1308079536,1308080127,NL
+1308078912,1308080127,NL
1308080128,1308082175,RU
1308082176,1308084223,GB
1308084224,1308086271,RS
@@ -30836,7 +31548,6 @@
1308088320,1308090367,UA
1308090368,1308092415,SK
1308092416,1308094463,RU
-1308094464,1308096511,KW
1308096512,1308098559,RS
1308098560,1308360703,NL
1308360704,1308622847,PL
@@ -31113,7 +31824,9 @@
1311263424,1311263615,CH
1311263616,1311263743,FR
1311263744,1311263871,CH
-1311263872,1311264767,FR
+1311263872,1311263999,FR
+1311264000,1311264015,CH
+1311264016,1311264767,FR
1311264768,1311266815,RU
1311266816,1311268863,FR
1311268864,1311270911,BE
@@ -31508,7 +32221,7 @@
1317650432,1317666815,RU
1317666816,1317666823,IQ
1317666824,1317666831,CD
-1317666832,1317666839,NG
+1317666832,1317666839,A2
1317666840,1317666855,GH
1317666856,1317666863,A2
1317666864,1317666871,GH
@@ -31567,7 +32280,8 @@
1317667760,1317667767,FR
1317667768,1317667775,ZA
1317667776,1317667783,US
-1317667784,1317667799,NG
+1317667784,1317667791,AO
+1317667792,1317667799,NG
1317667800,1317667807,A2
1317667808,1317667815,NG
1317667816,1317668095,A2
@@ -31656,9 +32370,7 @@
1317669960,1317669983,A2
1317669984,1317669991,LR
1317669992,1317669999,NG
-1317670000,1317670007,A2
-1317670008,1317670015,NG
-1317670016,1317670063,A2
+1317670000,1317670063,A2
1317670064,1317670103,NG
1317670104,1317670135,A2
1317670136,1317670143,NG
@@ -31692,8 +32404,8 @@
1317670648,1317670655,NG
1317670656,1317670663,AO
1317670664,1317670679,A2
-1317670680,1317670695,NG
-1317670696,1317670711,A2
+1317670680,1317670703,NG
+1317670704,1317670711,A2
1317670712,1317670719,GH
1317670720,1317670727,A2
1317670728,1317670735,GH
@@ -31765,7 +32477,8 @@
1317671920,1317671927,NG
1317671928,1317671935,A2
1317671936,1317672447,GA
-1317672448,1317672463,A2
+1317672448,1317672455,A2
+1317672456,1317672463,GA
1317672464,1317672471,NG
1317672472,1317672479,A2
1317672480,1317672487,ZM
@@ -31952,8 +32665,7 @@
1317675544,1317675551,IQ
1317675552,1317675559,NG
1317675560,1317675567,NA
-1317675568,1317675583,A2
-1317675584,1317675591,LR
+1317675568,1317675591,A2
1317675592,1317675607,NG
1317675608,1317675623,A2
1317675624,1317675639,NG
@@ -31973,7 +32685,8 @@
1317675776,1317675783,NG
1317675784,1317675799,A2
1317675800,1317675807,GB
-1317675808,1317675823,A2
+1317675808,1317675815,NG
+1317675816,1317675823,A2
1317675824,1317675847,NG
1317675848,1317675855,A2
1317675856,1317675863,NG
@@ -31992,9 +32705,8 @@
1317676008,1317676015,GH
1317676016,1317676023,SD
1317676024,1317676031,GQ
-1317676032,1317676039,A2
-1317676040,1317676047,CD
-1317676048,1317676055,A2
+1317676032,1317676039,NG
+1317676040,1317676055,A2
1317676056,1317676063,NG
1317676064,1317676079,A2
1317676080,1317676087,AO
@@ -32013,7 +32725,7 @@
1317676192,1317676207,SD
1317676208,1317676215,A2
1317676216,1317676223,NG
-1317676224,1317676231,A2
+1317676224,1317676231,GH
1317676232,1317676239,NG
1317676240,1317676247,SD
1317676248,1317676255,NG
@@ -32059,7 +32771,7 @@
1317676944,1317676951,CM
1317676952,1317676983,A2
1317676984,1317676991,NG
-1317676992,1317676999,LR
+1317676992,1317676999,A2
1317677000,1317677007,IQ
1317677008,1317677015,CD
1317677016,1317677023,A2
@@ -32076,7 +32788,8 @@
1317677128,1317677135,NG
1317677136,1317677191,A2
1317677192,1317677199,SD
-1317677200,1317677215,NG
+1317677200,1317677207,A2
+1317677208,1317677215,NG
1317677216,1317677231,A2
1317677232,1317677239,UG
1317677240,1317677247,A2
@@ -32140,15 +32853,14 @@
1317678224,1317678231,NG
1317678232,1317678239,BF
1317678240,1317678247,CD
-1317678248,1317678271,A2
+1317678248,1317678255,TD
+1317678256,1317678271,A2
1317678272,1317678287,NG
1317678288,1317678295,GR
1317678296,1317678311,A2
1317678312,1317678319,SD
1317678320,1317678327,NG
-1317678328,1317678335,A2
-1317678336,1317678343,NG
-1317678344,1317678351,A2
+1317678328,1317678351,A2
1317678352,1317678359,CD
1317678360,1317678367,NG
1317678368,1317678375,CD
@@ -32179,7 +32891,7 @@
1317679632,1317679639,NG
1317679640,1317679647,ZW
1317679648,1317679655,CD
-1317679656,1317679663,A2
+1317679656,1317679663,NG
1317679664,1317679671,AO
1317679672,1317679687,NG
1317679688,1317679695,A2
@@ -32192,7 +32904,9 @@
1317679768,1317679775,A2
1317679776,1317679799,NG
1317679800,1317679807,A2
-1317679808,1317679847,NG
+1317679808,1317679831,NG
+1317679832,1317679839,A2
+1317679840,1317679847,NG
1317679848,1317679855,A2
1317679856,1317679871,NG
1317679872,1317681183,A2
@@ -32208,9 +32922,7 @@
1317686304,1317686319,NL
1317686320,1317686335,DE
1317686336,1317686399,NL
-1317686400,1317695743,DE
-1317695744,1317695999,CH
-1317696000,1317698559,DE
+1317686400,1317698559,DE
1317698560,1317698687,NL
1317698688,1317699583,DE
1317699584,1317715967,RU
@@ -32243,7 +32955,9 @@
1317836864,1317836927,CY
1317836928,1317836991,NL
1317836992,1317837007,GB
-1317837008,1317838943,NL
+1317837008,1317837567,NL
+1317837568,1317837823,US
+1317837824,1317838943,NL
1317838944,1317838959,GB
1317838960,1317838975,NL
1317838976,1317839103,GI
@@ -32285,8 +32999,8 @@
1317994496,1317995519,NL
1317995520,1317996095,DE
1317996096,1317996287,NL
-1317996288,1317998079,DE
-1317998080,1317998591,NL
+1317996288,1317998207,DE
+1317998208,1317998591,NL
1317998592,1318000383,DE
1318000384,1318000447,NL
1318000448,1318002175,DE
@@ -32382,8 +33096,9 @@
1318936576,1318944767,DK
1318944768,1318956287,CZ
1318956288,1318957055,PL
-1318957056,1318958847,CZ
-1318958848,1318961151,PL
+1318957056,1318958079,CZ
+1318958080,1318960895,PL
+1318960896,1318961151,CZ
1318961152,1318969343,NL
1318969344,1318977535,RU
1318977536,1318985727,LT
@@ -32567,7 +33282,10 @@
1332412416,1332477951,GR
1332477952,1332609023,ES
1332609024,1332613119,PL
-1332613120,1332629503,UA
+1332613120,1332617215,UA
+1332617216,1332621311,CZ
+1332621312,1332625407,UA
+1332625408,1332629503,RU
1332629504,1332633599,DE
1332633600,1332637695,UA
1332637696,1332641791,BG
@@ -32691,8 +33409,8 @@
1334647808,1334648063,LB
1334648064,1334648319,IQ
1334648320,1334648831,A2
-1334648832,1334651391,GB
-1334651392,1334651647,NL
+1334648832,1334651455,GB
+1334651456,1334651647,NL
1334651648,1334651903,FR
1334651904,1334652159,DE
1334652160,1334652543,GB
@@ -32730,8 +33448,8 @@
1334725632,1334726143,SE
1334726144,1334726655,NL
1334726656,1334729983,RU
-1334729984,1334730015,KZ
-1334730016,1334730239,RU
+1334729984,1334730027,KZ
+1334730028,1334730239,RU
1334730240,1334730431,KZ
1334730432,1334730439,RU
1334730440,1334730443,KZ
@@ -32745,8 +33463,8 @@
1334730544,1334730579,KZ
1334730580,1334730583,RU
1334730584,1334730667,KZ
-1334730668,1334730679,RU
-1334730680,1334730751,KZ
+1334730668,1334730671,RU
+1334730672,1334730751,KZ
1334730752,1334734847,RU
1334734848,1334738943,LT
1334738944,1334743039,CH
@@ -32816,7 +33534,6 @@
1336614912,1336616959,GB
1336616960,1336619007,ES
1336619008,1336621055,AL
-1336621056,1336623103,IT
1336623104,1336625151,BE
1336625152,1336625823,IE
1336625824,1336625839,GB
@@ -33070,7 +33787,12 @@
1346699756,1346699756,LI
1346699757,1346699767,GB
1346699768,1346699775,US
-1346699776,1346700575,GB
+1346699776,1346699839,GB
+1346699840,1346699871,HK
+1346699872,1346699875,GB
+1346699876,1346699879,IL
+1346699880,1346699887,US
+1346699888,1346700575,GB
1346700576,1346700591,VG
1346700592,1346700607,GB
1346700608,1346700623,US
@@ -33095,7 +33817,9 @@
1346704640,1346704767,LI
1346704768,1346705247,GB
1346705248,1346705279,US
-1346705280,1346707455,GB
+1346705280,1346705407,GB
+1346705408,1346705535,US
+1346705536,1346707455,GB
1346707456,1346711551,DE
1346711552,1346715647,AZ
1346715648,1346723839,NL
@@ -33402,9 +34126,7 @@
1347384704,1347384831,US
1347384832,1347385063,EE
1347385064,1347385071,RU
-1347385072,1347385215,EE
-1347385216,1347385343,US
-1347385344,1347385599,EE
+1347385072,1347385599,EE
1347385600,1347385855,US
1347385856,1347386559,EE
1347386560,1347386567,RU
@@ -33415,7 +34137,7 @@
1347386816,1347387011,EE
1347387012,1347387015,DE
1347387016,1347387215,EE
-1347387216,1347387219,DE
+1347387216,1347387219,NZ
1347387220,1347387224,EE
1347387225,1347387228,DE
1347387229,1347387391,EE
@@ -33607,8 +34329,8 @@
1347854880,1347854887,DE
1347854888,1347854911,EU
1347854912,1347855071,DE
-1347855072,1347855079,EU
-1347855080,1347855103,DE
+1347855072,1347855087,EU
+1347855088,1347855103,DE
1347855104,1347855359,CH
1347855360,1347855935,DE
1347855936,1347855943,EU
@@ -33655,7 +34377,9 @@
1347861800,1347861823,DE
1347861824,1347861943,EU
1347861944,1347861951,DE
-1347861952,1347862111,EU
+1347861952,1347862007,EU
+1347862008,1347862015,CH
+1347862016,1347862111,EU
1347862112,1347862143,DE
1347862144,1347862303,EU
1347862304,1347862431,DE
@@ -33676,7 +34400,9 @@
1347915776,1347919871,RU
1347919872,1347923967,DE
1347923968,1347928063,CZ
-1347928064,1347932159,RU
+1347928064,1347930623,RU
+1347930624,1347930879,GB
+1347930880,1347932159,RU
1347932160,1347936255,SK
1347936256,1347940351,FR
1347940352,1347944447,BA
@@ -34038,9 +34764,7 @@
1352149856,1352149871,SE
1352149872,1352277535,DE
1352277536,1352277567,IT
-1352277568,1352287399,DE
-1352287400,1352287407,NL
-1352287408,1352402791,DE
+1352277568,1352402791,DE
1352402792,1352402799,BE
1352402800,1352404599,DE
1352404600,1352404607,NL
@@ -34075,8 +34799,8 @@
1353258416,1353258423,DK
1353258424,1353258495,SE
1353258496,1353258503,GB
-1353258504,1353258527,SE
-1353258528,1353258559,GB
+1353258504,1353258519,SE
+1353258520,1353258559,GB
1353258560,1353258639,SE
1353258640,1353258783,GB
1353258784,1353258807,SE
@@ -34095,7 +34819,9 @@
1353268224,1353268479,GB
1353268480,1353268575,BE
1353268576,1353268583,GB
-1353268584,1353269247,BE
+1353268584,1353268599,BE
+1353268600,1353268607,GB
+1353268608,1353269247,BE
1353269248,1353270527,GB
1353270528,1353270783,IE
1353270784,1353271295,GB
@@ -34143,7 +34869,11 @@
1353280120,1353280127,GB
1353280128,1353280143,IT
1353280144,1353280151,GB
-1353280152,1353280671,IT
+1353280152,1353280159,IT
+1353280160,1353280167,GB
+1353280168,1353280287,IT
+1353280288,1353280295,GB
+1353280296,1353280671,IT
1353280672,1353280679,GB
1353280680,1353281023,IT
1353281024,1353281535,BE
@@ -34216,10 +34946,13 @@
1353298752,1353298815,SE
1353298816,1353298831,PT
1353298832,1353298839,SE
-1353298840,1353298879,GB
+1353298840,1353298847,IE
+1353298848,1353298879,GB
1353298880,1353298881,SE
1353298882,1353298887,GB
-1353298888,1353299647,SE
+1353298888,1353299503,SE
+1353299504,1353299511,GB
+1353299512,1353299647,SE
1353299648,1353299839,GB
1353299840,1353299847,SE
1353299848,1353299863,GB
@@ -34249,9 +34982,7 @@
1353310336,1353310463,GB
1353310464,1353310479,ES
1353310480,1353310487,GB
-1353310488,1353310559,ES
-1353310560,1353310575,GB
-1353310576,1353310599,ES
+1353310488,1353310599,ES
1353310600,1353310607,DE
1353310608,1353310719,ES
1353310720,1353311175,IT
@@ -34454,7 +35185,7 @@
1357321016,1357321023,DK
1357321024,1357321087,KE
1357321088,1357321215,HK
-1357321216,1357321471,GB
+1357321216,1357321471,EU
1357321472,1357321503,ES
1357321504,1357321727,EU
1357321728,1357321983,CY
@@ -34523,10 +35254,10 @@
1357358592,1357358847,DE
1357358848,1357359103,PL
1357359104,1357359999,ES
-1357360000,1357360031,GB
-1357360032,1357360127,EU
-1357360128,1357360279,GB
-1357360280,1357360383,EU
+1357360000,1357360279,GB
+1357360280,1357360319,EU
+1357360320,1357360335,GB
+1357360336,1357360383,EU
1357360384,1357360639,ES
1357360640,1357360895,GB
1357360896,1357361151,DE
@@ -34551,7 +35282,9 @@
1357366864,1357366879,ES
1357366880,1357366911,EU
1357366912,1357366927,GB
-1357366928,1357366975,EU
+1357366928,1357366943,EU
+1357366944,1357366959,GB
+1357366960,1357366975,EU
1357366976,1357367295,GB
1357367296,1357367551,FR
1357367552,1357367807,EU
@@ -34662,7 +35395,8 @@
1357883536,1357883551,FR
1357883552,1357883583,EU
1357883584,1357883727,FR
-1357883728,1357883759,EU
+1357883728,1357883743,DE
+1357883744,1357883759,EU
1357883760,1357883775,FR
1357883776,1357883807,RU
1357883808,1357883839,EU
@@ -34708,7 +35442,7 @@
1357891584,1357891647,EU
1357891648,1357891679,NL
1357891680,1357891711,GB
-1357891712,1357891839,FI
+1357891712,1357891839,EU
1357891840,1357892095,GB
1357892096,1357892111,DE
1357892112,1357892127,ES
@@ -34721,7 +35455,7 @@
1357892200,1357892207,NL
1357892208,1357892215,SE
1357892216,1357892223,US
-1357892224,1357892351,FI
+1357892224,1357892351,EU
1357892352,1357893119,NL
1357893120,1357893375,SE
1357893376,1357893407,EU
@@ -34733,13 +35467,16 @@
1357897856,1357898495,DE
1357898496,1357898751,EU
1357898752,1357899019,DE
-1357899020,1357899023,EU
+1357899020,1357899023,NL
1357899024,1357899039,DE
1357899040,1357899047,EU
1357899048,1357899063,DE
1357899064,1357899071,EU
1357899072,1357899199,DE
-1357899200,1357899279,EU
+1357899200,1357899263,EU
+1357899264,1357899267,DE
+1357899268,1357899275,FR
+1357899276,1357899279,NL
1357899280,1357899287,RU
1357899288,1357899327,EU
1357899328,1357899391,PL
@@ -34761,7 +35498,7 @@
1357903872,1357904383,EU
1357904384,1357904895,DE
1357904896,1357905407,GB
-1357905408,1357905663,FR
+1357905408,1357905663,SE
1357905664,1357905919,NL
1357905920,1357910015,LT
1357910016,1357914111,GR
@@ -34807,7 +35544,8 @@
1357989784,1357989791,GB
1357989792,1357989807,FR
1357989808,1357989823,GB
-1357989824,1357989839,FR
+1357989824,1357989831,NL
+1357989832,1357989839,FR
1357989840,1357989847,GB
1357989848,1357989887,FR
1357989888,1357991679,GB
@@ -34890,10 +35628,8 @@
1358223672,1358223687,DE
1358223688,1358223695,GB
1358223696,1358223719,DE
-1358223720,1358223783,GB
-1358223784,1358223791,DE
-1358223792,1358223807,GB
-1358223808,1358223843,DE
+1358223720,1358223815,GB
+1358223816,1358223843,DE
1358223844,1358223871,GB
1358223872,1358223887,NL
1358223888,1358223895,DE
@@ -34905,8 +35641,8 @@
1358223940,1358223975,DE
1358223976,1358223991,NL
1358223992,1358223999,DE
-1358224000,1358224079,NL
-1358224080,1358224511,DE
+1358224000,1358224087,NL
+1358224088,1358224511,DE
1358224512,1358224519,BE
1358224520,1358224611,DE
1358224612,1358224651,BE
@@ -34915,9 +35651,7 @@
1358224728,1358224959,DE
1358224960,1358225127,IT
1358225128,1358225135,DE
-1358225136,1358225143,IT
-1358225144,1358225151,DE
-1358225152,1358225183,IT
+1358225136,1358225183,IT
1358225184,1358225191,DE
1358225192,1358225199,IT
1358225200,1358225407,DE
@@ -35086,10 +35820,12 @@
1358487552,1358487711,SE
1358487712,1358487727,US
1358487728,1358487999,FR
-1358488000,1358488223,SE
+1358488000,1358488191,SE
+1358488192,1358488223,GB
1358488224,1358488239,US
1358488240,1358488255,FR
-1358488256,1358488479,SE
+1358488256,1358488447,SE
+1358488448,1358488479,GB
1358488480,1358488495,US
1358488496,1358488511,FR
1358488512,1358491647,SE
@@ -35150,9 +35886,7 @@
1358669352,1358669359,GB
1358669360,1358669463,PT
1358669464,1358669471,GB
-1358669472,1358669503,PT
-1358669504,1358669519,GB
-1358669520,1358669543,PT
+1358669472,1358669543,PT
1358669544,1358669551,GB
1358669552,1358669975,PT
1358669976,1358669983,GB
@@ -35161,8 +35895,10 @@
1358670024,1358670183,PT
1358670184,1358670191,GB
1358670192,1358670943,PT
-1358670944,1358670959,GB
-1358670960,1358671415,PT
+1358670944,1358670951,FR
+1358670952,1358671039,PT
+1358671040,1358671103,GB
+1358671104,1358671415,PT
1358671416,1358671423,GB
1358671424,1358671431,PT
1358671432,1358671439,GB
@@ -35305,7 +36041,9 @@
1358876672,1358880767,LV
1358880768,1358884863,GB
1358884864,1358888959,SE
-1358888960,1358893055,DE
+1358888960,1358889599,DE
+1358889600,1358889631,IN
+1358889632,1358893055,DE
1358893056,1358897151,RU
1358897152,1358898175,A2
1358898176,1358898239,CA
@@ -35519,8 +36257,8 @@
1359467488,1359467495,DE
1359467496,1359467647,US
1359467648,1359467775,DE
-1359467776,1359467823,US
-1359467824,1359467903,DE
+1359467776,1359467831,US
+1359467832,1359467903,DE
1359467904,1359468063,US
1359468064,1359468575,DE
1359468576,1359468583,SG
@@ -35765,7 +36503,9 @@
1360625664,1360626687,DE
1360626688,1360627199,LB
1360627200,1360627455,DE
-1360627456,1360627743,LB
+1360627456,1360627520,IQ
+1360627521,1360627711,DE
+1360627712,1360627743,LB
1360627744,1360627967,DE
1360627968,1360628095,IQ
1360628096,1360628223,LU
@@ -36081,7 +36821,7 @@
1361036596,1361036599,GI
1361036600,1361036607,IQ
1361036608,1361036611,GI
-1361036612,1361036615,IQ
+1361036612,1361036615,NL
1361036616,1361036623,GB
1361036624,1361036631,IQ
1361036632,1361036635,GR
@@ -36978,7 +37718,9 @@
1372147712,1372151807,BE
1372151808,1372152823,DE
1372152824,1372152831,GB
-1372152832,1372159999,DE
+1372152832,1372156063,DE
+1372156064,1372156095,GB
+1372156096,1372159999,DE
1372160000,1372164095,GB
1372164096,1372166863,DE
1372166864,1372166879,US
@@ -37066,8 +37808,8 @@
1372702992,1372703271,EU
1372703272,1372703323,DE
1372703324,1372703327,EU
-1372703328,1372703407,DE
-1372703408,1372703423,EU
+1372703328,1372703391,DE
+1372703392,1372703423,EU
1372703424,1372703487,DE
1372703488,1372703743,EU
1372703744,1372713327,DE
@@ -37190,7 +37932,9 @@
1382182832,1382182895,DE
1382182896,1382182911,GB
1382182912,1382183167,LI
-1382183168,1382187007,DE
+1382183168,1382183423,CH
+1382183424,1382183935,LI
+1382183936,1382187007,DE
1382187008,1382191871,ES
1382191872,1382192127,VE
1382192128,1382203391,ES
@@ -37301,7 +38045,6 @@
1383104024,1383104255,GB
1383104256,1383104511,FR
1383104512,1383112703,JE
-1383112704,1383120895,GE
1383120896,1383129031,IT
1383129032,1383129039,ES
1383129040,1383129087,IT
@@ -37386,7 +38129,6 @@
1383440384,1383448575,RU
1383448576,1383456767,RS
1383456768,1383464959,UA
-1383464960,1383473151,US
1383473152,1383481343,DE
1383481344,1383481599,GB
1383481600,1383481615,US
@@ -37434,9 +38176,7 @@
1384190464,1384190719,NL
1384190720,1384190975,DE
1384190976,1384191231,DK
-1384191232,1384191359,DE
-1384191360,1384191423,AT
-1384191424,1384191999,DE
+1384191232,1384191999,DE
1384192000,1384192191,NL
1384192192,1384192255,DE
1384192256,1384192511,NL
@@ -37624,8 +38364,7 @@
1385275392,1385283583,IT
1385283584,1385285631,DE
1385285632,1385287679,GB
-1385287680,1385289727,IS
-1385289728,1385291775,NO
+1385287680,1385291775,IS
1385291776,1385299967,TR
1385299968,1385308159,BG
1385308160,1385309439,BE
@@ -37808,7 +38547,9 @@
1388389928,1388390015,NG
1388390016,1388390143,IT
1388390144,1388394495,NG
-1388394496,1388396543,IT
+1388394496,1388396031,IT
+1388396032,1388396287,NG
+1388396288,1388396543,IT
1388396544,1388404735,LV
1388404736,1388412927,UA
1388412928,1388421119,RU
@@ -38000,7 +38741,9 @@
1388743088,1388743099,GB
1388743100,1388743343,IE
1388743344,1388743351,GB
-1388743352,1388743443,IE
+1388743352,1388743359,IE
+1388743360,1388743375,GB
+1388743376,1388743443,IE
1388743444,1388743451,GB
1388743452,1388743555,IE
1388743556,1388743559,GB
@@ -38074,9 +38817,7 @@
1388765184,1388773375,GB
1388773376,1388781567,NO
1388781568,1388789759,ES
-1388789760,1388791519,NL
-1388791520,1388791527,GB
-1388791528,1388794943,NL
+1388789760,1388794943,NL
1388794944,1388794959,GB
1388794960,1388795343,NL
1388795344,1388795359,GB
@@ -38670,11 +39411,11 @@
1399848960,1400111103,FR
1400111104,1400373247,NL
1400373248,1400705279,DE
-1400705280,1400706047,EU
-1400706048,1400708095,DE
-1400708096,1400709119,EU
-1400709120,1400710143,DE
-1400710144,1400710399,EU
+1400705280,1400705791,EU
+1400705792,1400708607,DE
+1400708608,1400709120,EU
+1400709121,1400710142,DE
+1400710143,1400710399,EU
1400710400,1400712191,DE
1400712192,1400712447,EU
1400712448,1400712703,DE
@@ -38705,7 +39446,9 @@
1401264128,1401264903,DE
1401264904,1401265151,EU
1401265152,1401265919,DE
-1401265920,1401266175,EU
+1401265920,1401265951,EU
+1401265952,1401265983,DE
+1401265984,1401266175,EU
1401266176,1401273599,DE
1401273600,1401273727,EU
1401273728,1401274367,DE
@@ -38807,45 +39550,97 @@
1401667584,1401683967,IT
1401683968,1401684067,SE
1401684068,1401684071,NO
-1401684072,1401684479,SE
+1401684072,1401684075,DE
+1401684076,1401684479,SE
1401684480,1401684511,DK
-1401684512,1401684543,SE
+1401684512,1401684515,DE
+1401684516,1401684543,SE
1401684544,1401684607,DK
1401684608,1401684671,SE
1401684672,1401684703,DK
1401684704,1401684731,SE
1401684732,1401684735,DK
1401684736,1401684755,NO
-1401684756,1401684767,SE
+1401684756,1401684759,SE
+1401684760,1401684763,DE
+1401684764,1401684767,SE
1401684768,1401684895,NO
-1401684896,1401686015,SE
+1401684896,1401684995,SE
+1401684996,1401684999,DE
+1401685000,1401686015,SE
1401686016,1401686059,GB
-1401686060,1401686063,SE
+1401686060,1401686063,DE
1401686064,1401686143,GB
1401686144,1401686223,SE
1401686224,1401686271,GB
1401686272,1401686287,NL
-1401686288,1401686335,SE
+1401686288,1401686291,DE
+1401686292,1401686335,SE
1401686336,1401686399,NL
1401686400,1401686911,SE
1401686912,1401686927,DE
-1401686928,1401691519,SE
+1401686928,1401686943,SE
+1401686944,1401686947,DE
+1401686948,1401691519,SE
1401691520,1401691535,DE
1401691536,1401695263,SE
1401695264,1401695267,GB
1401695268,1401695271,SE
1401695272,1401695275,GB
-1401695276,1401697815,SE
+1401695276,1401695279,DE
+1401695280,1401697815,SE
1401697816,1401697823,DE
1401697824,1401698223,SE
1401698224,1401698227,GB
-1401698228,1401708543,SE
+1401698228,1401698231,DE
+1401698232,1401703951,SE
+1401703952,1401703955,DE
+1401703956,1401704511,SE
+1401704512,1401704515,DE
+1401704516,1401705983,SE
+1401705984,1401705987,DE
+1401705988,1401708543,SE
1401708544,1401709055,FR
1401709056,1401709311,SE
1401709312,1401709567,GB
-1401709568,1401714047,SE
+1401709568,1401711615,SE
+1401711616,1401711647,GB
+1401711648,1401711679,DE
+1401711680,1401711711,NL
+1401711712,1401711743,ES
+1401711744,1401711775,DK
+1401711776,1401711807,IT
+1401711808,1401711839,US
+1401711840,1401711871,NL
+1401711872,1401711903,GB
+1401711904,1401711935,DE
+1401711936,1401711967,NL
+1401711968,1401711999,ES
+1401712000,1401712031,DK
+1401712032,1401712063,CH
+1401712064,1401712095,FR
+1401712096,1401712127,NL
+1401712128,1401712159,GB
+1401712160,1401712191,DE
+1401712192,1401712223,SE
+1401712224,1401712255,ES
+1401712256,1401712287,DK
+1401712288,1401712319,SE
+1401712320,1401712351,IT
+1401712352,1401712383,DE
+1401712384,1401712415,GB
+1401712416,1401712447,DE
+1401712448,1401712479,NL
+1401712480,1401712511,ES
+1401712512,1401712543,SE
+1401712544,1401712575,US
+1401712576,1401712607,GB
+1401712608,1401712639,NL
+1401712640,1401714047,SE
1401714048,1401714063,FR
-1401714064,1401715455,SE
+1401714064,1401715403,SE
+1401715404,1401715407,DE
+1401715408,1401715455,SE
1401715456,1401715459,US
1401715460,1401717759,SE
1401717760,1401718015,NL
@@ -38854,7 +39649,10 @@
1401719952,1401719955,GB
1401719956,1401719959,SE
1401719960,1401719963,GB
-1401719964,1401727743,SE
+1401719964,1401719967,DE
+1401719968,1401726783,SE
+1401726784,1401726787,DE
+1401726788,1401727743,SE
1401727744,1401727999,GB
1401728000,1401728335,SE
1401728336,1401728351,NL
@@ -38891,7 +39689,9 @@
1401745984,1401745999,NL
1401746000,1401746015,ES
1401746016,1401746019,GB
-1401746020,1401746175,SE
+1401746020,1401746023,SE
+1401746024,1401746027,DE
+1401746028,1401746175,SE
1401746176,1401746191,DK
1401746192,1401746215,SE
1401746216,1401746223,BG
@@ -38901,7 +39701,8 @@
1401746272,1401746279,GB
1401746280,1401746283,SE
1401746284,1401746287,US
-1401746288,1401746431,SE
+1401746288,1401746291,DE
+1401746292,1401746431,SE
1401746432,1401746447,NL
1401746448,1401746467,SE
1401746468,1401746471,NL
@@ -38910,12 +39711,15 @@
1401746488,1401746495,SE
1401746496,1401746511,NL
1401746512,1401746527,ES
-1401746528,1401746623,SE
+1401746528,1401746531,DE
+1401746532,1401746623,SE
1401746624,1401746639,DE
1401746640,1401746655,SE
1401746656,1401746687,IE
1401746688,1401746703,NO
-1401746704,1401746751,SE
+1401746704,1401746719,SE
+1401746720,1401746723,DE
+1401746724,1401746751,SE
1401746752,1401746767,NL
1401746768,1401746783,ES
1401746784,1401746879,SE
@@ -38925,13 +39729,15 @@
1401746960,1401747007,SE
1401747008,1401747023,NL
1401747024,1401747039,ES
-1401747040,1401747135,SE
+1401747040,1401747043,DE
+1401747044,1401747135,SE
1401747136,1401747151,DE
1401747152,1401747199,SE
1401747200,1401747215,IT
1401747216,1401747235,SE
1401747236,1401747239,US
-1401747240,1401747279,SE
+1401747240,1401747243,DE
+1401747244,1401747279,SE
1401747280,1401747295,ES
1401747296,1401747391,SE
1401747392,1401747407,DE
@@ -38940,7 +39746,9 @@
1401747488,1401747495,DK
1401747496,1401747499,SE
1401747500,1401747503,GB
-1401747504,1401747647,SE
+1401747504,1401747583,SE
+1401747584,1401747587,DE
+1401747588,1401747647,SE
1401747648,1401747663,DE
1401747664,1401747711,SE
1401747712,1401747967,FR
@@ -39116,9 +39924,13 @@
1403574784,1403575039,IT
1403575040,1403576063,SE
1403576064,1403576319,DE
-1403576320,1403580159,SE
+1403576320,1403578879,SE
+1403578880,1403579135,DK
+1403579136,1403580159,SE
1403580160,1403580415,GB
-1403580416,1403584511,SE
+1403580416,1403581951,SE
+1403581952,1403582207,US
+1403582208,1403584511,SE
1403584512,1403600895,DE
1403600896,1403601519,FR
1403601520,1403601535,MC
@@ -39418,7 +40230,8 @@
1406964928,1406967295,DE
1406967296,1406967327,GB
1406967328,1406967343,NL
-1406967344,1406967807,DE
+1406967344,1406967359,GB
+1406967360,1406967807,DE
1406967808,1406975999,RU
1406976000,1406984191,IE
1406984192,1407000575,RU
@@ -39443,7 +40256,14 @@
1407123456,1407131647,SE
1407131648,1407139839,NL
1407139840,1407148031,DE
-1407148032,1407152263,GB
+1407148032,1407148295,GB
+1407148296,1407148303,SE
+1407148304,1407149695,GB
+1407149696,1407149759,CY
+1407149760,1407151615,GB
+1407151616,1407151871,SE
+1407151872,1407152259,GB
+1407152260,1407152263,IE
1407152264,1407152287,US
1407152288,1407152903,GB
1407152904,1407152927,NL
@@ -39466,8 +40286,7 @@
1407516728,1407516735,NG
1407516736,1407516743,UG
1407516744,1407516751,LR
-1407516752,1407516759,SL
-1407516760,1407516767,A2
+1407516752,1407516767,A2
1407516768,1407516775,AO
1407516776,1407516783,A2
1407516784,1407516791,NG
@@ -39483,7 +40302,8 @@
1407516912,1407516951,NG
1407516952,1407516959,A2
1407516960,1407516967,NG
-1407516968,1407516983,A2
+1407516968,1407516975,A2
+1407516976,1407516983,GN
1407516984,1407516991,KE
1407516992,1407516999,CD
1407517000,1407517023,A2
@@ -39535,7 +40355,7 @@
1407518352,1407518359,A2
1407518360,1407518367,NG
1407518368,1407518375,ZA
-1407518376,1407518383,CD
+1407518376,1407518383,AO
1407518384,1407518391,A2
1407518392,1407518399,CD
1407518400,1407518831,A2
@@ -39593,7 +40413,9 @@
1407519896,1407519903,GN
1407519904,1407519911,NG
1407519912,1407519919,GN
-1407519920,1407519959,A2
+1407519920,1407519943,A2
+1407519944,1407519951,CD
+1407519952,1407519959,A2
1407519960,1407519967,GB
1407519968,1407519983,NG
1407519984,1407519991,SD
@@ -39665,7 +40487,7 @@
1407520792,1407520799,ZA
1407520800,1407520807,A2
1407520808,1407520815,MU
-1407520816,1407520823,A2
+1407520816,1407520823,ZW
1407520824,1407520831,CI
1407520832,1407520839,SO
1407520840,1407520847,A2
@@ -39728,7 +40550,9 @@
1407522384,1407522391,A2
1407522392,1407522407,NG
1407522408,1407522415,ZW
-1407522416,1407522439,A2
+1407522416,1407522423,SD
+1407522424,1407522431,A2
+1407522432,1407522439,ZM
1407522440,1407522455,UG
1407522456,1407522463,ML
1407522464,1407522471,A2
@@ -39757,7 +40581,7 @@
1407522656,1407522663,CI
1407522664,1407522671,A2
1407522672,1407522679,ZM
-1407522680,1407522687,IQ
+1407522680,1407522687,SD
1407522688,1407522695,NG
1407522696,1407522703,GL
1407522704,1407522711,NG
@@ -39767,8 +40591,8 @@
1407522736,1407522743,LR
1407522744,1407522751,NG
1407522752,1407522767,ZM
-1407522768,1407522775,A2
-1407522776,1407522791,NG
+1407522768,1407522783,A2
+1407522784,1407522791,NG
1407522792,1407522799,A2
1407522800,1407522807,NG
1407522808,1407522815,A2
@@ -39780,7 +40604,8 @@
1407522856,1407522863,ZW
1407522864,1407522871,TZ
1407522872,1407522879,IQ
-1407522880,1407522895,A2
+1407522880,1407522887,MU
+1407522888,1407522895,A2
1407522896,1407522903,UG
1407522904,1407522911,KE
1407522912,1407522919,CG
@@ -39790,12 +40615,14 @@
1407522944,1407522951,CD
1407522952,1407522967,ZW
1407522968,1407522975,MU
-1407522976,1407522991,A2
+1407522976,1407522983,CD
+1407522984,1407522991,A2
1407522992,1407522999,CD
1407523000,1407523007,A2
1407523008,1407523015,NG
1407523016,1407523023,KE
-1407523024,1407523079,A2
+1407523024,1407523071,A2
+1407523072,1407523079,CD
1407523080,1407523088,NG
1407523089,1407523103,A2
1407523104,1407523111,UG
@@ -39834,23 +40661,35 @@
1407523560,1407523567,KE
1407523568,1407523583,A2
1407523584,1407523591,IQ
-1407523592,1407523839,A2
+1407523592,1407523607,A2
+1407523608,1407523615,IQ
+1407523616,1407523623,A2
+1407523624,1407523631,IQ
+1407523632,1407523639,A2
+1407523640,1407523647,IQ
+1407523648,1407523679,A2
+1407523680,1407523687,IQ
+1407523688,1407523839,A2
1407523840,1407524351,MW
1407524352,1407524607,GB
1407524608,1407524615,ZW
-1407524616,1407524623,CM
+1407524616,1407524623,CD
1407524624,1407524631,ZA
1407524632,1407524639,NG
1407524640,1407524647,KE
1407524648,1407524655,CD
-1407524656,1407524663,NG
+1407524656,1407524663,ZW
1407524664,1407524671,CD
1407524672,1407524679,A2
1407524680,1407524687,LR
1407524688,1407524703,MZ
-1407524704,1407524727,A2
+1407524704,1407524711,A2
+1407524712,1407524719,ZW
+1407524720,1407524727,A2
1407524728,1407524735,NG
-1407524736,1407524759,A2
+1407524736,1407524743,A2
+1407524744,1407524751,ZW
+1407524752,1407524759,A2
1407524760,1407524767,CM
1407524768,1407524775,BW
1407524776,1407524783,A2
@@ -39860,12 +40699,15 @@
1407524840,1407524847,LR
1407524848,1407524855,A2
1407524856,1407524863,CD
-1407524864,1407524887,A2
+1407524864,1407524879,A2
+1407524880,1407524887,ZW
1407524888,1407524895,TZ
1407524896,1407524903,LR
-1407524904,1407524935,A2
+1407524904,1407524911,A2
+1407524912,1407524919,ZW
+1407524920,1407524935,A2
1407524936,1407524943,GR
-1407524944,1407524951,A2
+1407524944,1407524951,ZW
1407524952,1407524959,CM
1407524960,1407524967,TZ
1407524968,1407524975,NG
@@ -39880,11 +40722,11 @@
1407525040,1407525047,ZA
1407525048,1407525055,NG
1407525056,1407525063,ZA
-1407525064,1407525071,A2
+1407525064,1407525071,SO
1407525072,1407525079,NG
1407525080,1407525087,A2
1407525088,1407525095,MW
-1407525096,1407525103,A2
+1407525096,1407525103,ZW
1407525104,1407525111,NG
1407525112,1407525119,ZA
1407525120,1407525127,A2
@@ -39973,8 +40815,7 @@
1407533056,1407533311,NG
1407533312,1407533327,AO
1407533328,1407533343,A2
-1407533344,1407533359,NG
-1407533360,1407533375,A2
+1407533344,1407533375,NG
1407533376,1407533407,CD
1407533408,1407533423,A2
1407533424,1407533567,GH
@@ -40025,8 +40866,7 @@
1407535632,1407535639,SD
1407535640,1407535647,CD
1407535648,1407535655,NG
-1407535656,1407535663,GB
-1407535664,1407535671,A2
+1407535656,1407535671,A2
1407535672,1407535679,SD
1407535680,1407535687,GN
1407535688,1407535695,A2
@@ -40041,8 +40881,7 @@
1407535776,1407535783,GN
1407535784,1407535815,A2
1407535816,1407535823,NG
-1407535824,1407535831,GB
-1407535832,1407535847,A2
+1407535824,1407535847,A2
1407535848,1407535855,CD
1407535856,1407535863,SD
1407535864,1407536127,A2
@@ -40087,9 +40926,7 @@
1407537368,1407537383,NG
1407537384,1407537399,A2
1407537400,1407537407,BF
-1407537408,1407537415,A2
-1407537416,1407537423,GH
-1407537424,1407537431,A2
+1407537408,1407537431,A2
1407537432,1407537447,NG
1407537448,1407537455,UG
1407537456,1407537463,AO
@@ -40100,9 +40937,7 @@
1407537512,1407537519,LR
1407537520,1407537543,A2
1407537544,1407537551,AO
-1407537552,1407537559,A2
-1407537560,1407537567,NG
-1407537568,1407537575,A2
+1407537552,1407537575,A2
1407537576,1407537599,NG
1407537600,1407537607,A2
1407537608,1407537615,CM
@@ -40140,8 +40975,7 @@
1407538072,1407538079,A2
1407538080,1407538087,LR
1407538088,1407538095,AO
-1407538096,1407538103,CD
-1407538104,1407538111,A2
+1407538096,1407538111,A2
1407538112,1407538119,LR
1407538120,1407538127,NG
1407538128,1407538143,A2
@@ -40204,8 +41038,7 @@
1407539720,1407539727,A2
1407539728,1407539735,GR
1407539736,1407539743,NG
-1407539744,1407539751,A2
-1407539752,1407539759,NG
+1407539744,1407539759,A2
1407539760,1407539767,GH
1407539768,1407539775,GR
1407539776,1407539783,A2
@@ -40224,7 +41057,8 @@
1407539928,1407539935,GN
1407539936,1407539943,A2
1407539944,1407539951,CD
-1407539952,1407539967,A2
+1407539952,1407539959,LR
+1407539960,1407539967,A2
1407539968,1407539975,CD
1407539976,1407540055,A2
1407540056,1407540063,NG
@@ -40238,7 +41072,12 @@
1407540160,1407540167,CD
1407540168,1407540199,A2
1407540200,1407540215,CD
-1407540216,1407541471,A2
+1407540216,1407540223,A2
+1407540224,1407540231,AO
+1407540232,1407540239,NG
+1407540240,1407540279,A2
+1407540280,1407540287,NG
+1407540288,1407541471,A2
1407541472,1407541495,NG
1407541496,1407541535,A2
1407541536,1407541543,CM
@@ -40292,13 +41131,18 @@
1407545856,1407545863,CI
1407545864,1407545895,A2
1407545896,1407545903,CD
-1407545904,1407545951,A2
+1407545904,1407545919,A2
+1407545920,1407545927,NG
+1407545928,1407545951,A2
1407545952,1407545959,NG
1407545960,1407545967,A2
1407545968,1407545975,GQ
1407545976,1407545983,A2
1407545984,1407545991,MU
-1407545992,1407546367,A2
+1407545992,1407545999,GN
+1407546000,1407546031,A2
+1407546032,1407546039,NG
+1407546040,1407546367,A2
1407546368,1407546495,AE
1407546496,1407546799,A2
1407546800,1407546815,GH
@@ -40318,8 +41162,7 @@
1407547240,1407547255,SL
1407547256,1407547263,A2
1407547264,1407547271,SL
-1407547272,1407547279,NG
-1407547280,1407547303,A2
+1407547272,1407547303,A2
1407547304,1407547311,SL
1407547312,1407547327,NG
1407547328,1407547335,A2
@@ -40355,19 +41198,18 @@
1407549040,1407549047,NG
1407549048,1407549055,A2
1407549056,1407549063,NG
-1407549064,1407549071,A2
+1407549064,1407549071,GA
1407549072,1407549079,NG
1407549080,1407549127,A2
1407549128,1407549135,NG
-1407549136,1407549183,A2
+1407549136,1407549175,A2
+1407549176,1407549183,NG
1407549184,1407549439,GE
1407549440,1407582207,RU
1407582208,1407614975,PL
1407614976,1407680511,ES
-1407680512,1407680591,FR
-1407680592,1407680607,GB
-1407680608,1407680639,FR
-1407680640,1407681023,GB
+1407680512,1407680671,FR
+1407680672,1407681023,GB
1407681024,1407681087,ES
1407681088,1407681279,GB
1407681280,1407681291,ES
@@ -40705,13 +41547,9 @@
1410036992,1410037247,LB
1410037248,1410037759,A2
1410037760,1410038015,US
-1410038016,1410039807,A2
-1410039808,1410041855,AE
-1410041856,1410042815,A2
+1410038016,1410042815,A2
1410042816,1410042831,US
-1410042832,1410043903,A2
-1410043904,1410044415,JO
-1410044416,1410044927,A2
+1410042832,1410044927,A2
1410044928,1410045183,VG
1410045184,1410045439,IQ
1410045440,1410045695,LB
@@ -40728,9 +41566,7 @@
1410212864,1410213119,GB
1410213120,1410234839,FR
1410234840,1410234847,A2
-1410234848,1410250551,FR
-1410250552,1410250559,GB
-1410250560,1410258527,FR
+1410234848,1410258527,FR
1410258528,1410258535,ES
1410258536,1410261007,FR
1410261008,1410261015,GB
@@ -41031,17 +41867,19 @@
1411919872,1411923967,DE
1411923968,1411940351,BG
1411940352,1411973119,PL
-1411973120,1411999743,SI
-1411999744,1411999783,BA
-1411999784,1411999791,SI
-1411999792,1411999799,BA
-1411999800,1411999807,SI
+1411973120,1411999751,SI
+1411999752,1411999783,BA
+1411999784,1411999807,SI
1411999808,1411999847,BA
1411999848,1411999871,SI
1411999872,1411999887,BA
1411999888,1411999903,SI
-1411999904,1411999943,BA
-1411999944,1411999999,SI
+1411999904,1411999911,BA
+1411999912,1411999919,SI
+1411999920,1411999927,BA
+1411999928,1411999951,SI
+1411999952,1411999959,BA
+1411999960,1411999999,SI
1412000000,1412000767,BA
1412000768,1412000783,SI
1412000784,1412000791,BA
@@ -41086,9 +41924,7 @@
1412003352,1412003375,SI
1412003376,1412003383,BA
1412003384,1412003391,SI
-1412003392,1412003407,BA
-1412003408,1412003423,SI
-1412003424,1412003527,BA
+1412003392,1412003527,BA
1412003528,1412003535,SI
1412003536,1412003551,BA
1412003552,1412003583,SI
@@ -41141,7 +41977,9 @@
1412686240,1412686335,BB
1412686336,1412686591,IE
1412686592,1412686847,GB
-1412686848,1412690191,IE
+1412686848,1412689315,IE
+1412689316,1412689343,GB
+1412689344,1412690191,IE
1412690192,1412690199,GB
1412690200,1412694015,IE
1412694016,1412710399,EE
@@ -41200,7 +42038,9 @@
1422468208,1422468223,IT
1422468224,1422468671,DE
1422468672,1422468735,IT
-1422468736,1422479615,DE
+1422468736,1422476863,DE
+1422476864,1422476895,GB
+1422476896,1422479615,DE
1422479616,1422479871,BE
1422479872,1422491647,DE
1422491648,1422508031,RU
@@ -41219,12 +42059,7 @@
1422761984,1422770175,PL
1422770176,1422786559,GR
1422786560,1422852095,HU
-1422852096,1422853119,FR
-1422853120,1422853631,EU
-1422853632,1422853919,FR
-1422853920,1422854143,EU
-1422854144,1422854151,FR
-1422854152,1422856383,EU
+1422852096,1422856383,EU
1422856384,1422856447,FR
1422856448,1422856703,EU
1422856704,1422857151,FR
@@ -41250,7 +42085,8 @@
1424556032,1424588799,EG
1424588800,1424588839,DE
1424588840,1424588847,GB
-1424588848,1424588959,DE
+1424588848,1424588951,DE
+1424588952,1424588959,GB
1424588960,1424588963,IT
1424588964,1424589311,DE
1424589312,1424589567,FR
@@ -41305,16 +42141,16 @@
1424597344,1424597351,CH
1424597352,1424597375,GB
1424597376,1424597391,CZ
-1424597392,1424597503,GB
+1424597392,1424597407,GB
+1424597408,1424597423,CZ
+1424597424,1424597503,GB
1424597504,1424597759,FR
1424597760,1424598015,IT
1424598016,1424599039,GB
1424599040,1424599279,DK
1424599280,1424599295,GB
1424599296,1424599551,DK
-1424599552,1424599839,HU
-1424599840,1424599847,GB
-1424599848,1424599855,HU
+1424599552,1424599855,HU
1424599856,1424599871,GB
1424599872,1424599875,HU
1424599876,1424599879,GB
@@ -41369,7 +42205,10 @@
1424605696,1424605951,NL
1424605952,1424605959,CH
1424605960,1424606023,AT
-1424606024,1424607167,GB
+1424606024,1424606207,GB
+1424606208,1424606719,IT
+1424606720,1424606975,NL
+1424606976,1424607167,GB
1424607168,1424607199,SK
1424607200,1424607215,GB
1424607216,1424607223,SK
@@ -41384,8 +42223,8 @@
1424608384,1424608399,ES
1424608400,1424608511,FR
1424608512,1424608687,ES
-1424608688,1424608695,GB
-1424608696,1424609023,ES
+1424608688,1424608691,GB
+1424608692,1424609023,ES
1424609024,1424609259,DE
1424609260,1424609271,GB
1424609272,1424609279,DE
@@ -41447,12 +42286,12 @@
1424617408,1424617423,ES
1424617424,1424617431,GB
1424617432,1424617439,ES
-1424617440,1424617463,IT
+1424617440,1424617447,IT
+1424617448,1424617455,GB
+1424617456,1424617463,IT
1424617464,1424617471,GB
1424617472,1424617727,US
-1424617728,1424617983,IT
-1424617984,1424618015,GB
-1424618016,1424618039,IT
+1424617728,1424618039,IT
1424618040,1424618047,GB
1424618048,1424618239,IT
1424618240,1424618495,NL
@@ -41462,9 +42301,7 @@
1424618944,1424619007,FR
1424619008,1424619775,IT
1424619776,1424619807,BE
-1424619808,1424619815,GB
-1424619816,1424619823,BE
-1424619824,1424619839,GB
+1424619808,1424619839,GB
1424619840,1424619915,BE
1424619916,1424619919,GB
1424619920,1424620031,BE
@@ -42025,12 +42862,15 @@
1427723520,1427728479,DE
1427728480,1427728511,CY
1427728512,1427728543,BR
-1427728544,1427728671,DE
+1427728544,1427728575,DE
+1427728576,1427728607,BR
+1427728608,1427728639,TW
+1427728640,1427728671,DE
1427728672,1427728703,TR
1427728704,1427728799,DE
1427728800,1427728831,RU
1427728832,1427728895,CY
-1427728896,1427728927,DE
+1427728896,1427728927,RU
1427728928,1427728959,IL
1427728960,1427728991,RU
1427728992,1427729055,DE
@@ -42058,34 +42898,37 @@
1427743616,1427743647,DK
1427743648,1427743775,DE
1427743776,1427743807,ZA
-1427743808,1427743839,US
+1427743808,1427743839,DE
1427743840,1427743871,RU
1427743872,1427743935,DE
1427743936,1427743967,RU
1427743968,1427744127,DE
1427744128,1427744159,PL
1427744160,1427744191,RU
-1427744192,1427744223,TR
-1427744224,1427744255,DE
+1427744192,1427744255,DE
1427744256,1427744287,US
1427744288,1427744319,TR
1427744320,1427744351,DE
1427744352,1427744383,UA
1427744384,1427744415,PL
1427744416,1427744447,UA
-1427744448,1427744639,DE
+1427744448,1427744479,US
+1427744480,1427744639,DE
1427744640,1427744671,TR
1427744672,1427744735,DE
1427744736,1427744767,DK
1427744768,1427744863,DE
1427744864,1427744927,TR
-1427744928,1427744991,DE
+1427744928,1427744959,HU
+1427744960,1427744991,DE
1427744992,1427745023,DK
1427745024,1427745055,BM
1427745056,1427745151,DE
1427745152,1427745183,RO
1427745184,1427745215,CH
-1427745216,1427745439,DE
+1427745216,1427745375,DE
+1427745376,1427745407,TW
+1427745408,1427745439,DE
1427745440,1427745471,US
1427745472,1427745503,DE
1427745504,1427745535,RU
@@ -42099,7 +42942,8 @@
1427745760,1427745791,LT
1427745792,1427745823,GB
1427745824,1427745855,US
-1427745856,1427746079,DE
+1427745856,1427746047,DE
+1427746048,1427746079,SE
1427746080,1427746111,GB
1427746112,1427746143,DE
1427746144,1427746175,GR
@@ -42120,33 +42964,42 @@
1427748480,1427748511,TR
1427748512,1427748543,DE
1427748544,1427748575,MX
-1427748576,1427748799,DE
+1427748576,1427748703,DE
+1427748704,1427748735,US
+1427748736,1427748799,DE
1427748800,1427748831,US
1427748832,1427749567,DE
1427749568,1427749599,CY
-1427749600,1427749631,NL
+1427749600,1427749631,DE
1427749632,1427749663,US
-1427749664,1427749887,DE
+1427749664,1427749855,DE
+1427749856,1427749887,RU
1427749888,1427749919,BR
1427749920,1427749951,DE
1427749952,1427749983,RU
1427749984,1427750079,DE
1427750080,1427750111,BG
-1427750112,1427750239,DE
+1427750112,1427750175,DE
+1427750176,1427750207,TR
+1427750208,1427750239,DE
1427750240,1427750271,US
-1427750272,1427750303,DE
+1427750272,1427750303,GR
1427750304,1427750335,GB
-1427750336,1427751167,DE
+1427750336,1427750367,US
+1427750368,1427751167,DE
1427751168,1427751423,NL
1427751424,1427759935,DE
1427759936,1427759967,HR
-1427759968,1427760191,DE
+1427759968,1427760031,DE
+1427760032,1427760063,US
+1427760064,1427760191,DE
1427760192,1427760255,US
1427760256,1427760319,BR
1427760320,1427760351,TR
1427760352,1427760383,RU
1427760384,1427760415,TR
-1427760416,1427760575,DE
+1427760416,1427760447,US
+1427760448,1427760575,DE
1427760576,1427760607,CH
1427760608,1427760799,DE
1427760800,1427760831,US
@@ -42187,9 +43040,7 @@
1428045824,1428062207,MK
1428062208,1428078591,SE
1428078592,1428094975,RU
-1428094976,1428096031,AT
-1428096032,1428096039,CH
-1428096040,1428103167,AT
+1428094976,1428103167,AT
1428103168,1428111359,GB
1428111360,1428119551,A2
1428119552,1428121599,LV
@@ -42507,7 +43358,8 @@
1434615808,1434648575,IL
1434648576,1434681343,FI
1434681344,1434681983,DE
-1434681984,1434682111,NL
+1434681984,1434682015,CY
+1434682016,1434682111,NL
1434682112,1434682303,DE
1434682304,1434682367,NL
1434682368,1434683119,DE
@@ -42734,12 +43586,9 @@
1438890240,1438890495,RU
1438890496,1438890751,IQ
1438890752,1438892031,RU
-1438892032,1438892287,US
-1438892288,1438900223,IS
-1438900224,1438900479,AQ
-1438900480,1438904319,IS
-1438904320,1438904575,CH
-1438904576,1438908415,IS
+1438892032,1438895359,CH
+1438895360,1438900223,IS
+1438900224,1438908415,AQ
1438908416,1438924799,GR
1438924800,1438941183,NO
1438941184,1438957567,BG
@@ -42917,7 +43766,9 @@
1441389224,1441389231,LU
1441389232,1441389567,FR
1441389568,1441389599,LU
-1441389600,1441390591,FR
+1441389600,1441389967,FR
+1441389968,1441389983,CA
+1441389984,1441390591,FR
1441390592,1441398783,DK
1441398784,1441415167,RU
1441415168,1441423359,GB
@@ -43231,7 +44082,8 @@
1446905124,1446905127,AF
1446905128,1446905131,IQ
1446905132,1446905135,A2
-1446905136,1446905143,IQ
+1446905136,1446905139,LY
+1446905140,1446905143,IQ
1446905144,1446905147,A2
1446905148,1446905151,LY
1446905152,1446905155,AF
@@ -43427,7 +44279,7 @@
1446907112,1446907115,IQ
1446907116,1446907123,A2
1446907124,1446907131,IQ
-1446907132,1446907135,A2
+1446907132,1446907135,AF
1446907136,1446907139,IQ
1446907140,1446907143,A2
1446907144,1446907147,AF
@@ -43982,7 +44834,8 @@
1446911568,1446911571,IQ
1446911572,1446911575,LY
1446911576,1446911579,IQ
-1446911580,1446911595,A2
+1446911580,1446911583,CG
+1446911584,1446911595,A2
1446911596,1446911597,LY
1446911598,1446911619,A2
1446911620,1446911623,GH
@@ -44016,7 +44869,7 @@
1446911788,1446911791,AF
1446911792,1446911795,LY
1446911796,1446911799,IQ
-1446911800,1446911803,A2
+1446911800,1446911803,NG
1446911804,1446911811,LY
1446911812,1446911815,IQ
1446911816,1446911819,LY
@@ -44131,11 +44984,7 @@
1449656320,1449657087,GB
1449657088,1449658623,RO
1449658624,1449659135,GB
-1449659136,1449660415,RO
-1449660416,1449662463,GB
-1449662464,1449676799,RO
-1449676800,1449678847,GB
-1449678848,1449685759,RO
+1449659136,1449685759,RO
1449685760,1449686271,GB
1449686272,1449686527,RO
1449686528,1449687039,GB
@@ -44147,9 +44996,7 @@
1449705472,1449705727,GB
1449705728,1449706239,RO
1449706240,1449706495,GB
-1449706496,1449707519,RO
-1449707520,1449709567,GB
-1449709568,1449710591,RO
+1449706496,1449710591,RO
1449710592,1449711103,GB
1449711104,1449711359,RO
1449711360,1449711615,GB
@@ -44208,8 +45055,8 @@
1449899008,1449899263,GB
1449899264,1449899519,RO
1449899520,1449899775,GB
-1449899776,1449904127,RO
-1449904128,1449910271,GB
+1449899776,1449908223,RO
+1449908224,1449910271,GB
1449910272,1449918463,RO
1449918464,1449951231,JO
1449951232,1449983999,TR
@@ -44392,9 +45239,7 @@
1467466272,1467466495,NL
1467466496,1467467071,DE
1467467072,1467467103,CH
-1467467104,1467467903,DE
-1467467904,1467468031,CH
-1467468032,1467468111,DE
+1467467104,1467468111,DE
1467468112,1467468119,BR
1467468120,1467473919,DE
1467473920,1467482111,RU
@@ -44486,7 +45331,6 @@
1475131392,1475133439,RU
1475133440,1475135487,CZ
1475135488,1475137535,CH
-1475137536,1475139583,SE
1475139584,1475141631,ES
1475141632,1475143679,FI
1475143680,1475145727,JO
@@ -44571,9 +45415,9 @@
1475223552,1475229695,NO
1475229696,1475229759,SE
1475229760,1475229951,NO
-1475229952,1475230111,SE
-1475230112,1475230199,NO
-1475230200,1475230207,SE
+1475229952,1475230175,SE
+1475230176,1475230191,NO
+1475230192,1475230207,SE
1475230208,1475233791,NO
1475233792,1475234303,GB
1475234304,1475234559,IE
@@ -45044,7 +45888,6 @@
1486323448,1486323455,GB
1486323456,1486323711,EU
1486323712,1486325759,GB
-1486325760,1486327807,SA
1486327808,1486329855,CH
1486329856,1486331903,FR
1486331904,1486333951,NO
@@ -45340,7 +46183,9 @@
1495146496,1495150591,FR
1495150592,1495151103,GB
1495151104,1495151359,NL
-1495151360,1495154687,FR
+1495151360,1495153919,FR
+1495153920,1495154175,TR
+1495154176,1495154687,FR
1495154688,1495161599,EU
1495161600,1495161855,FR
1495161856,1495162367,EU
@@ -45458,9 +46303,7 @@
1495927296,1495927551,AE
1495927552,1495937023,RO
1495937024,1495937535,ES
-1495937536,1495986175,RO
-1495986176,1495988223,GB
-1495988224,1495990271,RO
+1495937536,1495990271,RO
1495990272,1495994367,GB
1495994368,1496078335,RO
1496078336,1496079359,MD
@@ -45504,11 +46347,13 @@
1500107944,1500107951,DE
1500107952,1500107999,NL
1500108000,1500108007,BE
-1500108008,1500108159,NL
-1500108160,1500108287,DE
+1500108008,1500108095,NL
+1500108096,1500108287,DE
1500108288,1500108319,NL
1500108320,1500108351,DE
-1500108352,1500110847,NL
+1500108352,1500108367,NL
+1500108368,1500108375,DE
+1500108376,1500110847,NL
1500110848,1500119039,UA
1500119040,1500127231,TR
1500127232,1500135423,FI
@@ -45643,13 +46488,11 @@
1502674944,1502691327,DE
1502691328,1502691679,GB
1502691680,1502691711,SE
-1502691712,1502692415,GB
-1502692416,1502692479,ES
-1502692480,1502706623,GB
+1502691712,1502702835,GB
+1502702836,1502702839,IE
+1502702840,1502706623,GB
1502706624,1502706687,CY
-1502706688,1502707631,GB
-1502707632,1502707639,IE
-1502707640,1502707711,GB
+1502706688,1502707711,GB
1502707712,1502724095,RU
1502724096,1502740479,GB
1502740480,1502756863,NL
@@ -45758,7 +46601,8 @@
1503895608,1503895631,DE
1503895632,1503895639,AT
1503895640,1503895647,GR
-1503895648,1503895671,DE
+1503895648,1503895663,DE
+1503895664,1503895671,FR
1503895672,1503895679,PL
1503895680,1503895687,IT
1503895688,1503895695,DE
@@ -45822,8 +46666,7 @@
1503898576,1503898599,DE
1503898600,1503898607,IT
1503898608,1503898615,GR
-1503898616,1503898623,SE
-1503898624,1503898631,DE
+1503898616,1503898631,DE
1503898632,1503898647,GR
1503898648,1503898679,DE
1503898680,1503898687,IT
@@ -45837,7 +46680,9 @@
1503898888,1503898895,IT
1503898896,1503898935,DE
1503898936,1503898943,IT
-1503898944,1503898991,DE
+1503898944,1503898959,DE
+1503898960,1503898967,IT
+1503898968,1503898991,DE
1503898992,1503898999,GB
1503899000,1503899007,AT
1503899008,1503899063,DE
@@ -45848,7 +46693,13 @@
1503899144,1503899151,IT
1503899152,1503899159,DE
1503899160,1503899167,GB
-1503899168,1503908351,DE
+1503899168,1503899183,DE
+1503899184,1503899191,GR
+1503899192,1503899199,CH
+1503899200,1503899263,DE
+1503899264,1503899271,AT
+1503899272,1503899287,BE
+1503899288,1503908351,DE
1503908352,1503909375,IT
1503909376,1503920127,DE
1503920128,1503985663,HR
@@ -45927,10 +46778,10 @@
1505312768,1505320959,RU
1505320960,1505321103,AT
1505321104,1505321135,DE
-1505321136,1505321407,AT
-1505321408,1505321439,DE
-1505321440,1505321631,AT
-1505321632,1505321823,DE
+1505321136,1505321423,AT
+1505321424,1505321439,DE
+1505321440,1505321663,AT
+1505321664,1505321823,DE
1505321824,1505321831,AT
1505321832,1505321983,DE
1505321984,1505322287,AT
@@ -45955,8 +46806,8 @@
1505336064,1505336071,GB
1505336072,1505336576,IE
1505336577,1505336639,GB
-1505336640,1505336831,IE
-1505336832,1505336863,GB
+1505336640,1505336823,IE
+1505336824,1505336863,GB
1505336864,1505336864,IE
1505336865,1505336879,GB
1505336880,1505336959,IE
@@ -46023,8 +46874,8 @@
1505455768,1505455791,GB
1505455792,1505455799,US
1505455800,1505455999,GB
-1505456000,1505456063,US
-1505456064,1505456127,GB
+1505456000,1505456079,US
+1505456080,1505456127,GB
1505456128,1505456255,US
1505456256,1505456639,GB
1505456640,1505456895,US
@@ -46082,7 +46933,9 @@
1505709056,1505714175,DE
1505714176,1505722367,LV
1505722368,1505738751,PL
-1505738752,1505745839,GB
+1505738752,1505745135,GB
+1505745136,1505745151,ES
+1505745152,1505745839,GB
1505745840,1505745855,IL
1505745856,1505746943,GB
1505746944,1505755135,RU
@@ -46107,7 +46960,9 @@
1506418688,1506418695,CY
1506418696,1506418703,GB
1506418704,1506418719,CA
-1506418720,1506422655,DE
+1506418720,1506418975,DE
+1506418976,1506418983,CA
+1506418984,1506422655,DE
1506422656,1506422687,CY
1506422688,1506422703,CA
1506422704,1506422711,GB
@@ -46218,9 +47073,9 @@
1506444288,1506445311,DE
1506445312,1506445337,FR
1506445338,1506445343,GB
-1506445344,1506445407,FR
-1506445408,1506445439,GB
-1506445440,1506445519,FR
+1506445344,1506445415,FR
+1506445416,1506445423,GB
+1506445424,1506445519,FR
1506445520,1506445527,GB
1506445528,1506445703,FR
1506445704,1506445711,NL
@@ -46246,9 +47101,7 @@
1506448704,1506448895,GB
1506448896,1506449159,BE
1506449160,1506449171,GB
-1506449172,1506449255,BE
-1506449256,1506449263,GB
-1506449264,1506449407,BE
+1506449172,1506449407,BE
1506449408,1506449663,NL
1506449664,1506449919,SK
1506449920,1506449927,CH
@@ -46261,7 +47114,8 @@
1506450848,1506450863,CZ
1506450864,1506450879,GB
1506450880,1506450943,CZ
-1506450944,1506451007,GB
+1506450944,1506450958,DK
+1506450959,1506451007,GB
1506451008,1506451023,DK
1506451024,1506451031,FI
1506451032,1506451039,DK
@@ -46318,7 +47172,9 @@
1506460064,1506460079,GB
1506460080,1506460126,FR
1506460127,1506460127,GB
-1506460128,1506460335,FR
+1506460128,1506460315,FR
+1506460316,1506460319,GB
+1506460320,1506460335,FR
1506460336,1506460343,GB
1506460344,1506460671,FR
1506460672,1506460927,AT
@@ -46336,7 +47192,8 @@
1506462208,1506462463,ES
1506462464,1506462527,FR
1506462528,1506462583,GB
-1506462584,1506462607,FR
+1506462584,1506462599,FR
+1506462600,1506462607,GB
1506462608,1506462623,A2
1506462624,1506462719,FR
1506462720,1506463231,IT
@@ -46373,8 +47230,8 @@
1506472704,1506473215,IT
1506473216,1506473471,GB
1506473472,1506474247,IT
-1506474248,1506474271,GB
-1506474272,1506474495,IT
+1506474248,1506474255,GB
+1506474256,1506474495,IT
1506474496,1506474751,FR
1506474752,1506475519,IT
1506475520,1506475559,AT
@@ -46410,7 +47267,13 @@
1506767616,1506767679,NO
1506767680,1506768895,GE
1506768896,1506770943,AT
-1506770944,1506772991,NL
+1506770944,1506771971,NL
+1506771972,1506771973,IR
+1506771974,1506772014,NL
+1506772015,1506772036,IR
+1506772037,1506772938,NL
+1506772939,1506772939,IR
+1506772940,1506772991,NL
1506772992,1506775039,GB
1506775040,1506777087,AT
1506777088,1506781695,GB
@@ -46698,7 +47561,9 @@
1518510080,1518516479,LV
1518516480,1518517247,SE
1518517248,1518518271,LV
-1518518272,1518665727,SE
+1518518272,1518551039,SE
+1518551040,1518565375,NL
+1518565376,1518665727,SE
1518665728,1518727167,RU
1518727168,1518731263,SE
1518731264,1518927871,DE
@@ -46942,7 +47807,6 @@
1533421568,1533423615,NL
1533423616,1533425663,IT
1533425664,1533429759,GB
-1533429760,1533431807,IT
1533431808,1533433855,IE
1533433856,1533435903,DK
1533435904,1533437951,CZ
@@ -47066,7 +47930,8 @@
1534714384,1534714399,FR
1534714400,1534714403,GB
1534714404,1534714407,PL
-1534714408,1534714431,GB
+1534714408,1534714415,DE
+1534714416,1534714431,GB
1534714432,1534714463,FR
1534714464,1534714495,GB
1534714496,1534714511,FR
@@ -47085,7 +47950,9 @@
1534714752,1534714767,DE
1534714768,1534714783,FR
1534714784,1534714799,PL
-1534714800,1534714831,FR
+1534714800,1534714815,FR
+1534714816,1534714819,BE
+1534714820,1534714831,FR
1534714832,1534714847,BE
1534714848,1534714855,GB
1534714856,1534714863,CH
@@ -47110,7 +47977,9 @@
1534715208,1534715215,BE
1534715216,1534715263,FR
1534715264,1534715279,ES
-1534715280,1534715295,FR
+1534715280,1534715283,PL
+1534715284,1534715287,FR
+1534715288,1534715295,PL
1534715296,1534715299,ES
1534715300,1534715303,FR
1534715304,1534715307,ES
@@ -47121,7 +47990,7 @@
1534715328,1534715359,FR
1534715360,1534715367,PL
1534715368,1534715371,FR
-1534715372,1534715375,GB
+1534715372,1534715375,CH
1534715376,1534715391,ES
1534715392,1534715407,PL
1534715408,1534715419,DE
@@ -47217,7 +48086,10 @@
1534717140,1534717143,BE
1534717144,1534717147,FR
1534717148,1534717151,IT
-1534717152,1534717263,FR
+1534717152,1534717247,FR
+1534717248,1534717251,CZ
+1534717252,1534717255,NL
+1534717256,1534717263,FR
1534717264,1534717267,PL
1534717268,1534717315,FR
1534717316,1534717319,IE
@@ -47367,10 +48239,11 @@
1534720112,1534720127,ES
1534720128,1534720211,FR
1534720212,1534720215,PL
-1534720216,1534720223,FR
+1534720216,1534720219,FR
+1534720220,1534720223,GB
1534720224,1534720239,DE
1534720240,1534720255,BE
-1534720256,1534720271,NL
+1534720256,1534720271,FR
1534720272,1534720287,PL
1534720288,1534720291,IT
1534720292,1534720295,PL
@@ -47415,7 +48288,7 @@
1534720864,1534720879,ES
1534720880,1534720895,FR
1534720896,1534720899,ES
-1534720900,1534720903,GB
+1534720900,1534720903,LT
1534720904,1534720943,FR
1534720944,1534720951,ES
1534720952,1534720959,PL
@@ -47466,8 +48339,8 @@
1534721496,1534721519,PL
1534721520,1534721527,FR
1534721528,1534721531,ES
-1534721532,1534721535,FR
-1534721536,1534721583,GB
+1534721532,1534721567,FR
+1534721568,1534721583,GB
1534721584,1534721599,FR
1534721600,1534721619,ES
1534721620,1534721627,PL
@@ -47481,7 +48354,7 @@
1534721756,1534721823,FR
1534721824,1534721827,PL
1534721828,1534721831,FR
-1534721832,1534721835,PL
+1534721832,1534721835,DE
1534721836,1534721839,BE
1534721840,1534721855,PL
1534721856,1534721887,ES
@@ -47496,8 +48369,7 @@
1534721968,1534721971,DE
1534721972,1534721975,PL
1534721976,1534721979,ES
-1534721980,1534721983,FR
-1534721984,1534722007,PL
+1534721980,1534722007,PL
1534722008,1534722011,PT
1534722012,1534722015,ES
1534722016,1534722039,FR
@@ -47690,8 +48562,7 @@
1536660016,1536660019,CG
1536660020,1536660023,DE
1536660024,1536660031,CG
-1536660032,1536660039,DJ
-1536660040,1536660735,DE
+1536660032,1536660735,DE
1536660736,1536660991,SA
1536660992,1536661247,DE
1536661248,1536661759,GQ
@@ -47700,7 +48571,8 @@
1536662304,1536662335,LB
1536662336,1536662367,DE
1536662368,1536662399,SO
-1536662400,1536662415,DE
+1536662400,1536662407,DE
+1536662408,1536662415,SO
1536662416,1536662431,GN
1536662432,1536662463,IQ
1536662464,1536662527,SO
@@ -47711,11 +48583,11 @@
1536663312,1536663319,DE
1536663320,1536663327,LB
1536663328,1536663343,DE
-1536663344,1536663391,IQ
-1536663392,1536663423,DE
+1536663344,1536663359,IQ
+1536663360,1536663423,DE
1536663424,1536663551,KW
1536663552,1536667647,SA
-1536667648,1536675839,RU
+1536671744,1536675839,RU
1536675840,1536679935,GB
1536679936,1536684031,LB
1536684032,1536688127,GB
@@ -47797,9 +48669,7 @@
1539049216,1539049223,LY
1539049224,1539049255,IT
1539049256,1539049263,LY
-1539049264,1539049279,IT
-1539049280,1539049287,LY
-1539049288,1539049311,IT
+1539049264,1539049311,IT
1539049312,1539049327,LY
1539049328,1539049335,IT
1539049336,1539049343,LY
@@ -47868,13 +48738,13 @@
1539219712,1539221503,GG
1539221504,1539222527,FR
1539222528,1539222783,HK
-1539222784,1539223551,FR
+1539222784,1539223039,CN
+1539223040,1539223551,FR
1539223552,1539225599,DE
1539225600,1539227647,HU
1539227648,1539229695,FI
1539229696,1539231743,DE
1539231744,1539233791,BE
-1539233792,1539235839,GR
1539235840,1539237887,DE
1539237888,1539239935,RU
1539239936,1539244031,DE
@@ -47952,7 +48822,6 @@
1539379200,1539380223,EU
1539380224,1539381247,CH
1539381248,1539382271,RS
-1539382272,1539383295,PL
1539383296,1539384319,UA
1539384320,1539385343,RU
1539385344,1539385855,PL
@@ -48080,7 +48949,6 @@
1539482112,1539482623,UA
1539482624,1539483135,RU
1539483136,1539483647,ES
-1539483648,1539484159,NL
1539484160,1539484671,GB
1539484672,1539485695,RU
1539485696,1539486207,RO
@@ -48402,8 +49270,7 @@
1539718912,1539719167,KZ
1539719168,1539719423,IE
1539719424,1539719679,PL
-1539719680,1539719935,IE
-1539719936,1539720191,DE
+1539719680,1539720191,DE
1539720192,1539720703,RU
1539720704,1539720959,IL
1539720960,1539721215,RU
@@ -48630,7 +49497,6 @@
1539780608,1539780863,PL
1539780864,1539781119,RO
1539781120,1539781375,NL
-1539781376,1539781631,DE
1539781632,1539781887,HU
1539781888,1539782143,IL
1539782144,1539782399,UA
@@ -48653,7 +49519,6 @@
1539786752,1539787007,HU
1539787008,1539787263,TR
1539787264,1539787519,IE
-1539787520,1539787775,UA
1539787776,1539788031,CH
1539788032,1539788287,HR
1539788288,1539788543,GB
@@ -48975,7 +49840,6 @@
1540026368,1540028415,UA
1540028416,1540029439,ES
1540029440,1540030463,RU
-1540030464,1540031487,DE
1540031488,1540032511,UA
1540032512,1540033535,RU
1540033536,1540034559,UA
@@ -49121,7 +49985,6 @@
1540206592,1540208639,RU
1540208640,1540209663,NO
1540209664,1540211711,RU
-1540211712,1540212735,DE
1540212736,1540213759,RU
1540213760,1540214783,UA
1540214784,1540215807,RU
@@ -49818,7 +50681,7 @@
1540488704,1540488959,DE
1540488960,1540489215,RO
1540489216,1540491263,RU
-1540491264,1540493311,UA
+1540491264,1540492287,UA
1540493312,1540494335,CZ
1540494336,1540495359,UA
1540495360,1540496383,RU
@@ -49829,14 +50692,13 @@
1540502528,1540503551,RU
1540503552,1540504575,NL
1540504576,1540505599,SE
-1540505600,1540506623,RU
1540506624,1540507647,GB
1540507648,1540508671,RU
1540508672,1540509695,UA
1540509696,1540510719,RO
1540510720,1540511743,RU
1540511744,1540512767,BG
-1540512768,1540514815,UA
+1540513792,1540514815,UA
1540514816,1540515839,GB
1540515840,1540516863,RU
1540516864,1540517887,UA
@@ -50432,7 +51294,6 @@
1540818944,1540819967,UA
1540819968,1540820991,CZ
1540820992,1540822015,RU
-1540822016,1540823039,FR
1540823040,1540824063,UA
1540824064,1540825087,RU
1540825088,1540826111,PL
@@ -51284,7 +52145,6 @@
1541236736,1541237247,DE
1541237248,1541237759,RU
1541237760,1541238271,CZ
-1541238272,1541238783,ES
1541238784,1541239295,SK
1541239296,1541239807,PL
1541239808,1541240319,RU
@@ -51355,7 +52215,6 @@
1541275136,1541275647,FR
1541275648,1541276671,UA
1541276672,1541277695,RS
-1541277696,1541278719,ES
1541278720,1541280767,UA
1541280768,1541281791,BG
1541281792,1541282815,PL
@@ -51688,8 +52547,7 @@
1541426176,1541426687,RU
1541426688,1541427199,UA
1541427200,1541428223,RU
-1541428224,1541428735,UA
-1541428736,1541429247,RU
+1541428224,1541429247,UA
1541429248,1541429759,FI
1541429760,1541430271,CZ
1541430272,1541430783,LT
@@ -51819,7 +52677,7 @@
1541543936,1541544447,GB
1541544448,1541544959,PL
1541544960,1541545471,FR
-1541545472,1541545983,RU
+1541545472,1541545983,NL
1541545984,1541546495,LV
1541546496,1541547007,UA
1541547008,1541547519,SE
@@ -51885,7 +52743,6 @@
1541589248,1541589503,UA
1541589504,1541590015,CH
1541590016,1541590527,RU
-1541590528,1541590783,DK
1541590784,1541591039,UA
1541591040,1541592063,RU
1541592064,1541592575,UA
@@ -51908,6 +52765,167 @@
1541602048,1541602303,PL
1541602304,1541603327,UA
1541603328,1541604351,PL
+1541604352,1541605119,TR
+1541605120,1541605375,CZ
+1541605376,1541606911,RU
+1541606912,1541607423,UZ
+1541607424,1541608447,RU
+1541608448,1541608703,DE
+1541608704,1541608959,PL
+1541608960,1541609215,SA
+1541609216,1541609471,RU
+1541609472,1541609983,SA
+1541609984,1541610239,GB
+1541610240,1541610495,NL
+1541610496,1541611775,RU
+1541611776,1541612031,RO
+1541612032,1541612543,RU
+1541612544,1541614079,PL
+1541614080,1541614335,UA
+1541614336,1541614591,SI
+1541614592,1541615615,RU
+1541615616,1541615871,CH
+1541615872,1541616127,SE
+1541616128,1541617663,RU
+1541617664,1541619199,PL
+1541619200,1541619455,GB
+1541619456,1541620735,PL
+1541620736,1541620991,RU
+1541620992,1541621247,UA
+1541621248,1541621759,IL
+1541621760,1541622271,RO
+1541622272,1541622527,RU
+1541622528,1541622783,NL
+1541622784,1541623295,PL
+1541623296,1541623551,GB
+1541623552,1541623679,RU
+1541623808,1541624831,PL
+1541624832,1541625855,RU
+1541625856,1541626367,PL
+1541626368,1541626623,RO
+1541626624,1541627903,RU
+1541627904,1541628415,CZ
+1541628416,1541628927,DE
+1541628928,1541629183,PT
+1541629184,1541629439,LV
+1541629440,1541630975,PL
+1541630976,1541631231,GR
+1541631232,1541631487,IT
+1541631488,1541631999,SI
+1541632000,1541632511,RU
+1541632512,1541632767,NL
+1541632768,1541633023,SK
+1541633024,1541634303,PL
+1541634304,1541634559,MD
+1541634560,1541635071,PL
+1541635072,1541636095,UA
+1541636096,1541636863,AT
+1541636864,1541637119,RO
+1541637120,1541637631,PL
+1541637632,1541638143,CZ
+1541638144,1541638399,RU
+1541638400,1541638655,FR
+1541638656,1541639167,HU
+1541639168,1541640191,RU
+1541640192,1541641215,KZ
+1541641216,1541641727,RU
+1541641728,1541642239,UA
+1541642240,1541643263,RU
+1541643264,1541644287,PL
+1541644288,1541645311,RU
+1541645312,1541645823,IL
+1541646080,1541646335,PL
+1541646336,1541646847,RU
+1541646848,1541647359,NO
+1541647360,1541648383,RU
+1541648384,1541648639,PL
+1541648640,1541648895,DK
+1541648896,1541649151,GB
+1541649152,1541649407,NL
+1541649408,1541650431,UA
+1541650432,1541650687,RU
+1541650688,1541650943,MD
+1541650944,1541651199,SE
+1541651200,1541651455,FI
+1541651456,1541652479,RU
+1541652480,1541652991,FI
+1541652992,1541653247,FR
+1541653248,1541653503,CZ
+1541653504,1541654015,PL
+1541654016,1541654271,RU
+1541654272,1541655551,PL
+1541655552,1541656063,AT
+1541656064,1541656575,UA
+1541656576,1541656831,SE
+1541656832,1541657087,BE
+1541657088,1541657599,RU
+1541657600,1541659647,PL
+1541659648,1541660671,GB
+1541660672,1541661695,SK
+1541661696,1541661951,RU
+1541661952,1541662207,NL
+1541662208,1541662719,RO
+1541662720,1541663743,CZ
+1541663744,1541664767,RO
+1541664768,1541666047,RU
+1541666048,1541666815,GB
+1541666816,1541667839,NO
+1541667840,1541668095,CH
+1541668096,1541668351,GB
+1541668352,1541668607,UA
+1541668608,1541668863,GE
+1541668864,1541669887,GB
+1541669888,1541670911,LV
+1541670912,1541671423,PL
+1541671424,1541671679,RU
+1541671680,1541671935,PL
+1541671936,1541672959,UA
+1541672960,1541674495,RS
+1541674496,1541675007,KG
+1541675008,1541675519,IE
+1541675520,1541676031,RU
+1541676288,1541676543,RO
+1541676544,1541677055,RU
+1541677056,1541678079,PL
+1541678080,1541678591,RO
+1541678592,1541678847,BG
+1541678848,1541679615,RU
+1541679616,1541680127,PL
+1541680128,1541681151,CZ
+1541681152,1541682175,RU
+1541682176,1541682687,DE
+1541682688,1541683199,RU
+1541683200,1541683455,PL
+1541683456,1541683711,RU
+1541683712,1541684223,UA
+1541684224,1541684735,CH
+1541684736,1541686271,RU
+1541686272,1541687295,UA
+1541687296,1541688319,GB
+1541688320,1541688831,RU
+1541688832,1541689343,GB
+1541689344,1541690367,PL
+1541690368,1541691391,LT
+1541691392,1541691903,PL
+1541691904,1541692159,SE
+1541692160,1541692415,ES
+1541692416,1541693439,PL
+1541693440,1541694463,RU
+1541694464,1541694719,CZ
+1541694720,1541694975,CH
+1541694976,1541695487,RU
+1541695488,1541696511,DE
+1541696512,1541697535,MD
+1541697536,1541698047,PL
+1541698048,1541698303,DK
+1541698304,1541698559,GB
+1541698560,1541699327,RU
+1541699328,1541699583,RO
+1541699584,1541700095,RU
+1541700096,1541700607,UA
+1541700608,1541700863,RU
+1541700864,1541701119,PL
+1541701632,1541702655,RO
1543503872,1545601023,GB
1545601024,1545673167,SE
1545673168,1545673175,FI
@@ -52032,7 +53050,9 @@
1546379264,1546381311,ES
1546381312,1546383359,DK
1546383360,1546385407,IT
-1546385408,1546387455,FR
+1546385408,1546385535,FR
+1546385536,1546385599,US
+1546385600,1546387455,FR
1546387456,1546460960,TR
1546460961,1546460967,NL
1546460968,1546518527,TR
@@ -52138,8 +53158,8 @@
1547620352,1547620359,A2
1547620360,1547620367,NG
1547620368,1547620375,A2
-1547620376,1547620383,NG
-1547620384,1547620399,A2
+1547620376,1547620391,NG
+1547620392,1547620399,A2
1547620400,1547620407,NG
1547620408,1547620415,A2
1547620416,1547620423,NG
@@ -52160,17 +53180,15 @@
1547620936,1547620951,A2
1547620952,1547620959,NG
1547620960,1547620967,A2
-1547620968,1547620983,NG
-1547620984,1547620999,A2
+1547620968,1547620991,NG
+1547620992,1547620999,A2
1547621000,1547621031,NG
1547621032,1547621039,A2
1547621040,1547621063,NG
1547621064,1547621071,A2
1547621072,1547621087,NG
1547621088,1547621095,A2
-1547621096,1547621119,NG
-1547621120,1547621127,A2
-1547621128,1547621135,NG
+1547621096,1547621135,NG
1547621136,1547621143,A2
1547621144,1547621151,NG
1547621152,1547621167,A2
@@ -52187,9 +53205,77 @@
1547621304,1547621335,NG
1547621336,1547621351,A2
1547621352,1547621375,NG
-1547621376,1547622463,A2
-1547622464,1547622471,NG
-1547622472,1547624447,A2
+1547621376,1547621447,A2
+1547621448,1547621455,NG
+1547621456,1547621463,A2
+1547621464,1547621471,NG
+1547621472,1547621575,A2
+1547621576,1547621583,NG
+1547621584,1547621615,A2
+1547621616,1547621623,NG
+1547621624,1547621687,A2
+1547621688,1547621711,NG
+1547621712,1547622407,A2
+1547622408,1547622415,NG
+1547622416,1547622455,A2
+1547622456,1547622471,NG
+1547622472,1547622511,A2
+1547622512,1547622527,NG
+1547622528,1547622559,A2
+1547622560,1547622575,NG
+1547622576,1547622583,A2
+1547622584,1547622615,NG
+1547622616,1547622623,A2
+1547622624,1547622631,NG
+1547622632,1547622911,A2
+1547622912,1547622935,NG
+1547622936,1547622951,A2
+1547622952,1547622959,NG
+1547622960,1547622967,A2
+1547622968,1547622983,NG
+1547622984,1547622991,A2
+1547622992,1547623015,NG
+1547623016,1547623031,A2
+1547623032,1547623039,NG
+1547623040,1547623047,A2
+1547623048,1547623071,NG
+1547623072,1547623103,A2
+1547623104,1547623159,NG
+1547623160,1547623167,A2
+1547623168,1547623175,NG
+1547623176,1547623183,A2
+1547623184,1547623191,NG
+1547623192,1547623199,A2
+1547623200,1547623207,NG
+1547623208,1547623215,A2
+1547623216,1547623247,NG
+1547623248,1547623255,A2
+1547623256,1547623263,NG
+1547623264,1547623287,A2
+1547623288,1547623295,NG
+1547623296,1547623319,A2
+1547623320,1547623327,NG
+1547623328,1547623335,A2
+1547623336,1547623343,NG
+1547623344,1547623359,A2
+1547623360,1547623367,NG
+1547623368,1547623383,A2
+1547623384,1547623391,NG
+1547623392,1547623399,A2
+1547623400,1547623415,NG
+1547623416,1547623455,A2
+1547623456,1547623463,NG
+1547623464,1547623479,A2
+1547623480,1547623487,NG
+1547623488,1547623495,A2
+1547623496,1547623519,NG
+1547623520,1547623527,A2
+1547623528,1547623559,NG
+1547623560,1547623567,A2
+1547623568,1547623615,NG
+1547623616,1547623727,A2
+1547623728,1547623735,NG
+1547623736,1547624447,A2
1547624448,1547628543,CZ
1547628544,1547632639,BG
1547632640,1547636735,TR
@@ -52277,7 +53363,8 @@
1551556608,1551558655,FR
1551558656,1551560703,EU
1551560704,1551561727,DE
-1551561728,1551564799,EU
+1551561728,1551562751,FR
+1551562752,1551564799,EU
1551564800,1551572991,FR
1551572992,1551576063,NL
1551576064,1551577087,EU
@@ -52517,7 +53604,6 @@
1566401920,1566401983,NO
1566401984,1566402047,AU
1566402048,1566402559,NO
-1566402560,1566404607,IT
1566404608,1566406655,ES
1566406656,1566408703,NL
1566408704,1566410751,GB
@@ -52737,7 +53823,8 @@
1570652160,1570652287,SE
1570652288,1570652291,MY
1570652292,1570652295,GB
-1570652296,1570652543,SE
+1570652296,1570652299,DE
+1570652300,1570652543,SE
1570652544,1570652551,FR
1570652552,1570652891,SE
1570652892,1570652895,DE
@@ -52752,7 +53839,9 @@
1570660360,1570660367,SE
1570660368,1570660383,FR
1570660384,1570660387,RU
-1570660388,1570660543,SE
+1570660388,1570660407,SE
+1570660408,1570660411,DE
+1570660412,1570660543,SE
1570660544,1570660575,FI
1570660576,1570660591,GB
1570660592,1570660595,RU
@@ -52762,7 +53851,8 @@
1570660616,1570660619,RU
1570660620,1570660623,SE
1570660624,1570660639,FR
-1570660640,1570660863,SE
+1570660640,1570660675,DE
+1570660676,1570660863,SE
1570660864,1570661375,NO
1570661376,1570661631,GB
1570661632,1570662143,SE
@@ -52780,7 +53870,9 @@
1570665920,1570665935,GB
1570665936,1570665951,IT
1570665952,1570665967,FR
-1570665968,1570666175,SE
+1570665968,1570666143,SE
+1570666144,1570666147,DE
+1570666148,1570666175,SE
1570666176,1570666191,GB
1570666192,1570666223,FR
1570666224,1570666227,SE
@@ -52789,7 +53881,9 @@
1570666368,1570666383,FR
1570666384,1570666387,SE
1570666388,1570666391,NL
-1570666392,1570666431,SE
+1570666392,1570666395,SE
+1570666396,1570666399,DE
+1570666400,1570666431,SE
1570666432,1570666447,GB
1570666448,1570666463,DE
1570666464,1570666495,SE
@@ -52804,7 +53898,9 @@
1570666752,1570666755,ES
1570666756,1570666759,SE
1570666760,1570666767,GB
-1570666768,1570666943,SE
+1570666768,1570666887,SE
+1570666888,1570666891,DE
+1570666892,1570666943,SE
1570666944,1570666959,FR
1570666960,1570666975,SE
1570666976,1570666991,FR
@@ -52813,7 +53909,9 @@
1570667012,1570667015,SE
1570667016,1570667023,GB
1570667024,1570667039,ES
-1570667040,1570667199,SE
+1570667040,1570667167,SE
+1570667168,1570667171,DE
+1570667172,1570667199,SE
1570667200,1570667215,FR
1570667216,1570667231,SE
1570667232,1570667247,FR
@@ -52825,7 +53923,8 @@
1570667328,1570667335,SE
1570667336,1570667339,GB
1570667340,1570667343,NL
-1570667344,1570667455,SE
+1570667344,1570667347,DE
+1570667348,1570667455,SE
1570667456,1570667471,FR
1570667472,1570667487,SE
1570667488,1570667503,FR
@@ -52837,7 +53936,9 @@
1570667532,1570667535,GB
1570667536,1570667587,SE
1570667588,1570667591,US
-1570667592,1570667711,SE
+1570667592,1570667599,SE
+1570667600,1570667603,DE
+1570667604,1570667711,SE
1570667712,1570667727,FR
1570667728,1570667743,NL
1570667744,1570667775,SE
@@ -52849,7 +53950,9 @@
1570667904,1570667907,SE
1570667908,1570667911,RU
1570667912,1570667915,US
-1570667916,1570667967,SE
+1570667916,1570667919,SE
+1570667920,1570667923,DE
+1570667924,1570667967,SE
1570667968,1570667983,FR
1570667984,1570668031,SE
1570668032,1570668035,NL
@@ -52878,8 +53981,8 @@
1571429376,1571432447,UA
1571432448,1571434495,CZ
1571434496,1571435519,UA
-1571435520,1571435775,NL
-1571435776,1571438591,CZ
+1571435520,1571436031,NL
+1571436032,1571438591,CZ
1571438592,1571441663,UA
1571441664,1571442175,KZ
1571442176,1571442687,NL
@@ -53101,7 +54204,6 @@
1572612096,1572614143,RU
1572614144,1572616191,ES
1572616192,1572618239,CH
-1572618240,1572620287,RS
1572620288,1572620415,CH
1572620416,1572620431,CZ
1572620432,1572620559,CH
@@ -53312,7 +54414,8 @@
1578590536,1578590543,FR
1578590544,1578590559,GB
1578590560,1578590575,ES
-1578590576,1578590603,FR
+1578590576,1578590599,FR
+1578590600,1578590603,LT
1578590604,1578590607,PL
1578590608,1578590615,FR
1578590616,1578590619,DE
@@ -53325,9 +54428,11 @@
1578590664,1578590667,FR
1578590668,1578590671,NL
1578590672,1578590687,PL
-1578590688,1578590699,FR
-1578590700,1578590731,PL
-1578590732,1578590799,FR
+1578590688,1578590691,GB
+1578590692,1578590695,DE
+1578590696,1578590699,FR
+1578590700,1578590735,PL
+1578590736,1578590799,FR
1578590800,1578590831,GB
1578590832,1578590839,FR
1578590840,1578590847,PL
@@ -53362,7 +54467,8 @@
1578591296,1578591327,FR
1578591328,1578591343,PL
1578591344,1578591391,FR
-1578591392,1578591407,CH
+1578591392,1578591395,IT
+1578591396,1578591407,PL
1578591408,1578591411,ES
1578591412,1578591415,FR
1578591416,1578591423,ES
@@ -53395,7 +54501,7 @@
1578591808,1578591887,FR
1578591888,1578591891,DE
1578591892,1578591899,FR
-1578591900,1578591903,GB
+1578591900,1578591903,NL
1578591904,1578591919,PL
1578591920,1578591939,ES
1578591940,1578591951,FR
@@ -53420,8 +54526,7 @@
1578592208,1578592223,FR
1578592224,1578592239,ES
1578592240,1578592271,FR
-1578592272,1578592275,PL
-1578592276,1578592279,FI
+1578592272,1578592279,PL
1578592280,1578592283,BE
1578592284,1578592287,NL
1578592288,1578592295,PL
@@ -53442,7 +54547,8 @@
1578592516,1578592519,PL
1578592520,1578592531,FR
1578592532,1578592535,GB
-1578592536,1578592543,NL
+1578592536,1578592539,PL
+1578592540,1578592543,ES
1578592544,1578592559,FR
1578592560,1578592575,NL
1578592576,1578592591,GB
@@ -53452,8 +54558,14 @@
1578592720,1578592735,CH
1578592736,1578592743,PL
1578592744,1578592747,PT
-1578592748,1578592783,DE
-1578592784,1578592831,FR
+1578592748,1578592751,DE
+1578592752,1578592767,IE
+1578592768,1578592783,DE
+1578592784,1578592799,FR
+1578592800,1578592807,GB
+1578592808,1578592811,FR
+1578592812,1578592815,PL
+1578592816,1578592831,FR
1578592832,1578592847,PL
1578592848,1578592851,BE
1578592852,1578592855,DE
@@ -53479,7 +54591,10 @@
1578593416,1578593423,PL
1578593424,1578593439,FR
1578593440,1578593455,PL
-1578593456,1578593487,FR
+1578593456,1578593471,FR
+1578593472,1578593479,GB
+1578593480,1578593483,PL
+1578593484,1578593487,FR
1578593488,1578593495,ES
1578593496,1578593503,FR
1578593504,1578593519,PL
@@ -53532,7 +54647,10 @@
1578594088,1578594095,CZ
1578594096,1578594111,FR
1578594112,1578594127,PL
-1578594128,1578594159,FR
+1578594128,1578594143,FR
+1578594144,1578594147,PL
+1578594148,1578594151,ES
+1578594152,1578594159,IT
1578594160,1578594163,PT
1578594164,1578594167,ES
1578594168,1578594171,DE
@@ -53587,8 +54705,8 @@
1578594784,1578594799,FR
1578594800,1578594815,DE
1578594816,1578594847,FR
-1578594848,1578594863,IT
-1578594864,1578594871,GB
+1578594848,1578594867,IT
+1578594868,1578594871,BE
1578594872,1578595039,FR
1578595040,1578595055,GB
1578595056,1578595103,FR
@@ -53613,9 +54731,7 @@
1578595328,1578595343,IT
1578595344,1578595363,FR
1578595364,1578595367,DE
-1578595368,1578595371,FR
-1578595372,1578595375,BE
-1578595376,1578595379,FR
+1578595368,1578595379,FR
1578595380,1578595383,CH
1578595384,1578595387,ES
1578595388,1578595407,PL
@@ -53688,7 +54804,8 @@
1578610768,1578610771,CH
1578610772,1578610775,GB
1578610776,1578610779,DE
-1578610780,1578610799,FR
+1578610780,1578610783,FR
+1578610784,1578610799,DE
1578610800,1578610803,PL
1578610804,1578610807,GB
1578610808,1578610943,FR
@@ -53734,7 +54851,7 @@
1578611776,1578611783,DE
1578611784,1578611807,FR
1578611808,1578611839,CH
-1578611840,1578611855,ES
+1578611840,1578611855,BE
1578611856,1578611919,FR
1578611920,1578611935,BE
1578611936,1578611943,PL
@@ -53753,7 +54870,7 @@
1578612120,1578612123,IE
1578612124,1578612127,DE
1578612128,1578612135,ES
-1578612136,1578612139,NL
+1578612136,1578612139,IE
1578612140,1578612143,ES
1578612144,1578612223,PL
1578612224,1578612239,IT
@@ -53776,7 +54893,7 @@
1578612904,1578612907,DE
1578612908,1578612911,FR
1578612912,1578612959,ES
-1578612960,1578612975,FR
+1578612960,1578612975,DE
1578612976,1578612983,IT
1578612984,1578612991,FR
1578612992,1578613247,DE
@@ -53815,7 +54932,14 @@
1578614196,1578614207,GB
1578614208,1578614271,PL
1578614272,1578614527,ES
-1578614528,1578631167,FR
+1578614528,1578614543,GB
+1578614544,1578614559,PL
+1578614560,1578614575,FR
+1578614576,1578614583,DE
+1578614584,1578614591,GB
+1578614592,1578614623,CZ
+1578614624,1578614655,BE
+1578614656,1578631167,FR
1578631168,1578663935,RO
1578663936,1578762239,RU
1578762240,1578795007,BG
@@ -53881,7 +55005,9 @@
1581826048,1581842431,GB
1581842432,1581858815,BG
1581858816,1581875199,IT
-1581875200,1581891583,TR
+1581875200,1581881343,TR
+1581881344,1581881599,GB
+1581881600,1581891583,TR
1581891584,1581907967,RU
1581907968,1581924351,IT
1581924352,1581940735,UA
@@ -53958,7 +55084,9 @@
1583742976,1583747071,TR
1583747072,1583751167,RU
1583751168,1583755263,NO
-1583755264,1583759359,NL
+1583755264,1583755414,NL
+1583755415,1583755424,RU
+1583755425,1583759359,NL
1583759360,1583763455,TR
1583763456,1583767551,RU
1583767552,1583771647,AT
@@ -53993,7 +55121,9 @@
1583815216,1583815343,NL
1583815344,1583815351,US
1583815352,1583816703,NL
-1583816704,1583820799,TR
+1583816704,1583819007,TR
+1583819008,1583819136,GB
+1583819137,1583820799,TR
1583820800,1583824895,LV
1583824896,1583828991,SI
1583828992,1583833087,RU
@@ -54049,7 +55179,6 @@
1585231360,1585231615,NL
1585231616,1585231871,RU
1585231872,1585233919,CZ
-1585233920,1585235967,LB
1585235968,1585238015,RU
1585238016,1585240063,DE
1585240064,1585241087,FR
@@ -54292,6 +55421,15 @@
1586495488,1587019775,DK
1587019776,1587085311,PL
1587085312,1587150847,UA
+1587150848,1587154943,RU
+1587154944,1587159039,PL
+1587159040,1587163135,UA
+1587163136,1587165183,DE
+1587165184,1587167231,PL
+1587167232,1587175423,RU
+1587175424,1587177471,PL
+1587177472,1587179519,RS
+1587179520,1587183615,UA
1587183616,1587199999,RU
1587200000,1587216383,UA
1587216384,1587347455,BG
@@ -54434,20 +55572,26 @@
1592061952,1592066047,RU
1592066048,1592067583,US
1592067584,1592067711,NO
-1592067712,1592069119,CY
+1592067712,1592067839,CY
+1592067840,1592068095,NL
+1592068096,1592069119,CY
1592069120,1592069135,RU
1592069136,1592069247,CY
1592069248,1592069375,RU
1592069376,1592069407,US
1592069408,1592069631,CY
-1592069632,1592069759,NL
-1592069760,1592069855,CY
-1592069856,1592069887,NL
+1592069632,1592069711,NL
+1592069712,1592069727,CY
+1592069728,1592069759,NL
+1592069760,1592069839,CY
+1592069840,1592069887,NL
1592069888,1592074239,RU
1592074240,1592078335,SK
1592078336,1592082431,NL
1592082432,1592086527,GB
-1592086528,1592087295,CZ
+1592086528,1592087079,CZ
+1592087080,1592087087,PL
+1592087088,1592087295,CZ
1592087296,1592088191,PL
1592088192,1592090623,CZ
1592090624,1592094719,RU
@@ -54510,7 +55654,6 @@
1592326144,1592328191,UA
1592328192,1592393727,RU
1592393728,1592459263,SE
-1592459264,1592524799,GE
1592524800,1592540415,GB
1592540416,1592540423,A2
1592540424,1592557567,GB
@@ -54878,8 +56021,16 @@
1602449408,1602451455,LV
1602451456,1602453503,DE
1602453504,1602455551,SK
-1602455552,1602456015,FR
-1602456016,1602456031,ES
+1602455552,1602455690,FR
+1602455691,1602455691,BE
+1602455692,1602456015,FR
+1602456016,1602456025,ES
+1602456026,1602456026,DE
+1602456027,1602456027,NL
+1602456028,1602456028,IT
+1602456029,1602456029,ES
+1602456030,1602456030,PT
+1602456031,1602456031,ES
1602456032,1602456175,FR
1602456176,1602456183,ES
1602456184,1602457599,FR
@@ -54960,7 +56111,8 @@
1603161008,1603161023,GB
1603161024,1603161103,DE
1603161104,1603161119,GB
-1603161120,1603161567,DE
+1603161120,1603161135,AT
+1603161136,1603161567,DE
1603161568,1603161599,FR
1603161600,1603162111,DE
1603162112,1603166207,TJ
@@ -55026,8 +56178,8 @@
1603225632,1603225639,US
1603225640,1603225647,CN
1603225648,1603225855,FR
-1603225856,1603226111,GB
-1603226112,1603227647,FR
+1603225856,1603226623,GB
+1603226624,1603227647,FR
1603227648,1603231743,AT
1603231744,1603235839,IT
1603235840,1603239935,RU
@@ -55064,7 +56216,9 @@
1603982784,1603982847,AN
1603982848,1603984895,GB
1603984896,1603985151,PT
-1603985152,1603990271,GB
+1603985152,1603985279,GB
+1603985280,1603985407,BR
+1603985408,1603990271,GB
1603990272,1603990527,SA
1603990528,1603993599,GB
1603993600,1604009983,ME
@@ -55170,8 +56324,8 @@
1605125280,1605125335,GB
1605125336,1605125343,US
1605125344,1605125375,GB
-1605125376,1605125919,US
-1605125920,1605126143,GB
+1605125376,1605125903,US
+1605125904,1605126143,GB
1605126144,1605127679,US
1605127680,1605127935,GB
1605127936,1605128703,US
@@ -55203,7 +56357,6 @@
1605230592,1605238783,TR
1605238784,1605246975,IT
1605246976,1605255167,PL
-1605255168,1605263359,HU
1605263360,1605271551,RU
1605271552,1605279743,DE
1605279744,1605287935,FR
@@ -55290,9 +56443,7 @@
1607966720,1607967743,RU
1607967744,1607968767,UA
1607968768,1607969791,SE
-1607969792,1607970815,RU
1607972864,1607974911,NL
-1607974912,1607975935,LV
1607976960,1607977983,KZ
1607979008,1607980031,RU
1607980032,1607981055,DE
@@ -55419,8 +56570,13 @@
1614741504,1614757887,CA
1614757888,1614774271,US
1614774272,1614786559,CA
-1614786560,1618886655,US
-1618968576,1618984959,US
+1614786560,1618837503,US
+1618837504,1618841599,CA
+1618841600,1618849791,US
+1618849792,1618862079,CA
+1618862080,1618866175,US
+1618866176,1618870271,CA
+1618870272,1618984959,US
1618984960,1619001343,CA
1619001344,1632305151,US
1632305152,1632321535,CA
@@ -56294,7 +57450,10 @@
1710949376,1710950399,NP
1710950400,1711210495,CN
1711210496,1711276031,ID
-1728053248,1728120831,AU
+1728053248,1728120063,AU
+1728120064,1728120319,SG
+1728120320,1728120575,IN
+1728120576,1728120831,AU
1728120832,1728121855,CN
1728121856,1728123903,HK
1728123904,1728125951,CN
@@ -56389,6 +57548,89 @@
1728291840,1728292863,SG
1728292864,1728293887,PG
1728293888,1728294911,MY
+1728294912,1728295935,TH
+1728295936,1728299007,JP
+1728299008,1728300031,TW
+1728300032,1728301055,AU
+1728301056,1728302079,SG
+1728302080,1728303103,IN
+1728303104,1728305151,ID
+1728305152,1728306175,AU
+1728306176,1728307199,ID
+1728307200,1728308223,BD
+1728308224,1728309247,IN
+1728309248,1728310271,NZ
+1728310272,1728311295,AU
+1728311296,1728312319,GU
+1728312320,1728315391,VN
+1728315392,1728316415,ID
+1728316416,1728317439,MY
+1728317440,1728318463,JP
+1728318464,1728319487,SG
+1728319488,1728320511,AU
+1728320512,1728321535,PH
+1728321536,1728322559,JP
+1728322560,1728323583,MY
+1728323584,1728324607,JP
+1728324608,1728325631,SG
+1728325632,1728326655,JP
+1728326656,1728327679,MY
+1728327680,1728328703,KR
+1728328704,1728329727,ID
+1728329728,1728330751,CN
+1728330752,1728331775,AU
+1728708608,1728709631,CN
+1728709632,1728710655,TW
+1728710656,1728710911,AU
+1728710912,1728711167,IN
+1728711424,1728711679,AU
+1728711680,1728712703,HK
+1728712704,1728713727,CN
+1728713728,1728714751,MN
+1728714752,1728715775,IN
+1728715776,1728716799,NP
+1728716800,1728717823,AU
+1728717824,1728718847,JP
+1728718848,1728719871,MY
+1728719872,1728720895,NZ
+1728720896,1728721919,AU
+1728721920,1728722943,BD
+1728722944,1728723199,ID
+1728723200,1728723455,AU
+1728723456,1728724991,ID
+1729544192,1729545215,IN
+1729545216,1729546239,AU
+1729546240,1729547263,HK
+1729547264,1729548287,IN
+1729548288,1729549311,AU
+1729549312,1729550335,JP
+1729550336,1729551359,MY
+1729551360,1729552383,KR
+1729552384,1729553407,AU
+1729553408,1729554431,CN
+1729554432,1729554943,ID
+1729555456,1729556479,IN
+1729556480,1729557503,ID
+1729557504,1729558527,HK
+1729558528,1729559551,ID
+1729559552,1729560575,CN
+1729953792,1729954815,MY
+1729954816,1729955839,ID
+1729961984,1729964031,IN
+1729964032,1729965055,AU
+1729965056,1729966079,IN
+1729966080,1729967103,JP
+1729967104,1729968127,AU
+1729968128,1729969151,MY
+1729969152,1729970175,LK
+1744199680,1744201727,AU
+1744201728,1744201983,VN
+1744202240,1744202495,IN
+1744202496,1744202751,ID
+1744202752,1744203775,PK
+1744203776,1744204799,MY
+1744204800,1744205823,ID
+1744205824,1744207871,CN
1778384896,1778385151,CN
1778385152,1778385407,AU
1778385408,1778393087,CN
@@ -56424,7 +57666,9 @@
1815912448,1815920639,CA
1815920640,1815928831,US
1815928832,1815937023,BS
-1815937024,1816068095,US
+1815937024,1816024319,US
+1816024320,1816024575,CA
+1816024576,1816068095,US
1816068096,1816133631,CA
1816133632,1828716543,US
1828716544,1830813695,FR
@@ -56480,7 +57724,7 @@
1833248768,1833250815,MK
1833250816,1833254911,GB
1833254912,1833256959,DE
-1833256960,1833261055,GB
+1833259008,1833261055,GB
1833261056,1833263103,PL
1833263104,1833265151,DE
1833265152,1833267199,GB
@@ -56488,7 +57732,6 @@
1833269248,1833271295,FI
1833271296,1833273343,IT
1833273344,1833275391,EU
-1833275392,1833277439,GB
1833277440,1833279487,CH
1833279488,1833281535,AL
1833281536,1833283583,AT
@@ -56609,7 +57852,8 @@
1833468592,1833471999,CH
1833472000,1833474047,EU
1833474048,1833474559,UA
-1833474560,1833476095,EU
+1833474560,1833474815,RU
+1833474816,1833476095,EU
1833476096,1833477375,NL
1833477376,1833477503,GB
1833477504,1833477631,DE
@@ -56669,17 +57913,15 @@
1833648128,1833652223,LB
1833652224,1833659903,DE
1833659904,1833659919,NA
-1833659920,1833660159,DE
-1833660160,1833660175,CH
-1833660176,1833660179,DE
-1833660180,1833660223,CH
-1833660224,1833660351,DE
+1833659920,1833660351,DE
1833660352,1833660415,US
1833660416,1833664511,IT
1833664512,1833668607,RU
1833668608,1833672703,CZ
1833672704,1833676799,GB
-1833676800,1833680895,DE
+1833676800,1833677567,DE
+1833677568,1833677599,CH
+1833677600,1833680895,DE
1833680896,1833684991,UA
1833684992,1833689087,DE
1833689088,1833693183,FI
@@ -56786,12 +58028,10 @@
1835909120,1835913215,RS
1835913216,1835917311,RU
1835917312,1835920127,GB
-1835920128,1835920143,PT
-1835920144,1835920151,GB
-1835920152,1835920159,PT
-1835920160,1835920263,GB
-1835920264,1835920279,PT
-1835920280,1835925503,GB
+1835920128,1835920159,PT
+1835920160,1835920255,GB
+1835920256,1835920303,PT
+1835920304,1835925503,GB
1835925504,1835933695,LV
1835933696,1835941887,RU
1835941888,1835950079,UA
@@ -56874,7 +58114,9 @@
1839796608,1839796671,US
1839796672,1839797759,GB
1839797760,1839798015,GR
-1839798016,1839798527,GB
+1839798016,1839798271,GB
+1839798272,1839798399,DE
+1839798400,1839798527,GB
1839798528,1839798559,US
1839798560,1839800447,GB
1839800448,1839800479,SG
@@ -56887,13 +58129,13 @@
1839801344,1839801471,CN
1839801472,1839801551,GB
1839801552,1839801567,US
-1839801568,1839801599,GB
-1839801600,1839801855,US
-1839801856,1839802111,GB
+1839801568,1839802111,GB
1839802112,1839802239,RO
1839802240,1839806463,GB
1839806464,1839811071,US
-1839811072,1839816703,GB
+1839811072,1839811455,GB
+1839811456,1839811583,IE
+1839811584,1839816703,GB
1839816704,1839824895,NO
1839824896,1839890431,RU
1839890432,1839923199,GB
@@ -57199,7 +58441,10 @@
1844127744,1844129791,DE
1844129792,1844131583,NL
1844131584,1844131711,SC
-1844131712,1844131839,NL
+1844131712,1844131743,NL
+1844131744,1844131775,RU
+1844131776,1844131807,AE
+1844131808,1844131839,US
1844131840,1844133887,DE
1844133888,1844135935,LT
1844135936,1844137983,NL
@@ -57227,7 +58472,8 @@
1844169656,1844169663,SE
1844169664,1844169679,US
1844169680,1844169687,ZM
-1844169688,1844169727,SE
+1844169688,1844169695,IQ
+1844169696,1844169727,SE
1844169728,1844169767,DE
1844169768,1844169951,US
1844169952,1844169983,DE
@@ -57235,9 +58481,10 @@
1844169988,1844169991,DE
1844169992,1844169995,AF
1844169996,1844169999,TM
-1844170000,1844170007,DE
-1844170008,1844170015,AF
-1844170016,1844170751,DE
+1844170000,1844170015,AF
+1844170016,1844170239,DE
+1844170240,1844170247,AF
+1844170248,1844170751,DE
1844170752,1844174847,RU
1844174848,1844178943,DE
1844178944,1844180991,EE
@@ -57249,7 +58496,23 @@
1844181953,1844181958,GB
1844181959,1844181984,TR
1844181985,1844181990,GB
-1844181991,1844183039,TR
+1844181991,1844182272,TR
+1844182273,1844182302,US
+1844182303,1844182309,TR
+1844182310,1844182329,US
+1844182330,1844182343,TR
+1844182344,1844182403,US
+1844182404,1844182416,TR
+1844182417,1844182417,US
+1844182418,1844182424,TR
+1844182425,1844182426,US
+1844182427,1844182432,TR
+1844182433,1844182480,US
+1844182481,1844182485,TR
+1844182486,1844182489,US
+1844182490,1844182501,TR
+1844182502,1844182511,US
+1844182512,1844183039,TR
1844183040,1844191231,IT
1844191232,1844195327,AL
1844195328,1844203519,RU
@@ -57257,7 +58520,9 @@
1844207616,1844211711,RU
1844211712,1844215807,SK
1844215808,1844219903,BE
-1844219904,1844220159,A2
+1844219904,1844219919,A2
+1844219920,1844219959,LB
+1844219960,1844220159,A2
1844220160,1844220191,IQ
1844220192,1844220415,DE
1844220416,1844220431,A2
@@ -57290,7 +58555,8 @@
1844310016,1844318207,FR
1844318208,1844322303,IT
1844322304,1844326399,CZ
-1844326400,1844330495,DK
+1844326400,1844329983,DK
+1844329984,1844330495,LU
1844330496,1844334591,GB
1844334592,1844342783,RU
1844342784,1844346879,IT
@@ -57715,7 +58981,6 @@
1888266240,1888268287,JP
1888268288,1888270335,AU
1888270336,1888271359,SG
-1888271360,1888272383,TH
1888272384,1888288767,KR
1888288768,1888354303,AU
1888354304,1888485375,TH
@@ -57850,7 +59115,9 @@
1908539392,1908670463,CN
1908670464,1908735999,TW
1908736000,1908740095,AU
-1908740096,1908748287,JP
+1908740096,1908744191,JP
+1908744192,1908746239,SG
+1908746240,1908748287,JP
1908748288,1908750335,PK
1908750336,1908752383,JP
1908752384,1908753407,NZ
@@ -58319,7 +59586,7 @@
1958830080,1958838271,JP
1958838272,1958842367,IN
1958842368,1958844415,NZ
-1958844416,1958846463,HK
+1958845440,1958846463,HK
1958846464,1958848511,IN
1958848512,1958850559,BD
1958850560,1958853631,AU
@@ -60879,7 +62146,9 @@
2332098560,2332622847,DE
2332622848,2332688383,CN
2332688384,2332753919,NL
-2332753920,2333868031,DE
+2332753920,2333736959,DE
+2333736960,2333802495,EU
+2333802496,2333868031,DE
2333933568,2334064639,DE
2334064640,2334916607,US
2334916608,2334982143,AU
@@ -61535,7 +62804,7 @@
2453864448,2453929983,CH
2453929984,2454061055,US
2454061056,2454126591,GB
-2454126592,2454192127,US
+2454159360,2454192127,US
2454192128,2454257663,NO
2454257664,2454388735,US
2454388736,2454454271,SE
@@ -61962,7 +63231,7 @@
2532114432,2532179967,GB
2532179968,2532376575,US
2532376576,2532442111,ES
-2532442112,2532507647,FR
+2532442112,2532507647,EU
2532507648,2532573183,US
2532573184,2532638719,ES
2532638720,2533031935,US
@@ -63672,20 +64941,46 @@
2899443712,2899574783,FR
2899574784,2899902463,GB
2902458368,2902462463,A1
-2902462464,2902470936,US
+2902462464,2902470775,US
+2902470776,2902470777,BD
+2902470778,2902470936,US
2902470937,2902470938,LK
-2902470939,2902471468,US
+2902470939,2902470986,US
+2902470987,2902470989,BD
+2902470990,2902471468,US
2902471469,2902471470,AU
2902471471,2902471895,US
2902471896,2902471897,AU
2902471898,2902471960,US
2902471961,2902471962,AU
-2902471963,2902472037,US
+2902471963,2902472018,US
+2902472019,2902472021,AL
+2902472022,2902472037,US
2902472038,2902472039,AU
-2902472040,2902472834,US
+2902472040,2902472725,US
+2902472726,2902472728,BD
+2902472729,2902472788,US
+2902472789,2902472790,LK
+2902472791,2902472813,US
+2902472814,2902472814,LK
+2902472815,2902472834,US
2902472835,2902472836,BD
-2902472837,2902492927,US
-2902492928,2902493183,IN
+2902472837,2902473028,US
+2902473029,2902473031,IN
+2902473032,2902473107,US
+2902473108,2902473109,BD
+2902473110,2902473649,US
+2902473650,2902473650,BD
+2902473651,2902473652,US
+2902473653,2902473653,BD
+2902473654,2902474023,US
+2902474024,2902474032,RU
+2902474033,2902474062,US
+2902474063,2902474073,RU
+2902474074,2902475263,US
+2902475264,2902475327,CY
+2902475328,2902492671,US
+2902492672,2902493183,IN
2902493184,2902507519,US
2902507520,2902515711,CA
2902515712,2904555519,US
@@ -63745,7 +65040,7 @@
2915765288,2915765343,US
2915765344,2915765351,NZ
2915765352,2915765367,US
-2915765368,2915765375,PE
+2915765368,2915765375,ZA
2915765376,2915765431,US
2915765432,2915765439,MX
2915765440,2915765471,US
@@ -64060,37 +65355,38 @@
2916434560,2916434591,CA
2916434592,2916434623,US
2916434624,2916434655,CA
-2916434656,2916436543,US
+2916434656,2916436487,US
+2916436488,2916436495,CA
+2916436496,2916436543,US
2916436544,2916436607,CA
-2916436608,2916436735,US
-2916436736,2916436743,CA
-2916436744,2916437039,US
+2916436608,2916437039,US
2916437040,2916437047,DE
2916437048,2916437055,CN
2916437056,2916437063,GB
-2916437064,2916437503,US
+2916437064,2916437199,US
+2916437200,2916437207,GB
+2916437208,2916437215,TH
+2916437216,2916437231,US
+2916437232,2916437239,SG
+2916437240,2916437503,US
2916437504,2916437567,CA
2916437568,2916440143,US
2916440144,2916440159,CA
2916440160,2916440175,US
2916440176,2916440191,CA
-2916440192,2916440223,US
-2916440224,2916440239,CA
-2916440240,2916440287,US
+2916440192,2916440287,US
2916440288,2916440295,CA
2916440296,2916441119,US
2916441120,2916441151,CA
-2916441152,2916441191,US
-2916441192,2916441199,CA
-2916441200,2916441343,US
+2916441152,2916441199,US
+2916441200,2916441207,MY
+2916441208,2916441343,US
2916441344,2916442111,CA
2916442112,2916442623,US
2916442624,2916442879,CA
2916442880,2916443614,US
2916443615,2916443647,CA
-2916443648,2916444351,US
-2916444352,2916444359,CA
-2916444360,2916444927,US
+2916443648,2916444927,US
2916444928,2916445951,CA
2916445952,2916449279,US
2916449280,2916450303,CA
@@ -64110,9 +65406,7 @@
2917168000,2917168031,UA
2917168032,2917168095,US
2917168096,2917168127,NZ
-2917168128,2917168159,US
-2917168160,2917168191,NL
-2917168192,2917168223,US
+2917168128,2917168223,US
2917168224,2917168255,BR
2917168256,2917168319,US
2917168320,2917168351,AR
@@ -64124,15 +65418,12 @@
2917168608,2917168639,BR
2917168640,2917169663,US
2917169664,2917169695,DE
-2917169696,2917169727,NL
-2917169728,2917170015,US
+2917169696,2917170015,US
2917170016,2917170047,UA
2917170048,2917170079,BR
-2917170080,2917170111,NL
+2917170080,2917170111,US
2917170112,2917170143,RU
-2917170144,2917170175,US
-2917170176,2917170207,NL
-2917170208,2917170239,US
+2917170144,2917170239,US
2917170240,2917170271,RU
2917170272,2917170303,BR
2917170304,2917193025,US
@@ -64221,7 +65512,9 @@
2918199680,2918199743,CA
2918199744,2918200287,US
2918200288,2918200303,CA
-2918200304,2918232063,US
+2918200304,2918201551,US
+2918201552,2918201567,CA
+2918201568,2918232063,US
2918232064,2918236159,CA
2918236160,2918260735,US
2918260736,2918264831,CA
@@ -64257,8 +65550,8 @@
2918481920,2918514943,US
2918514944,2918515079,CA
2918515080,2918532111,US
-2918532112,2918532127,CN
-2918532128,2918532143,US
+2918532112,2918532119,CN
+2918532120,2918532143,US
2918532144,2918532151,PK
2918532152,2918533119,US
2918533120,2918533127,CN
@@ -64275,29 +65568,24 @@
2918534704,2918534735,CN
2918534736,2918534751,US
2918534752,2918534767,CN
-2918534768,2918534783,US
-2918534784,2918534807,CN
+2918534768,2918534799,US
+2918534800,2918534807,CN
2918534808,2918534815,US
-2918534816,2918534887,CN
-2918534888,2918534911,US
+2918534816,2918534879,CN
+2918534880,2918534911,US
2918534912,2918534943,KR
-2918534944,2918534983,CN
+2918534944,2918534975,CN
+2918534976,2918534983,US
2918534984,2918534991,ID
2918534992,2918535199,US
2918535200,2918535231,CN
2918535232,2918535423,US
2918535424,2918535679,CN
2918535680,2918535807,US
-2918535808,2918536191,CN
-2918536192,2918536703,US
-2918536704,2918536711,CN
-2918536712,2918536767,US
-2918536768,2918536791,CN
-2918536792,2918536799,US
-2918536800,2918536815,CN
-2918536816,2918536823,US
-2918536824,2918536959,CN
-2918536960,2918537215,US
+2918535808,2918535967,CN
+2918535968,2918535983,US
+2918535984,2918536191,CN
+2918536192,2918537215,US
2918537216,2918537615,CN
2918537616,2918537623,US
2918537624,2918537727,CN
@@ -64572,8 +65860,7 @@
2919170552,2919170559,FR
2919170560,2919170575,US
2919170576,2919170583,FR
-2919170584,2919170591,US
-2919170592,2919170599,CN
+2919170584,2919170599,US
2919170600,2919170607,JP
2919170608,2919170615,US
2919170616,2919170623,CN
@@ -64618,11 +65905,24 @@
2919171144,2919171151,TR
2919171152,2919171159,US
2919171160,2919171167,AU
-2919171168,2919174143,US
+2919171168,2919171311,US
+2919171312,2919171319,IL
+2919171320,2919171327,TW
+2919171328,2919171343,US
+2919171344,2919171351,BR
+2919171352,2919171399,US
+2919171400,2919171407,IT
+2919171408,2919171455,US
+2919171456,2919171463,BR
+2919171464,2919171479,US
+2919171480,2919171487,BR
+2919171488,2919174143,US
2919174144,2919178239,CA
2919178240,2919186431,US
2919186432,2919190527,CA
-2919190528,2919202815,US
+2919190528,2919202079,US
+2919202080,2919202111,BE
+2919202112,2919202815,US
2919206912,2919211007,CA
2919219200,2919235583,US
2919235584,2919759871,CA
@@ -64696,7 +65996,9 @@
2928175056,2928175063,MX
2928175064,2928175143,US
2928175144,2928175151,PH
-2928175152,2928175271,US
+2928175152,2928175207,US
+2928175208,2928175215,CA
+2928175216,2928175271,US
2928175272,2928175279,NZ
2928175280,2928175303,US
2928175304,2928175311,CN
@@ -65667,7 +66969,94 @@
2948135936,2948136959,IN
2948136960,2948595711,CN
2948595712,2952790015,KR
-2969567232,2973761535,BR
+2952790016,2953314303,DE
+2953314304,2953379839,UA
+2953379840,2953445375,DE
+2953445376,2953453567,IT
+2953453568,2953455615,IS
+2953455616,2953457663,SK
+2953457664,2953459711,DE
+2953459712,2953461759,IT
+2953461760,2953465855,ES
+2953465856,2953467903,EU
+2953467904,2953469951,BE
+2953469952,2953478143,CH
+2953478144,2953510911,SE
+2953510912,2953576447,NO
+2953576448,2953592831,BG
+2953592832,2953596927,IR
+2953596928,2953598975,ES
+2953598976,2953601023,IT
+2953601024,2953603071,RU
+2953603072,2953609215,GB
+2953609216,2953707519,IL
+2953707520,2953838591,RU
+2953838592,2954100735,SA
+2954100736,2954362879,DK
+2954362880,2954625023,GB
+2954625024,2954641407,DE
+2954641408,2954643455,RU
+2954643456,2954645503,IQ
+2954645504,2954647551,AZ
+2954647552,2954657791,ES
+2954657792,2954756095,JO
+2954756096,2954821631,TR
+2954821632,2954887167,FR
+2954887168,2954891263,UA
+2954891264,2954895359,IT
+2954895360,2954897407,RU
+2954897408,2954899455,DE
+2954899456,2954901503,ES
+2954901504,2954903551,IT
+2954903552,2954919935,IE
+2954919936,2954928127,RU
+2954928128,2954932223,PL
+2954932224,2954936319,RU
+2954936320,2954938367,AM
+2954938368,2954940415,HU
+2954940416,2954944511,DE
+2954944512,2954946559,GB
+2954946560,2954948607,DE
+2954948608,2954950655,RU
+2954950656,2954952703,ES
+2954952704,2955018239,TR
+2955018240,2955083775,IE
+2955083776,2955149311,GB
+2955149312,2955411455,UA
+2955411456,2955673599,TR
+2955673600,2955804671,SA
+2955804672,2955837439,EE
+2955837440,2955845631,IR
+2955845632,2955853823,GB
+2955853824,2955870207,CH
+2955870208,2955935743,UA
+2955935744,2956230655,RU
+2956230656,2956238847,SI
+2956238848,2956242943,ES
+2956242944,2956244991,SE
+2956244992,2956247039,FR
+2956247040,2956249087,DE
+2956249088,2956251135,RU
+2956251136,2956253183,GB
+2956253184,2956255231,IE
+2956255232,2956259327,FR
+2956259328,2956261375,DE
+2956261376,2956263423,ES
+2956263424,2956296191,TR
+2956296192,2956328959,RU
+2956328960,2956460031,TR
+2956460032,2956468223,RU
+2956468224,2956470271,LV
+2956470272,2956472319,NL
+2956472320,2956474367,RU
+2956474368,2956476415,GB
+2956476416,2956492799,ES
+2956492800,2956496895,CH
+2956496896,2956500991,IR
+2956500992,2956509183,RU
+2956509184,2956517375,GB
+2956517376,2956521471,NL
+2969567232,2977955839,BR
2986344448,2987393023,DE
2987393024,2987397119,IM
2987397120,2987401215,LV
@@ -65810,7 +67199,6 @@
2987755520,2987757567,PL
2987757568,2987759615,DE
2987759616,2987761663,PL
-2987761664,2987763711,DK
2987763712,2987765759,GR
2987765760,2987767807,FR
2987767808,2987769855,CZ
@@ -65902,7 +67290,7 @@
2988441696,2988441791,FR
2988441792,2988441807,PL
2988441808,2988441815,FR
-2988441816,2988441819,GB
+2988441816,2988441819,FI
2988441820,2988441839,FR
2988441840,2988441843,PL
2988441844,2988441847,BE
@@ -65924,7 +67312,8 @@
2988441980,2988441983,IT
2988441984,2988441991,FR
2988441992,2988441995,ES
-2988441996,2988442003,FR
+2988441996,2988441999,PT
+2988442000,2988442003,FR
2988442004,2988442007,ES
2988442008,2988442047,FR
2988442048,2988442063,GB
@@ -65937,8 +67326,8 @@
2988442432,2988442439,CZ
2988442440,2988442447,ES
2988442448,2988442463,GB
-2988442464,2988442639,FR
-2988442640,2988442647,PL
+2988442464,2988442623,FR
+2988442624,2988442647,PL
2988442648,2988442651,DE
2988442652,2988442655,GB
2988442656,2988442671,PL
@@ -65990,7 +67379,7 @@
2988443928,2988444167,FR
2988444168,2988444171,CZ
2988444172,2988444199,FR
-2988444200,2988444203,DE
+2988444200,2988444203,FI
2988444204,2988444207,NL
2988444208,2988444415,FR
2988444416,2988444679,ES
@@ -66058,7 +67447,8 @@
2988448512,2988448515,GB
2988448516,2988448519,FR
2988448520,2988448543,PL
-2988448544,2988448551,FR
+2988448544,2988448547,GB
+2988448548,2988448551,FR
2988448552,2988448559,PL
2988448560,2988448563,DE
2988448564,2988448575,ES
@@ -66094,7 +67484,9 @@
2988449536,2988449579,FR
2988449580,2988449583,PL
2988449584,2988449631,FR
-2988449632,2988449647,ES
+2988449632,2988449639,ES
+2988449640,2988449643,CH
+2988449644,2988449647,CZ
2988449648,2988449663,FR
2988449664,2988449695,DE
2988449696,2988449727,IT
@@ -66107,7 +67499,9 @@
2988457984,2988457987,FR
2988457988,2988457991,PL
2988457992,2988457995,CH
-2988457996,2988458031,FR
+2988457996,2988457999,FR
+2988458000,2988458015,DE
+2988458016,2988458031,FR
2988458032,2988458047,IT
2988458048,2988458055,PL
2988458056,2988458063,CH
@@ -66170,7 +67564,7 @@
2988459260,2988459263,NL
2988459264,2988459519,ES
2988459520,2988459583,DE
-2988459584,2988459599,FR
+2988459584,2988459599,ES
2988459600,2988459603,GB
2988459604,2988459615,FR
2988459616,2988459631,CZ
@@ -66200,8 +67594,7 @@
2988459856,2988459863,FR
2988459864,2988459867,ES
2988459868,2988459871,GB
-2988459872,2988459887,FR
-2988459888,2988459895,PL
+2988459872,2988459895,PL
2988459896,2988459967,FR
2988459968,2988459999,ES
2988460000,2988460015,NL
@@ -66258,8 +67651,8 @@
2988460932,2988460943,PL
2988460944,2988460959,DE
2988460960,2988460991,GB
-2988460992,2988461087,FR
-2988461088,2988461103,PL
+2988460992,2988461055,FR
+2988461056,2988461103,PL
2988461104,2988461151,FR
2988461152,2988461183,GB
2988461184,2988461255,FR
@@ -66301,7 +67694,7 @@
2988461624,2988461695,FR
2988461696,2988461699,DE
2988461700,2988461703,PL
-2988461704,2988461707,NL
+2988461704,2988461707,FR
2988461708,2988461711,BE
2988461712,2988461719,FR
2988461720,2988461723,DE
@@ -66380,7 +67773,8 @@
2988463104,2988463107,IT
2988463108,2988463111,FR
2988463112,2988463119,ES
-2988463120,2988463127,GB
+2988463120,2988463123,GB
+2988463124,2988463127,ES
2988463128,2988463131,FR
2988463132,2988463135,PL
2988463136,2988463143,NL
@@ -66393,7 +67787,7 @@
2988463204,2988463207,DE
2988463208,2988463211,FR
2988463212,2988463223,GB
-2988463224,2988463227,FR
+2988463224,2988463227,ES
2988463228,2988463231,CH
2988463232,2988463263,NL
2988463264,2988463279,PL
@@ -66451,8 +67845,7 @@
2988464284,2988464287,PL
2988464288,2988464303,FR
2988464304,2988464307,IT
-2988464308,2988464319,FR
-2988464320,2988464351,GB
+2988464308,2988464351,FR
2988464352,2988464355,DE
2988464356,2988464359,FR
2988464360,2988464363,PL
@@ -66466,22 +67859,23 @@
2988464576,2988464591,GB
2988464592,2988464607,FR
2988464608,2988464611,DE
-2988464612,2988464615,PL
-2988464616,2988464619,FR
+2988464612,2988464619,PL
2988464620,2988464623,ES
2988464624,2988464627,FR
2988464628,2988464631,IT
2988464632,2988464783,FR
2988464784,2988464787,IT
2988464788,2988464791,ES
-2988464792,2988464799,FR
+2988464792,2988464795,FR
+2988464796,2988464799,GB
2988464800,2988464815,DE
2988464816,2988464819,FR
2988464820,2988464823,NL
2988464824,2988464831,PL
2988464832,2988464895,ES
2988464896,2988464927,NL
-2988464928,2988464947,FR
+2988464928,2988464943,ES
+2988464944,2988464947,FR
2988464948,2988464951,CH
2988464952,2988464955,FR
2988464956,2988464959,GB
@@ -66543,16 +67937,38 @@
2988466144,2988466159,NL
2988466160,2988476415,FR
2988476416,2988478463,IT
-2988478464,2988482799,FR
+2988478464,2988482559,FR
+2988482560,2988482567,ES
+2988482568,2988482579,FR
+2988482580,2988482591,ES
+2988482592,2988482607,PL
+2988482608,2988482631,FR
+2988482632,2988482639,PL
+2988482640,2988482647,FR
+2988482648,2988482651,CZ
+2988482652,2988482655,GB
+2988482656,2988482763,FR
+2988482764,2988482767,GB
+2988482768,2988482775,PL
+2988482776,2988482779,NL
+2988482780,2988482783,PL
+2988482784,2988482799,FR
2988482800,2988482807,ES
2988482808,2988482811,GB
2988482812,2988482815,FR
2988482816,2988482819,NL
2988482820,2988482823,DE
-2988482824,2988482827,PL
-2988482828,2988482895,FR
-2988482896,2988482911,GB
-2988482912,2988482935,FR
+2988482824,2988482831,PL
+2988482832,2988482839,FI
+2988482840,2988482843,ES
+2988482844,2988482847,NL
+2988482848,2988482863,FR
+2988482864,2988482871,ES
+2988482872,2988482875,PT
+2988482876,2988482879,CZ
+2988482880,2988482895,FR
+2988482896,2988482927,GB
+2988482928,2988482935,FR
2988482936,2988482939,PL
2988482940,2988482943,LT
2988482944,2988482959,PL
@@ -66560,17 +67976,17 @@
2988482976,2988482979,DE
2988482980,2988482983,GB
2988482984,2988482987,DE
-2988482988,2988483079,FR
-2988483080,2988483087,IT
-2988483088,2988483091,FR
+2988482988,2988483091,FR
2988483092,2988483095,BE
-2988483096,2988483103,FR
+2988483096,2988483099,FR
+2988483100,2988483103,PL
2988483104,2988483107,IE
2988483108,2988483111,PL
2988483112,2988483115,ES
2988483116,2988483119,PL
2988483120,2988483127,ES
-2988483128,2988483151,FR
+2988483128,2988483135,PL
+2988483136,2988483151,FR
2988483152,2988483155,CH
2988483156,2988483159,FR
2988483160,2988483167,ES
@@ -66659,19 +68075,55 @@
2988484512,2988484543,IT
2988484544,2988484591,FR
2988484592,2988484607,ES
-2988484608,2988484863,FR
+2988484608,2988484775,FR
+2988484776,2988484783,PL
+2988484784,2988484831,FR
+2988484832,2988484847,PL
+2988484848,2988484863,FR
2988484864,2988484879,ES
-2988484880,2988484991,FR
+2988484880,2988484883,GB
+2988484884,2988484887,PL
+2988484888,2988484891,FR
+2988484892,2988484895,GB
+2988484896,2988484927,FR
+2988484928,2988484959,PT
+2988484960,2988484991,FR
2988484992,2988485007,LT
2988485008,2988485023,PL
-2988485024,2988485071,FR
+2988485024,2988485039,IE
+2988485040,2988485055,PL
+2988485056,2988485071,FR
2988485072,2988485087,IE
-2988485088,2988485327,FR
+2988485088,2988485119,PL
+2988485120,2988485135,FR
+2988485136,2988485151,PL
+2988485152,2988485167,IT
+2988485168,2988485183,FR
+2988485184,2988485247,BE
+2988485248,2988485255,IT
+2988485256,2988485263,NL
+2988485264,2988485267,DE
+2988485268,2988485271,CH
+2988485272,2988485279,FR
+2988485280,2988485311,PL
+2988485312,2988485327,IT
2988485328,2988485335,FI
2988485336,2988485343,PT
-2988485344,2988485487,FR
-2988485488,2988485503,DE
-2988485504,2988485599,FR
+2988485344,2988485347,ES
+2988485348,2988485351,IT
+2988485352,2988485355,GB
+2988485356,2988485359,PL
+2988485360,2988485439,FR
+2988485440,2988485455,PL
+2988485456,2988485479,FR
+2988485480,2988485487,IT
+2988485488,2988485503,FR
+2988485504,2988485519,GB
+2988485520,2988485559,FR
+2988485560,2988485567,NL
+2988485568,2988485583,GB
+2988485584,2988485591,ES
+2988485592,2988485599,FR
2988485600,2988485607,PL
2988485608,2988485611,GB
2988485612,2988485615,PL
@@ -66702,7 +68154,7 @@
2988486072,2988486075,FR
2988486076,2988486079,ES
2988486080,2988486083,BE
-2988486084,2988486087,NL
+2988486084,2988486087,IT
2988486088,2988486111,FR
2988486112,2988486127,PL
2988486128,2988486159,NL
@@ -66822,7 +68274,8 @@
2988489348,2988489351,PL
2988489352,2988489355,FR
2988489356,2988489359,PT
-2988489360,2988489379,ES
+2988489360,2988489375,FR
+2988489376,2988489379,ES
2988489380,2988489383,GB
2988489384,2988489391,FR
2988489392,2988489399,NL
@@ -66836,8 +68289,9 @@
2988489484,2988489487,GB
2988489488,2988489503,FR
2988489504,2988489519,GB
-2988489520,2988489535,ES
-2988489536,2988489543,PT
+2988489520,2988489527,ES
+2988489528,2988489539,NL
+2988489540,2988489543,CH
2988489544,2988489663,FR
2988489664,2988489667,DE
2988489668,2988489671,GB
@@ -66901,7 +68355,278 @@
2988490424,2988490463,FR
2988490464,2988490623,PL
2988490624,2988490751,ES
-2988490752,2988507143,FR
+2988490752,2988492799,FR
+2988492800,2988494847,PL
+2988494848,2988498991,FR
+2988498992,2988499007,PL
+2988499008,2988499039,FR
+2988499040,2988499051,DE
+2988499052,2988499055,IT
+2988499056,2988499063,FR
+2988499064,2988499067,DE
+2988499068,2988499071,FR
+2988499072,2988499103,PL
+2988499104,2988499119,IE
+2988499120,2988499135,FR
+2988499136,2988499139,DE
+2988499140,2988499143,FR
+2988499144,2988499151,DE
+2988499152,2988499167,FR
+2988499168,2988499199,ES
+2988499200,2988499327,FR
+2988499328,2988499343,NL
+2988499344,2988499347,PL
+2988499348,2988499351,FR
+2988499352,2988499359,IT
+2988499360,2988499367,PL
+2988499368,2988499375,IT
+2988499376,2988499379,PT
+2988499380,2988499387,PL
+2988499388,2988499407,FR
+2988499408,2988499415,PL
+2988499416,2988499423,FR
+2988499424,2988499455,PL
+2988499456,2988499463,NL
+2988499464,2988499471,DE
+2988499472,2988499487,FR
+2988499488,2988499519,PL
+2988499520,2988499551,FR
+2988499552,2988499559,PL
+2988499560,2988499567,NL
+2988499568,2988499575,IE
+2988499576,2988499579,FR
+2988499580,2988499583,CH
+2988499584,2988499599,IT
+2988499600,2988499615,PL
+2988499616,2988499623,DE
+2988499624,2988499631,ES
+2988499632,2988499635,CH
+2988499636,2988499639,DE
+2988499640,2988499663,GB
+2988499664,2988499671,DE
+2988499672,2988499679,NL
+2988499680,2988499683,FR
+2988499684,2988499687,CZ
+2988499688,2988499691,FI
+2988499692,2988499695,IT
+2988499696,2988499699,PT
+2988499700,2988499703,GB
+2988499704,2988499711,DE
+2988499712,2988499731,GB
+2988499732,2988499735,FR
+2988499736,2988499743,NL
+2988499744,2988499747,IE
+2988499748,2988499751,LT
+2988499752,2988499755,PL
+2988499756,2988499759,ES
+2988499760,2988499763,CH
+2988499764,2988499775,PL
+2988499776,2988499791,IT
+2988499792,2988499795,GB
+2988499796,2988499803,IT
+2988499804,2988499807,DE
+2988499808,2988499823,FR
+2988499824,2988499839,DE
+2988499840,2988499847,BE
+2988499848,2988499851,DE
+2988499852,2988499855,PL
+2988499856,2988499871,ES
+2988499872,2988499903,CH
+2988499904,2988499907,FR
+2988499908,2988499911,BE
+2988499912,2988499919,FR
+2988499920,2988499923,DE
+2988499924,2988499927,BE
+2988499928,2988499935,FR
+2988499936,2988499967,IE
+2988499968,2988500223,FR
+2988500224,2988500255,NL
+2988500256,2988500271,IT
+2988500272,2988500287,BE
+2988500288,2988500303,PL
+2988500304,2988500307,FR
+2988500308,2988500311,IT
+2988500312,2988500315,FR
+2988500316,2988500319,DE
+2988500320,2988500335,IT
+2988500336,2988500347,FR
+2988500348,2988500351,PL
+2988500352,2988500367,IE
+2988500368,2988500383,DE
+2988500384,2988500399,BE
+2988500400,2988500415,DE
+2988500416,2988500447,PL
+2988500448,2988500479,ES
+2988500480,2988500495,DE
+2988500496,2988500499,PL
+2988500500,2988500503,DE
+2988500504,2988500511,PL
+2988500512,2988500519,NL
+2988500520,2988500523,ES
+2988500524,2988500527,GB
+2988500528,2988500543,BE
+2988500544,2988500607,PL
+2988500608,2988500639,FR
+2988500640,2988500671,GB
+2988500672,2988500679,IT
+2988500680,2988500687,PL
+2988500688,2988500703,NL
+2988500704,2988500711,PL
+2988500712,2988500719,FR
+2988500720,2988500735,FI
+2988500736,2988500751,PT
+2988500752,2988500767,FR
+2988500768,2988500771,PT
+2988500772,2988500775,ES
+2988500776,2988500779,GB
+2988500780,2988500783,PL
+2988500784,2988500791,FR
+2988500792,2988500799,PL
+2988500800,2988500815,ES
+2988500816,2988500863,FR
+2988500864,2988500867,GB
+2988500868,2988500871,DE
+2988500872,2988500879,NL
+2988500880,2988500883,IE
+2988500884,2988500887,PL
+2988500888,2988500895,DE
+2988500896,2988500919,FR
+2988500920,2988500927,PL
+2988500928,2988500935,FR
+2988500936,2988500939,DE
+2988500940,2988500943,FI
+2988500944,2988500959,IT
+2988500960,2988500975,IE
+2988500976,2988500979,CZ
+2988500980,2988500983,NL
+2988500984,2988500987,DE
+2988500988,2988500991,PL
+2988500992,2988501055,FR
+2988501056,2988501119,PT
+2988501120,2988501199,FR
+2988501200,2988501215,GB
+2988501216,2988501219,DE
+2988501220,2988501223,ES
+2988501224,2988501227,PL
+2988501228,2988501231,CZ
+2988501232,2988501247,PL
+2988501248,2988501327,FR
+2988501328,2988501331,FI
+2988501332,2988501335,GB
+2988501336,2988501339,FR
+2988501340,2988501359,PL
+2988501360,2988501367,FR
+2988501368,2988501375,ES
+2988501376,2988501407,FR
+2988501408,2988501411,LT
+2988501412,2988501415,NL
+2988501416,2988501423,BE
+2988501424,2988501439,NL
+2988501440,2988501471,BE
+2988501472,2988501475,PT
+2988501476,2988501479,BE
+2988501480,2988501483,DE
+2988501484,2988501487,PL
+2988501488,2988501503,FR
+2988501504,2988501567,PT
+2988501568,2988501631,PL
+2988501632,2988501663,DE
+2988501664,2988501679,CH
+2988501680,2988501683,PL
+2988501684,2988501687,GB
+2988501688,2988501691,FR
+2988501692,2988501695,PL
+2988501696,2988501727,FI
+2988501728,2988501759,PL
+2988501760,2988502031,FR
+2988502032,2988502047,DE
+2988502048,2988502063,NL
+2988502064,2988502067,FR
+2988502068,2988502071,GB
+2988502072,2988502075,PL
+2988502076,2988502079,ES
+2988502080,2988502095,IE
+2988502096,2988502099,FI
+2988502100,2988502103,CZ
+2988502104,2988502111,PT
+2988502112,2988502143,PL
+2988502144,2988502207,FR
+2988502208,2988502223,GB
+2988502224,2988502255,FR
+2988502256,2988502263,GB
+2988502264,2988502267,ES
+2988502268,2988502271,DE
+2988502272,2988502399,FR
+2988502400,2988502407,NL
+2988502408,2988502411,FR
+2988502412,2988502415,CH
+2988502416,2988502431,DE
+2988502432,2988502447,FR
+2988502448,2988502451,IE
+2988502452,2988502455,IT
+2988502456,2988502459,ES
+2988502460,2988502463,PT
+2988502464,2988502527,FR
+2988502528,2988502591,PL
+2988502592,2988502599,FR
+2988502600,2988502603,DE
+2988502604,2988502607,PL
+2988502608,2988502631,FR
+2988502632,2988502639,NL
+2988502640,2988502655,FR
+2988502656,2988502719,DE
+2988502720,2988502723,ES
+2988502724,2988502731,FR
+2988502732,2988502735,PL
+2988502736,2988502751,FR
+2988502752,2988502783,ES
+2988502784,2988502795,FR
+2988502796,2988502799,DE
+2988502800,2988502831,GB
+2988502832,2988502839,DE
+2988502840,2988502847,NL
+2988502848,2988502851,FR
+2988502852,2988502855,CH
+2988502856,2988502859,FI
+2988502860,2988502863,BE
+2988502864,2988502867,IE
+2988502868,2988502871,LT
+2988502872,2988502875,PL
+2988502876,2988502879,ES
+2988502880,2988502883,IT
+2988502884,2988502887,CZ
+2988502888,2988502891,NL
+2988502892,2988502895,PL
+2988502896,2988502911,FR
+2988502912,2988502915,PL
+2988502916,2988502919,CH
+2988502920,2988502959,FR
+2988502960,2988502975,IE
+2988502976,2988502983,PL
+2988502984,2988502991,BE
+2988502992,2988503015,DE
+2988503016,2988503019,PL
+2988503020,2988503023,ES
+2988503024,2988503031,GB
+2988503032,2988503035,ES
+2988503036,2988503039,GB
+2988503040,2988503079,FR
+2988503080,2988503103,GB
+2988503104,2988503107,ES
+2988503108,2988503111,NL
+2988503112,2988503119,PL
+2988503120,2988503127,DE
+2988503128,2988503131,IT
+2988503132,2988503151,PL
+2988503152,2988503155,DE
+2988503156,2988503159,LT
+2988503160,2988503167,ES
+2988503168,2988503171,PL
+2988503172,2988503183,ES
+2988503184,2988503199,NL
+2988503200,2988503215,FR
+2988503216,2988503231,PL
+2988503232,2988507143,FR
2988507144,2988507147,BE
2988507148,2988507151,IT
2988507152,2988507159,DE
@@ -66922,7 +68647,9 @@
2988507280,2988507287,GB
2988507288,2988507327,FR
2988507328,2988507335,DE
-2988507336,2988507423,FR
+2988507336,2988507339,FR
+2988507340,2988507343,NL
+2988507344,2988507423,FR
2988507424,2988507431,PL
2988507432,2988507439,DE
2988507440,2988507443,IT
@@ -67005,7 +68732,9 @@
2988508208,2988508215,PL
2988508216,2988508219,FR
2988508220,2988508223,DE
-2988508224,2988508263,FR
+2988508224,2988508255,FR
+2988508256,2988508259,BE
+2988508260,2988508263,FR
2988508264,2988508271,ES
2988508272,2988508287,FR
2988508288,2988508303,PL
@@ -67033,7 +68762,9 @@
2988508712,2988508719,DE
2988508720,2988508723,IT
2988508724,2988508735,GB
-2988508736,2988508847,FR
+2988508736,2988508767,FR
+2988508768,2988508799,PT
+2988508800,2988508847,FR
2988508848,2988508855,GB
2988508856,2988508871,FR
2988508872,2988508875,PL
@@ -67045,8 +68776,7 @@
2988508944,2988508947,DE
2988508948,2988508951,FR
2988508952,2988508959,ES
-2988508960,2988508975,IT
-2988508976,2988508991,FR
+2988508960,2988508991,FR
2988508992,2988509055,NL
2988509056,2988509119,FR
2988509120,2988509151,IT
@@ -67155,7 +68885,20 @@
2988510408,2988510415,PL
2988510416,2988510431,FR
2988510432,2988510435,IT
-2988510436,2988510751,FR
+2988510436,2988510463,FR
+2988510464,2988510495,PL
+2988510496,2988510511,FR
+2988510512,2988510515,GB
+2988510516,2988510519,DE
+2988510520,2988510527,IE
+2988510528,2988510559,FR
+2988510560,2988510591,IT
+2988510592,2988510623,BE
+2988510624,2988510655,IE
+2988510656,2988510687,PL
+2988510688,2988510703,FR
+2988510704,2988510719,PL
+2988510720,2988510751,FR
2988510752,2988510759,PL
2988510760,2988510767,FR
2988510768,2988510775,ES
@@ -67292,8 +69035,7 @@
2988512840,2988512847,DE
2988512848,2988512851,ES
2988512852,2988512855,DE
-2988512856,2988512883,FR
-2988512884,2988512895,DE
+2988512856,2988512895,FR
2988512896,2988512899,PL
2988512900,2988512903,GB
2988512904,2988512907,ES
@@ -67341,8 +69083,7 @@
2988513360,2988513375,GB
2988513376,2988513379,FR
2988513380,2988513383,PT
-2988513384,2988513391,GB
-2988513392,2988513407,FR
+2988513384,2988513407,FR
2988513408,2988513471,PL
2988513472,2988513503,FR
2988513504,2988513507,CH
@@ -67366,9 +69107,7 @@
2988513704,2988513707,DE
2988513708,2988513723,FR
2988513724,2988513727,DE
-2988513728,2988513731,FR
-2988513732,2988513735,BE
-2988513736,2988513739,FR
+2988513728,2988513739,FR
2988513740,2988513743,ES
2988513744,2988513759,GB
2988513760,2988513879,FR
@@ -67422,8 +69161,7 @@
2988514304,2988514335,FR
2988514336,2988514339,IE
2988514340,2988514343,FR
-2988514344,2988514351,GB
-2988514352,2988514359,PL
+2988514344,2988514359,PL
2988514360,2988514367,ES
2988514368,2988514399,FR
2988514400,2988514431,GB
@@ -67457,7 +69195,9 @@
2988514984,2988514991,IT
2988514992,2988514995,FR
2988514996,2988515007,PL
-2988515008,2988515039,FR
+2988515008,2988515027,FR
+2988515028,2988515031,DE
+2988515032,2988515039,FR
2988515040,2988515071,GB
2988515072,2988515327,FR
2988515328,2988517375,DE
@@ -67510,7 +69250,7 @@
2988524308,2988524319,GB
2988524320,2988524351,FR
2988524352,2988524359,CH
-2988524360,2988524363,GB
+2988524360,2988524363,ES
2988524364,2988524367,DE
2988524368,2988524383,GB
2988524384,2988524415,IE
@@ -67543,22 +69283,26 @@
2988525852,2988525887,DE
2988525888,2988525951,FI
2988525952,2988526079,ES
-2988526080,2988526423,PL
+2988526080,2988526143,PT
+2988526144,2988526175,BE
+2988526176,2988526239,ES
+2988526240,2988526423,PL
2988526424,2988526427,NL
2988526428,2988526431,ES
2988526432,2988526447,FR
2988526448,2988526451,ES
2988526452,2988526455,FR
2988526456,2988526463,ES
-2988526464,2988526527,FR
-2988526528,2988526543,GB
+2988526464,2988526543,FR
2988526544,2988526559,IT
2988526560,2988526579,FR
2988526580,2988526583,ES
2988526584,2988526591,DE
2988526592,2988526607,FR
2988526608,2988526615,DE
-2988526616,2988526687,FR
+2988526616,2988526655,FR
+2988526656,2988526663,PL
+2988526664,2988526687,FR
2988526688,2988526703,ES
2988526704,2988526711,FR
2988526712,2988526715,ES
@@ -67690,7 +69434,8 @@
2988529248,2988529251,GB
2988529252,2988529255,PL
2988529256,2988529263,NL
-2988529264,2988529311,FR
+2988529264,2988529279,ES
+2988529280,2988529311,FR
2988529312,2988529315,PL
2988529316,2988529319,FR
2988529320,2988529323,FI
@@ -67724,7 +69469,10 @@
2988529768,2988529771,FR
2988529772,2988529775,DE
2988529776,2988529783,ES
-2988529784,2988529823,FR
+2988529784,2988529791,FR
+2988529792,2988529799,ES
+2988529800,2988529807,DE
+2988529808,2988529823,FR
2988529824,2988529855,ES
2988529856,2988529887,FR
2988529888,2988529891,DE
@@ -67737,7 +69485,7 @@
2988529940,2988529943,GB
2988529944,2988529951,ES
2988529952,2988529955,GB
-2988529956,2988529959,DE
+2988529956,2988529959,PL
2988529960,2988529967,GB
2988529968,2988529983,NL
2988529984,2988529999,GB
@@ -67754,15 +69502,14 @@
2988530104,2988530111,GB
2988530112,2988530191,FR
2988530192,2988530207,NL
-2988530208,2988530239,IE
+2988530208,2988530239,PL
2988530240,2988530271,FR
2988530272,2988530303,IE
2988530304,2988530367,FR
2988530368,2988530371,ES
2988530372,2988530379,FR
2988530380,2988530383,CH
-2988530384,2988530391,FR
-2988530392,2988530399,IE
+2988530384,2988530399,FR
2988530400,2988530403,ES
2988530404,2988530415,FR
2988530416,2988530419,PT
@@ -67784,9 +69531,9 @@
2988530872,2988530879,IT
2988530880,2988530887,PL
2988530888,2988530895,DE
-2988530896,2988530943,FR
-2988530944,2988530959,BE
-2988530960,2988530975,FR
+2988530896,2988530927,FR
+2988530928,2988530943,FI
+2988530944,2988530975,FR
2988530976,2988531007,PL
2988531008,2988531015,DE
2988531016,2988531019,NL
@@ -67855,8 +69602,9 @@
2988540364,2988540367,PL
2988540368,2988540375,FR
2988540376,2988540379,GB
-2988540380,2988540423,FR
-2988540424,2988540427,GB
+2988540380,2988540415,FR
+2988540416,2988540419,CZ
+2988540420,2988540427,GB
2988540428,2988540431,NL
2988540432,2988540435,FR
2988540436,2988540439,DE
@@ -67866,7 +69614,7 @@
2988540456,2988540459,DE
2988540460,2988540463,ES
2988540464,2988540471,PL
-2988540472,2988540479,DE
+2988540472,2988540479,ES
2988540480,2988540483,FR
2988540484,2988540487,DE
2988540488,2988540491,ES
@@ -68038,17 +69786,16 @@
2988542784,2988542847,CZ
2988542848,2988542919,DE
2988542920,2988542923,PL
-2988542924,2988542927,CH
-2988542928,2988542935,FR
+2988542924,2988542935,FR
2988542936,2988542939,IT
2988542940,2988542943,PL
2988542944,2988542959,DE
2988542960,2988542963,FR
-2988542964,2988542967,PL
+2988542964,2988542967,CH
2988542968,2988542975,DE
2988542976,2988543007,FR
2988543008,2988543011,PL
-2988543012,2988543015,IT
+2988543012,2988543015,LT
2988543016,2988543023,CH
2988543024,2988543039,DE
2988543040,2988543047,GB
@@ -68133,7 +69880,7 @@
2988544272,2988544275,DE
2988544276,2988544279,FR
2988544280,2988544283,GB
-2988544284,2988544287,DE
+2988544284,2988544287,CZ
2988544288,2988544291,PL
2988544292,2988544295,GB
2988544296,2988544303,FR
@@ -68182,12 +69929,11 @@
2988544928,2988544931,DE
2988544932,2988544935,FR
2988544936,2988544943,IT
-2988544944,2988544951,PL
+2988544944,2988544951,PT
2988544952,2988544959,GB
2988544960,2988544979,ES
2988544980,2988544983,FR
-2988544984,2988544991,IE
-2988544992,2988544995,PL
+2988544984,2988544995,PL
2988544996,2988544999,FR
2988545000,2988545003,DE
2988545004,2988545007,ES
@@ -68255,7 +70001,7 @@
2988545860,2988545867,FR
2988545868,2988545871,PL
2988545872,2988545919,FR
-2988545920,2988545923,GB
+2988545920,2988545923,ES
2988545924,2988545927,PL
2988545928,2988545931,BE
2988545932,2988545935,DE
@@ -68285,7 +70031,7 @@
2988546176,2988546239,GB
2988546240,2988546271,LT
2988546272,2988546279,IT
-2988546280,2988546283,GB
+2988546280,2988546283,DE
2988546284,2988546287,BE
2988546288,2988546291,GB
2988546292,2988546295,ES
@@ -68331,11 +70077,13 @@
2988546832,2988546835,DE
2988546836,2988546839,ES
2988546840,2988546847,IE
-2988546848,2988546879,FR
+2988546848,2988546851,PT
+2988546852,2988546855,IT
+2988546856,2988546879,FR
2988546880,2988546947,ES
2988546948,2988546951,DE
2988546952,2988546955,FR
-2988546956,2988546959,GB
+2988546956,2988546959,DE
2988546960,2988546963,CH
2988546964,2988546967,IT
2988546968,2988546971,FR
@@ -68345,8 +70093,7 @@
2988546996,2988546999,ES
2988547000,2988547003,IT
2988547004,2988547007,ES
-2988547008,2988547011,GB
-2988547012,2988547015,FR
+2988547008,2988547015,FR
2988547016,2988547019,NL
2988547020,2988547023,ES
2988547024,2988547039,FR
@@ -68460,7 +70207,8 @@
2988556964,2988556967,FR
2988556968,2988556975,BE
2988556976,2988556979,FI
-2988556980,2988557003,FR
+2988556980,2988556999,FR
+2988557000,2988557003,BE
2988557004,2988557007,ES
2988557008,2988557023,FR
2988557024,2988557039,IE
@@ -68492,7 +70240,7 @@
2988557344,2988557379,FR
2988557380,2988557383,ES
2988557384,2988557387,GB
-2988557388,2988557391,ES
+2988557388,2988557391,CZ
2988557392,2988557399,PL
2988557400,2988557407,DE
2988557408,2988557427,ES
@@ -68544,7 +70292,8 @@
2988558464,2988558527,NL
2988558528,2988558591,PL
2988558592,2988558655,GB
-2988558656,2988558727,FR
+2988558656,2988558719,FR
+2988558720,2988558727,PL
2988558728,2988558731,IT
2988558732,2988558735,PT
2988558736,2988558751,GB
@@ -68630,8 +70379,8 @@
2988560992,2988560995,FR
2988560996,2988561007,DE
2988561008,2988561023,FR
-2988561024,2988561031,ES
-2988561032,2988561039,FR
+2988561024,2988561027,BE
+2988561028,2988561039,FR
2988561040,2988561043,GB
2988561044,2988561047,FR
2988561048,2988561051,PL
@@ -68657,7 +70406,12 @@
2988561200,2988561203,PL
2988561204,2988561207,GB
2988561208,2988561215,PL
-2988561216,2988561283,FR
+2988561216,2988561231,FR
+2988561232,2988561235,PT
+2988561236,2988561239,GB
+2988561240,2988561243,BE
+2988561244,2988561263,PL
+2988561264,2988561283,FR
2988561284,2988561287,NL
2988561288,2988561291,ES
2988561292,2988561295,PT
@@ -68671,7 +70425,10 @@
2988561668,2988561671,PL
2988561672,2988561675,NL
2988561676,2988561679,FI
-2988561680,2988561695,ES
+2988561680,2988561683,FR
+2988561684,2988561687,CZ
+2988561688,2988561691,DE
+2988561692,2988561695,LT
2988561696,2988561727,FR
2988561728,2988561743,PL
2988561744,2988561747,FR
@@ -68689,8 +70446,7 @@
2988561888,2988561903,PL
2988561904,2988561983,FR
2988561984,2988562015,DE
-2988562016,2988562023,PT
-2988562024,2988562027,ES
+2988562016,2988562027,ES
2988562028,2988562031,LT
2988562032,2988562047,PL
2988562048,2988562079,DE
@@ -68723,7 +70479,7 @@
2988562864,2988562911,FR
2988562912,2988562943,PL
2988562944,2988563011,FR
-2988563012,2988563015,PL
+2988563012,2988563015,PT
2988563016,2988563023,GB
2988563024,2988563043,FR
2988563044,2988563047,ES
@@ -68762,19 +70518,39 @@
2988563676,2988563679,PL
2988563680,2988563967,FR
2988563968,2988563999,BE
-2988564000,2988564019,FR
+2988564000,2988564015,IE
+2988564016,2988564019,FR
2988564020,2988564023,PL
2988564024,2988564031,FR
2988564032,2988564063,BE
-2988564064,2988564191,FR
+2988564064,2988564175,FR
+2988564176,2988564179,PL
+2988564180,2988564183,GB
+2988564184,2988564191,IT
2988564192,2988564195,ES
2988564196,2988564203,DE
-2988564204,2988564383,FR
+2988564204,2988564215,FR
+2988564216,2988564219,GB
+2988564220,2988564223,IT
+2988564224,2988564279,FR
+2988564280,2988564287,ES
+2988564288,2988564303,FR
+2988564304,2988564307,IT
+2988564308,2988564311,PL
+2988564312,2988564319,ES
+2988564320,2988564351,FR
+2988564352,2988564359,DE
+2988564360,2988564367,GB
+2988564368,2988564383,FR
2988564384,2988564387,IE
2988564388,2988564391,GB
2988564392,2988564395,NL
2988564396,2988564399,CH
-2988564400,2988572671,FR
+2988564400,2988564403,DE
+2988564404,2988564407,ES
+2988564408,2988564471,FR
+2988564472,2988564479,GB
+2988564480,2988572671,FR
2988572672,2988703743,RU
2988703744,2988834815,PL
2988834816,2988965887,CH
@@ -68799,7 +70575,9 @@
2990518016,2990518079,IT
2990518080,2990525247,DE
2990525248,2990525311,ES
-2990525312,2990535935,DE
+2990525312,2990534655,DE
+2990534656,2990534687,EG
+2990534688,2990535935,DE
2990535936,2990535967,PL
2990535968,2990538751,DE
2990538752,2991063039,RU
@@ -69014,11 +70792,7 @@
2991981064,2991981071,DE
2991981072,2991981495,UA
2991981496,2991981503,NA
-2991981504,2991981647,UA
-2991981648,2991981655,NA
-2991981656,2991981687,UA
-2991981688,2991981695,NA
-2991981696,2991981839,UA
+2991981504,2991981839,UA
2991981840,2991981847,RU
2991981848,2991982535,UA
2991982536,2991982543,GL
@@ -69085,8 +70859,8 @@
2996862976,2996895743,AM
2996895744,2996928511,KW
2996928512,2996994047,RU
-2996994048,2996994879,DE
-2996994880,2996994943,UA
+2996994048,2996994911,DE
+2996994912,2996994943,BR
2996994944,2996995071,US
2996995072,2996995327,BZ
2996995328,2996995647,DE
@@ -69131,7 +70905,8 @@
2997001120,2997001471,DE
2997001472,2997001727,BZ
2997001728,2997001983,TR
-2997001984,2997003071,DE
+2997001984,2997003039,DE
+2997003040,2997003071,BR
2997003072,2997003135,RU
2997003136,2997003199,DE
2997003200,2997003263,RU
@@ -69139,11 +70914,10 @@
2997003288,2997003295,NL
2997003296,2997003327,CA
2997003328,2997003391,RU
-2997003392,2997003583,DE
-2997003584,2997003647,UA
-2997003648,2997004031,DE
+2997003392,2997004031,DE
2997004032,2997004287,BZ
-2997004288,2997004607,DE
+2997004288,2997004543,CA
+2997004544,2997004607,DE
2997004608,2997004671,RU
2997004672,2997004799,DE
2997004800,2997005055,BZ
@@ -69181,7 +70955,7 @@
2997020672,2997020719,DE
2997020720,2997020735,SE
2997020736,2997020799,DE
-2997020800,2997020863,US
+2997020800,2997020863,CA
2997020864,2997021183,DE
2997021184,2997021695,GB
2997021696,2997022079,DE
@@ -69239,11 +71013,13 @@
2999985712,2999985727,BE
2999985728,2999985743,CZ
2999985744,2999985759,NL
-2999985760,2999988991,BE
-2999988992,2999989007,FR
-2999989008,2999989247,NL
-2999989248,2999990527,BE
-2999990528,2999992319,NL
+2999985760,2999985918,BE
+2999985919,2999985919,NL
+2999985920,2999988991,BE
+2999988992,2999988999,FR
+2999989000,2999989247,NL
+2999989248,2999991039,BE
+2999991040,2999992319,NL
2999992320,3000000511,RU
3000000512,3000008703,DE
3000008704,3000016895,RU
@@ -69421,31 +71197,46 @@
3001823232,3001827327,GE
3001827328,3001827647,SE
3001827648,3001827743,GB
-3001827744,3001828864,SE
+3001827744,3001827775,US
+3001827776,3001828864,SE
3001828865,3001828896,US
-3001828897,3001829120,SE
+3001828897,3001828927,SE
+3001828928,3001828991,DE
+3001828992,3001829055,GB
+3001829056,3001829120,SE
3001829121,3001829152,US
-3001829153,3001830400,SE
+3001829153,3001829183,SE
+3001829184,3001829247,DE
+3001829248,3001829311,GB
+3001829312,3001830400,SE
3001830401,3001830432,GB
-3001830433,3001830527,SE
+3001830433,3001830495,SE
+3001830496,3001830527,GB
3001830528,3001830559,IT
3001830560,3001830591,FR
3001830592,3001830623,US
-3001830624,3001830656,SE
+3001830624,3001830631,SE
+3001830632,3001830639,IT
+3001830640,3001830656,SE
3001830657,3001830688,GB
-3001830689,3001830783,SE
+3001830689,3001830751,SE
+3001830752,3001830783,GB
3001830784,3001830815,IT
3001830816,3001830847,FR
3001830848,3001830879,US
-3001830880,3001830912,SE
+3001830880,3001830887,SE
+3001830888,3001830895,IT
+3001830896,3001830912,SE
3001830913,3001830944,GB
-3001830945,3001831039,SE
+3001830945,3001831007,SE
+3001831008,3001831039,GB
3001831040,3001831071,IT
3001831072,3001831103,FR
3001831104,3001831135,US
3001831136,3001831167,IT
3001831168,3001831199,GB
-3001831200,3001831295,SE
+3001831200,3001831263,SE
+3001831264,3001831295,GB
3001831296,3001831327,IT
3001831328,3001831359,FR
3001831360,3001831391,US
@@ -69552,8 +71343,7 @@
3001975896,3001975919,GB
3001975920,3001975927,CN
3001975928,3001975935,AU
-3001975936,3001976623,GB
-3001976624,3001976639,CN
+3001975936,3001976639,GB
3001976640,3001976655,RU
3001976656,3001976671,GB
3001976672,3001976679,IN
@@ -69614,8 +71404,7 @@
3002003456,3002011647,PL
3002011648,3002015743,BA
3002015744,3002019839,IT
-3002019840,3002020223,NL
-3002020224,3002020287,IL
+3002019840,3002020287,NL
3002020288,3002020303,US
3002020304,3002023935,NL
3002023936,3002028031,DE
@@ -69788,7 +71577,8 @@
3003058432,3003058687,FI
3003058688,3003058751,EE
3003058752,3003058943,PH
-3003058944,3003060223,EE
+3003058944,3003059199,IL
+3003059200,3003060223,EE
3003060224,3003062271,DE
3003062272,3003064319,NL
3003064320,3003066367,RO
@@ -69808,7 +71598,11 @@
3003088896,3003090943,FR
3003090944,3003092991,DE
3003092992,3003095039,NO
-3003095040,3003097087,AT
+3003095040,3003095567,AT
+3003095568,3003095583,CZ
+3003095584,3003096063,AT
+3003096064,3003096079,CZ
+3003096080,3003097087,AT
3003097088,3003099135,FR
3003099136,3003101183,CZ
3003101184,3003103231,UA
@@ -70055,6 +71849,7 @@
3038511104,3038773247,AR
3039035392,3039166463,DO
3039297536,3039363071,PY
+3039821824,3040346111,CO
3053453312,3054501887,ID
3054501888,3054534655,HK
3054534656,3054537727,PH
@@ -70288,6 +72083,9 @@
3091976192,3091980287,CA
3091980288,3093168127,US
3093168128,3093200895,CA
+3093200896,3093213183,US
+3093213184,3093217279,CA
+3093217280,3093233663,US
3093233664,3093237759,PR
3093237760,3093266431,US
3093299200,3093940991,US
@@ -70433,6 +72231,8 @@
3098099712,3098116095,US
3098148864,3098165247,JM
3098165248,3098181631,US
+3098181632,3098185727,CA
+3098185728,3098202111,US
3098214400,3098263551,US
3098263552,3098271743,CA
3098271744,3098275839,US
@@ -70480,7 +72280,7 @@
3122331648,3122348031,BO
3122397184,3122659327,CO
3122659328,3122724863,GT
-3122790400,3122987007,CL
+3122790400,3123052543,CL
3123052544,3123183615,AR
3123183616,3123314687,CL
3123314688,3123380223,EC
@@ -70493,7 +72293,8 @@
3124822016,3124838399,EC
3124854784,3124887551,CL
3124887552,3124953087,EC
-3125018624,3125149695,EC
+3124953088,3125018623,CL
+3125018624,3125280767,EC
3125280768,3125542911,PA
3125673984,3125805055,CL
3125805056,3126329343,CO
@@ -70512,6 +72313,7 @@
3129016320,3129999359,AR
3129999360,3130261503,CO
3130523648,3130654719,AR
+3130654720,3130720255,CO
3131047936,3131310079,PE
3131572224,3131703295,CO
3132096512,3132162047,CR
@@ -70530,7 +72332,9 @@
3133079552,3133145087,AR
3133145088,3145727999,BR
3145728000,3154116607,MX
-3154116608,3154149375,NO
+3154149376,3154157567,UA
+3154157568,3154173951,RU
+3154173952,3154182143,MD
3154182144,3154247679,DE
3154247680,3154313215,RS
3154313216,3154378751,TR
@@ -70572,7 +72376,6 @@
3157786624,3158048767,TR
3158048768,3158310911,CH
3158310912,3158312959,FI
-3158312960,3158315007,NL
3158315008,3158317055,DE
3158317056,3158319103,SI
3158319104,3158321151,GB
@@ -70618,13 +72421,23 @@
3158395008,3158395135,GB
3158395136,3158395151,AT
3158395152,3158395159,DE
-3158395160,3158395263,AT
+3158395160,3158395167,AT
+3158395168,3158395175,DE
+3158395176,3158395191,AT
+3158395192,3158395199,DE
+3158395200,3158395263,AT
3158395264,3158395295,DE
-3158395296,3158395431,AT
+3158395296,3158395359,AT
+3158395360,3158395367,DE
+3158395368,3158395431,AT
3158395432,3158395439,DE
3158395440,3158395647,AT
3158395648,3158395663,DE
-3158395664,3158396287,AT
+3158395664,3158395687,AT
+3158395688,3158395695,DE
+3158395696,3158395711,AT
+3158395712,3158395743,DE
+3158395744,3158396287,AT
3158396288,3158396319,DE
3158396320,3158396927,AT
3158396928,3158398975,IT
@@ -70842,7 +72655,10 @@
3160324096,3160328191,IT
3160328192,3160330239,FR
3160330240,3160332287,RU
-3160332288,3160333055,NO
+3160332288,3160332751,NO
+3160332752,3160332759,SE
+3160332760,3160332767,AU
+3160332768,3160333055,NO
3160333056,3160333087,CO
3160333088,3160334335,NO
3160334336,3160336383,RU
@@ -70899,10 +72715,14 @@
3161784320,3161800703,FI
3161800704,3161817087,SA
3161817088,3161833471,PL
-3161833472,3161833983,MK
-3161833984,3161834495,AT
-3161834496,3161835263,MK
-3161835264,3161849855,AT
+3161833472,3161835519,MK
+3161835520,3161835775,AT
+3161835776,3161837567,MK
+3161837568,3161837695,AT
+3161837696,3161840639,MK
+3161840640,3161840895,AT
+3161840896,3161844735,MK
+3161844736,3161849855,AT
3161849856,3161866239,BE
3161866240,3161882623,IR
3161882624,3161899007,DE
@@ -71030,11 +72850,10 @@
3163161760,3163161791,BR
3163161792,3163161887,DE
3163161888,3163161951,US
-3163161952,3163162111,DE
+3163161952,3163162079,DE
+3163162080,3163162111,RU
3163162112,3163162143,TR
-3163162144,3163162207,DE
-3163162208,3163162239,TR
-3163162240,3163162271,DE
+3163162144,3163162271,DE
3163162272,3163162303,NL
3163162304,3163162431,DE
3163162432,3163162463,CY
@@ -71052,16 +72871,17 @@
3163164192,3163164223,RU
3163164224,3163164287,DE
3163164288,3163164319,CL
-3163164320,3163164447,DE
+3163164320,3163164351,RU
+3163164352,3163164447,DE
3163164448,3163164479,RU
-3163164480,3163164511,US
+3163164480,3163164511,DE
3163164512,3163164543,HU
3163164544,3163164575,RU
3163164576,3163165759,DE
3163165760,3163165791,PL
3163165792,3163165823,RU
3163165824,3163166175,DE
-3163166176,3163166207,US
+3163166176,3163166207,RU
3163166208,3163166367,DE
3163166368,3163166399,US
3163166400,3163166495,DE
@@ -71103,7 +72923,8 @@
3163170144,3163170175,ZA
3163170176,3163170207,DE
3163170208,3163170239,RU
-3163170240,3163170303,DE
+3163170240,3163170271,DE
+3163170272,3163170303,TW
3163170304,3163170335,IT
3163170336,3163170367,RO
3163170368,3163170495,DE
@@ -71117,22 +72938,22 @@
3163170816,3163171871,DE
3163171872,3163171903,RO
3163171904,3163171935,BZ
-3163171936,3163171967,BR
-3163171968,3163172127,DE
+3163171936,3163172095,DE
+3163172096,3163172127,BR
3163172128,3163172159,US
3163172160,3163172191,TR
3163172192,3163172319,DE
3163172320,3163172351,NL
3163172352,3163172383,GB
-3163172384,3163172447,DE
-3163172448,3163172479,TR
+3163172384,3163172479,DE
3163172480,3163172511,US
3163172512,3163172543,RU
3163172544,3163172607,DE
3163172608,3163172639,DK
3163172640,3163172735,DE
3163172736,3163172767,GR
-3163172768,3163174047,DE
+3163172768,3163174015,DE
+3163174016,3163174047,RU
3163174048,3163174079,DK
3163174080,3163174111,DE
3163174112,3163174143,BE
@@ -71141,7 +72962,7 @@
3163174336,3163174367,RU
3163174368,3163174495,DE
3163174496,3163174527,US
-3163174528,3163174559,DE
+3163174528,3163174559,BD
3163174560,3163174591,PL
3163174592,3163174623,SE
3163174624,3163174655,GB
@@ -71151,14 +72972,17 @@
3163174784,3163174815,DE
3163174816,3163174847,CA
3163174848,3163174879,TR
-3163174880,3163176127,DE
+3163174880,3163176095,DE
+3163176096,3163176127,CY
3163176128,3163176159,US
3163176160,3163176255,DE
3163176256,3163176287,UG
3163176288,3163176319,PT
-3163176320,3163176479,DE
+3163176320,3163176447,DE
+3163176448,3163176479,US
3163176480,3163176511,GB
-3163176512,3163176575,DE
+3163176512,3163176543,TR
+3163176544,3163176575,DE
3163176576,3163176607,GR
3163176608,3163176767,DE
3163176768,3163176799,PL
@@ -71246,7 +73070,7 @@
3164949124,3164949131,DE
3164949132,3164949151,FR
3164949152,3164949155,NL
-3164949156,3164949159,FR
+3164949156,3164949159,DE
3164949160,3164949163,PL
3164949164,3164949183,FR
3164949184,3164949199,GB
@@ -71360,7 +73184,8 @@
3164952192,3164952207,ES
3164952208,3164952215,FR
3164952216,3164952219,NL
-3164952220,3164952239,FR
+3164952220,3164952223,FR
+3164952224,3164952239,GB
3164952240,3164952243,DE
3164952244,3164952247,BE
3164952248,3164952255,FR
@@ -71426,7 +73251,9 @@
3164954544,3164954559,LT
3164954560,3164954591,FR
3164954592,3164954623,PL
-3164954624,3164956479,FR
+3164954624,3164956383,FR
+3164956384,3164956399,DE
+3164956400,3164956479,FR
3164956480,3164956543,GB
3164956544,3164958847,FR
3164958848,3164958911,IT
@@ -71451,8 +73278,9 @@
3164959384,3164959387,PL
3164959388,3164959487,FR
3164959488,3164959743,ES
-3164959744,3164959871,FR
-3164959872,3164959903,GB
+3164959744,3164959887,FR
+3164959888,3164959895,ES
+3164959896,3164959903,PL
3164959904,3164959919,DE
3164959920,3164959927,FR
3164959928,3164959931,GB
@@ -71547,7 +73375,10 @@
3164961656,3164961663,ES
3164961664,3164961695,DE
3164961696,3164961727,GB
-3164961728,3164961743,ES
+3164961728,3164961731,ES
+3164961732,3164961735,IT
+3164961736,3164961739,FR
+3164961740,3164961743,GB
3164961744,3164961763,PL
3164961764,3164961767,IT
3164961768,3164961775,BE
@@ -71693,7 +73524,9 @@
3164970368,3164970371,PL
3164970372,3164970375,ES
3164970376,3164970399,IT
-3164970400,3164970415,GB
+3164970400,3164970407,CH
+3164970408,3164970411,IT
+3164970412,3164970415,GB
3164970416,3164970423,FR
3164970424,3164970427,IE
3164970428,3164970431,PT
@@ -71812,7 +73645,7 @@
3164975352,3164975355,NL
3164975356,3164975359,FR
3164975360,3164975615,ES
-3164975616,3164976127,GB
+3164975616,3164976127,FR
3164976128,3164976131,NL
3164976132,3164976135,GB
3164976136,3164976139,FR
@@ -71843,7 +73676,9 @@
3164976348,3164976351,ES
3164976352,3164976367,DE
3164976368,3164976383,PL
-3164976384,3164976407,FR
+3164976384,3164976399,FR
+3164976400,3164976403,ES
+3164976404,3164976407,FR
3164976408,3164976415,DE
3164976416,3164976431,IT
3164976432,3164976459,FR
@@ -71881,7 +73716,9 @@
3164977888,3164977903,IT
3164977904,3164977919,NL
3164977920,3164978047,DE
-3164978048,3164978067,FR
+3164978048,3164978055,FR
+3164978056,3164978063,NL
+3164978064,3164978067,FR
3164978068,3164978079,ES
3164978080,3164978111,IT
3164978112,3164978127,GB
@@ -71896,8 +73733,10 @@
3164978496,3164978511,IT
3164978512,3164978527,ES
3164978528,3164978543,FR
-3164978544,3164978559,PT
-3164978560,3164978575,FR
+3164978544,3164978563,PT
+3164978564,3164978567,PL
+3164978568,3164978571,GB
+3164978572,3164978575,FR
3164978576,3164978591,ES
3164978592,3164978607,FR
3164978608,3164978623,CZ
@@ -71979,13 +73818,11 @@
3168120832,3168124927,GB
3168124928,3168161791,RO
3168161792,3168165887,GB
-3168165888,3168169983,RO
-3168169984,3168178175,GB
-3168178176,3168182271,RO
-3168182272,3168186367,GB
-3168186368,3168190463,RO
+3168165888,3168190463,RO
3168190464,3168194559,GB
-3168194560,3168207103,RO
+3168194560,3168195583,RO
+3168195584,3168196095,DE
+3168196096,3168207103,RO
3168207104,3168207359,CY
3168207360,3168214527,RO
3168214528,3168214783,CY
@@ -72163,6 +74000,8 @@
3188513536,3188523007,AR
3188523008,3188539391,CO
3188539392,3188543487,CL
+3188543488,3188545535,PA
+3188545536,3188547583,AR
3188547584,3188551679,CO
3188555776,3188572159,CL
3188572160,3188576255,CO
@@ -72314,6 +74153,7 @@
3194585088,3194589183,HN
3194589184,3194591231,AR
3194591232,3194592255,PA
+3194592256,3194593279,GY
3194593280,3194595327,AR
3194595328,3194596351,PA
3194596352,3194597375,HT
@@ -72336,7 +74176,6 @@
3194707968,3194716159,AR
3194716160,3194724351,HN
3194724352,3194728447,PA
-3194732544,3194736639,AR
3194740736,3194742783,CL
3194742784,3194744831,EC
3194744832,3194746879,AR
@@ -72410,7 +74249,8 @@
3195740160,3195744255,PA
3195744256,3195748351,EC
3195748352,3195752447,CL
-3195756544,3195764735,AR
+3195756544,3195763711,AR
+3195763712,3195764735,BO
3195764736,3195768831,CR
3195772928,3195777023,VE
3195781120,3195797503,PA
@@ -72449,6 +74289,11 @@
3197370368,3197501439,GT
3197501440,3197534207,SV
3197566976,3197599743,CL
+3197599744,3197600767,GT
+3197600768,3197601791,CR
+3197603840,3197607935,AR
+3197612032,3197616127,SV
+3197616128,3197632511,CO
3197632512,3197698047,EC
3197698048,3197730815,VE
3197730816,3197763583,CL
@@ -72772,14 +74617,42 @@
3223582464,3223582719,NL
3223582720,3223582975,AU
3223583488,3223584767,US
-3223584768,3223650303,SE
+3223584768,3223589119,SE
+3223589120,3223589375,US
+3223589376,3223606527,SE
+3223606528,3223606783,GB
+3223606784,3223607551,SE
+3223607552,3223607807,GB
+3223607808,3223610367,SE
+3223610368,3223610623,IT
+3223610624,3223610879,SE
+3223610880,3223611135,NO
+3223611136,3223611647,SE
+3223611648,3223611903,GB
+3223611904,3223617535,SE
+3223617536,3223617791,NO
+3223617792,3223620863,SE
+3223620864,3223621119,DK
+3223621120,3223627775,SE
+3223627776,3223628031,DE
+3223628032,3223628287,SE
+3223628288,3223628543,ES
+3223628544,3223630591,SE
+3223630592,3223630847,GB
+3223630848,3223634431,SE
+3223634432,3223634687,US
+3223634688,3223646207,SE
+3223646208,3223646463,IT
+3223646464,3223646975,SE
+3223646976,3223647231,IT
+3223647232,3223650303,SE
3223650304,3223715839,CH
3223715840,3223781375,DK
3223781376,3223823871,US
3223823872,3223824127,AT
3223824128,3223863295,US
3223863552,3223863807,US
-3223864320,3223867647,FI
+3223865344,3223867391,FI
3223871488,3223887871,US
3223898368,3223898623,US
3223902464,3223902719,CA
@@ -73311,7 +75184,35 @@
3225876480,3225878527,US
3225878528,3225880319,SE
3225880320,3225880575,US
-3225880576,3225944063,SE
+3225880576,3225881343,SE
+3225881344,3225881599,IT
+3225881600,3225887999,SE
+3225888000,3225888255,GB
+3225888256,3225905407,SE
+3225905408,3225905663,IT
+3225905664,3225913855,SE
+3225913856,3225914111,DE
+3225914112,3225915135,SE
+3225915136,3225915391,DK
+3225915392,3225918463,SE
+3225918464,3225918719,GB
+3225918720,3225920767,SE
+3225920768,3225921023,GB
+3225921024,3225921791,SE
+3225921792,3225922047,GB
+3225922048,3225923839,SE
+3225923840,3225924095,GB
+3225924096,3225930239,SE
+3225930240,3225930495,FR
+3225930496,3225932799,SE
+3225932800,3225933055,IT
+3225933056,3225935359,SE
+3225935360,3225935615,US
+3225935616,3225937407,SE
+3225937408,3225937663,US
+3225937664,3225938431,SE
+3225938432,3225938687,US
+3225938688,3225944063,SE
3225944064,3225977855,TW
3225977856,3225978111,CH
3225978112,3226008831,TW
@@ -73898,7 +75799,7 @@
3227909632,3227909887,AU
3227910400,3227910655,AT
3227910656,3227911679,US
-3227911680,3227912191,HU
+3227911680,3227912191,EU
3227912192,3227912447,GB
3227912448,3227912703,ZA
3227912704,3227912959,US
@@ -74232,9 +76133,15 @@
3229120768,3229151487,US
3229151488,3229151743,SE
3229151744,3229155327,US
-3229155328,3229171455,SE
+3229155328,3229155839,SE
+3229155840,3229156095,ES
+3229156096,3229171455,SE
3229171456,3229171711,MT
-3229171712,3229219583,SE
+3229171712,3229200895,SE
+3229200896,3229201151,DE
+3229201152,3229201663,SE
+3229201664,3229201919,DK
+3229201920,3229219583,SE
3229219584,3229219839,EE
3229219840,3229220863,SE
3229220864,3229245439,GB
@@ -74296,11 +76203,13 @@
3229473792,3229474047,GB
3229474048,3229474303,DE
3229474304,3229475839,GB
-3229475840,3229478911,DE
+3229475840,3229478399,DE
+3229478400,3229478655,IE
+3229478656,3229478911,DE
3229478912,3229480959,IE
3229480960,3229481471,DE
3229481472,3229482239,GB
-3229482240,3229483007,DE
+3229482240,3229483007,IE
3229483008,3229499647,FI
3229499648,3229500671,US
3229548544,3229679615,US
@@ -74320,7 +76229,9 @@
3229749760,3229750015,BE
3229750016,3229764063,FI
3229764064,3229764095,AX
-3229764096,3229810687,FI
+3229764096,3229808639,FI
+3229808640,3229808647,AX
+3229808648,3229810687,FI
3229810688,3229814015,US
3229814016,3229814271,AU
3229814272,3229815807,US
@@ -75281,14 +77192,34 @@
3231896576,3231897599,RU
3231897600,3231898623,IE
3231898624,3231899647,SE
-3231899648,3231903743,UA
-3231903744,3231907839,RU
+3231899648,3231900671,UA
+3231900672,3231901439,DE
+3231901440,3231901695,BG
+3231901696,3231903743,UA
+3231903744,3231905791,RU
+3231905792,3231906047,PL
+3231906048,3231907839,RU
3231907840,3231916031,US
3231916032,3231948799,FI
3231973376,3232038911,AT
-3232038912,3232079871,SE
+3232038912,3232039167,SE
+3232039168,3232039423,DK
+3232039424,3232039679,IT
+3232039680,3232049151,SE
+3232049152,3232049407,GB
+3232049408,3232060415,SE
+3232060416,3232060671,IE
+3232060672,3232066559,SE
+3232066560,3232066815,NO
+3232066816,3232079871,SE
3232079872,3232080895,GB
-3232080896,3232092671,SE
+3232080896,3232083455,SE
+3232083456,3232083711,DE
+3232083712,3232089087,SE
+3232089088,3232089343,ES
+3232089344,3232090367,SE
+3232090368,3232090623,IT
+3232090624,3232092671,SE
3232092672,3232093183,GB
3232093184,3232093439,US
3232093440,3232094207,GB
@@ -75297,7 +77228,11 @@
3232095232,3232096255,GB
3232096256,3232097279,SE
3232097280,3232097535,IT
-3232097536,3232104447,SE
+3232097536,3232098047,SE
+3232098048,3232098303,FR
+3232098304,3232100095,SE
+3232100096,3232100351,IE
+3232100352,3232104447,SE
3232104448,3232107519,DE
3232107520,3232108543,RU
3232108544,3232129023,DE
@@ -75352,7 +77287,21 @@
3232706560,3232706815,US
3232710656,3232718847,US
3232727040,3232759807,US
-3232759808,3232825343,SE
+3232759808,3232774911,SE
+3232774912,3232775167,IE
+3232775168,3232794879,SE
+3232794880,3232795135,DE
+3232795136,3232802559,SE
+3232802560,3232802815,DK
+3232802816,3232803071,SE
+3232803072,3232803327,IE
+3232803328,3232804607,SE
+3232804608,3232804863,IT
+3232804864,3232812799,SE
+3232812800,3232813055,ES
+3232813056,3232820223,SE
+3232820224,3232820479,IE
+3232820480,3232825343,SE
3233285120,3233285375,US
3233480704,3233484799,US
3233484800,3233488895,ES
@@ -76160,7 +78109,6 @@
3238007040,3238010879,NL
3238010880,3238017023,CH
3238017024,3238018303,DK
-3238018304,3238018559,TR
3238018560,3238018815,FR
3238018816,3238019071,DE
3238019072,3238035455,PL
@@ -76790,7 +78738,6 @@
3239783424,3239783679,DK
3239783680,3239783935,CH
3239783936,3239784191,DE
-3239784192,3239784447,UA
3239784448,3239788543,DE
3239788544,3239789055,EU
3239789568,3239790079,FR
@@ -77204,7 +79151,7 @@
3240282112,3240282239,DE
3240282240,3240282367,UA
3240282368,3240282495,RO
-3240282496,3240282879,SE
+3240282624,3240282879,SE
3240282880,3240283007,UA
3240283008,3240283391,PL
3240283392,3240283647,TR
@@ -77299,7 +79246,6 @@
3240577280,3240577535,RO
3240577536,3240577791,DE
3240577792,3240578559,UA
-3240578560,3240578815,CH
3240578816,3240579071,IL
3240579072,3240587263,GB
3240587264,3240587519,NL
@@ -77474,7 +79420,6 @@
3240813568,3240814591,PL
3240814592,3240818687,IT
3240818688,3240820735,NL
-3240820736,3240820799,EU
3240820800,3240820831,RU
3240820832,3240827135,IT
3240827136,3240827391,FR
@@ -77535,8 +79480,7 @@
3240884224,3240886271,UA
3240886272,3240952071,SE
3240952072,3240952079,IE
-3240952080,3240952087,GB
-3240952088,3240952095,SE
+3240952080,3240952095,SE
3240952096,3240952127,US
3240952128,3240954495,SE
3240954496,3240954623,DE
@@ -77765,7 +79709,9 @@
3241869312,3241934847,PL
3241934848,3242196991,GB
3242196992,3242393599,FI
-3242393600,3242459135,NL
+3242393600,3242394471,NL
+3242394472,3242394479,DE
+3242394480,3242459135,NL
3242459136,3242467327,BG
3242467328,3242475519,HU
3242475520,3242483711,LV
@@ -78298,7 +80244,6 @@
3244906752,3244907007,SA
3244907008,3244907263,FR
3244907264,3244907519,RO
-3244907520,3244907775,GB
3244907776,3244908287,RU
3244908288,3244908543,NL
3244908544,3244908799,RU
@@ -78491,7 +80436,6 @@
3245001728,3245002751,IL
3245002752,3245003263,PL
3245003264,3245003519,SE
-3245003520,3245003775,CH
3245003776,3245004799,RU
3245004800,3245005823,PL
3245005824,3245006847,UA
@@ -78506,7 +80450,7 @@
3245017088,3245018111,PL
3245018112,3245019135,RU
3245019136,3245020159,SC
-3245020160,3245021183,CZ
+3245020160,3245021183,RU
3245021184,3245022207,UA
3245022208,3245023231,NO
3245023232,3245024255,PL
@@ -78649,7 +80593,6 @@
3245136384,3245136639,GB
3245136640,3245136895,EU
3245136896,3245137151,PL
-3245137152,3245137407,IT
3245137408,3245137663,DE
3245137664,3245137919,SE
3245137920,3245138431,DK
@@ -79010,7 +80953,9 @@
3245903032,3245903039,GB
3245903040,3245903959,IE
3245903960,3245903967,FR
-3245903968,3245904199,IE
+3245903968,3245904087,IE
+3245904088,3245904095,GB
+3245904096,3245904199,IE
3245904200,3245904207,GB
3245904208,3245906367,IE
3245906368,3245906431,GB
@@ -79508,7 +81453,9 @@
3247714304,3247716351,CH
3247716352,3247717887,ES
3247717888,3247718399,CH
-3247718400,3247769599,ES
+3247718400,3247742975,ES
+3247742976,3247751167,DE
+3247751168,3247769599,ES
3247769600,3247771647,DE
3247771648,3247775743,ES
3247775744,3247779647,DE
@@ -79531,7 +81478,6 @@
3247833088,3247865855,RU
3247865856,3247871999,GB
3247872000,3247875327,NL
-3247875328,3247875583,TR
3247875584,3247876095,DE
3247876096,3247876351,PL
3247876352,3247876607,FR
@@ -79660,8 +81606,8 @@
3248790784,3248791039,PL
3248791040,3248791295,BE
3248791296,3248791551,DE
-3248791552,3248792511,GB
-3248792512,3248796607,EU
+3248791552,3248792527,GB
+3248792528,3248796607,EU
3248796608,3248796863,GB
3248796864,3248798975,EU
3248798976,3248799231,GB
@@ -79928,17 +81874,57 @@
3249731584,3249732607,UA
3249732608,3249733631,IT
3249733632,3249799167,CZ
-3249799168,3249865727,SE
-3249865728,3249866751,GB
-3249866752,3249910783,SE
+3249799168,3249829887,SE
+3249829888,3249830143,GB
+3249830144,3249830399,SE
+3249830400,3249830655,IT
+3249830656,3249850623,SE
+3249850624,3249850879,GB
+3249850880,3249863679,SE
+3249863680,3249863935,ES
+3249863936,3249865471,SE
+3249865472,3249866751,GB
+3249866752,3249868543,SE
+3249868544,3249868799,DE
+3249868800,3249871103,SE
+3249871104,3249871359,NO
+3249871360,3249871615,SE
+3249871616,3249871871,NO
+3249871872,3249872383,SE
+3249872384,3249872639,GB
+3249872640,3249910783,SE
3249910784,3249912319,GB
3249912320,3249931007,SE
3249931008,3249931263,GB
3249931264,3249932031,SE
3249932032,3249934335,GB
-3249934336,3249968127,SE
+3249934336,3249967615,SE
+3249967616,3249967871,GB
+3249967872,3249968127,SE
3249968128,3249969151,FR
-3249969152,3250061311,SE
+3249969152,3249971199,SE
+3249971200,3249971455,IT
+3249971456,3249974527,SE
+3249974528,3249974783,ES
+3249974784,3249976063,SE
+3249976064,3249976319,FR
+3249976320,3249976831,SE
+3249976832,3249977087,GB
+3249977088,3249991679,SE
+3249991680,3249991935,US
+3249991936,3249995263,SE
+3249995264,3249995519,GB
+3249995520,3249997055,SE
+3249997056,3249997311,US
+3249997312,3250000127,SE
+3250000128,3250000383,GB
+3250000384,3250007295,SE
+3250007296,3250007551,GB
+3250007552,3250031359,SE
+3250031360,3250031615,US
+3250031616,3250035455,SE
+3250035456,3250035711,US
+3250035712,3250061311,SE
3250061312,3250061635,FI
3250061636,3250061639,AX
3250061640,3250083643,FI
@@ -80137,7 +82123,6 @@
3250692096,3250692351,NO
3250692352,3250692607,NL
3250692608,3250693375,BG
-3250693376,3250693631,IE
3250694400,3250694655,GB
3250694656,3250694911,SK
3250694912,3250695167,NL
@@ -80147,7 +82132,7 @@
3250697728,3250697983,BG
3250697984,3250698239,IT
3250698240,3250698751,GR
-3250698752,3250699775,GB
+3250699264,3250699775,GB
3250699776,3250700287,DE
3250700288,3250708479,UA
3250708480,3250716671,KZ
@@ -80517,8 +82502,7 @@
3251237888,3251238911,DK
3251238912,3251239935,FR
3251239936,3251240959,US
-3251240960,3251241215,DE
-3251241216,3251243007,GB
+3251240960,3251243007,GB
3251243008,3251245055,BE
3251245056,3251245311,DE
3251245312,3251245567,BE
@@ -80536,12 +82520,7 @@
3251248640,3251248895,DE
3251248896,3251249151,GB
3251249152,3251251199,NL
-3251251200,3251251455,PT
-3251251456,3251251711,GB
-3251251712,3251251967,CH
-3251251968,3251252223,BG
-3251252224,3251252479,AT
-3251252480,3251252735,NL
+3251251200,3251252735,EU
3251252736,3251256831,CH
3251256832,3251257343,GB
3251257344,3251259903,BE
@@ -80661,7 +82640,9 @@
3251734528,3251734783,NL
3251734784,3251765247,FI
3251765248,3251765503,NL
-3251765504,3251774207,FI
+3251765504,3251766663,FI
+3251766664,3251766671,AX
+3251766672,3251774207,FI
3251774208,3251774463,DE
3251774464,3251783423,FI
3251783424,3251783679,GB
@@ -80783,7 +82764,9 @@
3252407776,3252407791,GH
3252407792,3252407807,NO
3252407808,3252407999,GN
-3252408000,3252408159,NO
+3252408000,3252408063,NO
+3252408064,3252408079,ML
+3252408080,3252408159,NO
3252408160,3252408191,GQ
3252408192,3252408319,NO
3252408320,3252408327,MW
@@ -80815,7 +82798,9 @@
3252408856,3252408863,CM
3252408864,3252408871,LR
3252408872,3252408879,CI
-3252408880,3252409103,LT
+3252408880,3252409023,LT
+3252409024,3252409039,TZ
+3252409040,3252409103,LT
3252409104,3252409111,SD
3252409112,3252409119,LT
3252409120,3252409127,NG
@@ -80891,20 +82876,21 @@
3252414656,3252414991,LT
3252414992,3252414999,IQ
3252415000,3252415015,LT
-3252415016,3252415095,IQ
+3252415016,3252415031,IQ
+3252415032,3252415039,LT
+3252415040,3252415095,IQ
3252415096,3252415103,LT
3252415104,3252415127,IQ
3252415128,3252415135,LT
3252415136,3252415159,IQ
3252415160,3252415167,BE
3252415168,3252415231,IQ
-3252415232,3252415487,LT
-3252415488,3252415743,IQ
+3252415232,3252415743,LT
3252415744,3252415775,GB
3252415776,3252415967,LT
3252415968,3252415999,CM
-3252416000,3252416831,LT
-3252416832,3252416927,GN
+3252416000,3252416895,LT
+3252416896,3252416927,GN
3252416928,3252416959,LT
3252416960,3252417023,GN
3252417024,3252417279,LT
@@ -80941,9 +82927,7 @@
3252419360,3252419423,GH
3252419424,3252419839,LT
3252419840,3252419879,IQ
-3252419880,3252419903,LT
-3252419904,3252419911,IQ
-3252419912,3252419919,LT
+3252419880,3252419919,LT
3252419920,3252419927,IQ
3252419928,3252419935,LT
3252419936,3252419943,IQ
@@ -80956,9 +82940,7 @@
3252420120,3252420143,IQ
3252420144,3252420191,LT
3252420192,3252420223,IQ
-3252420224,3252420263,LT
-3252420264,3252420271,IQ
-3252420272,3252420351,LT
+3252420224,3252420351,LT
3252420352,3252420415,IQ
3252420416,3252420431,GB
3252420432,3252420447,LT
@@ -81001,7 +82983,7 @@
3252430520,3252430527,LT
3252430528,3252430543,BF
3252430544,3252430559,BJ
-3252430560,3252430591,BF
+3252430560,3252430591,LT
3252430592,3252430847,GN
3252430848,3252431359,MW
3252431360,3252431871,LT
@@ -81032,13 +83014,14 @@
3252435344,3252435359,BF
3252435360,3252435375,LT
3252435376,3252435415,GN
-3252435416,3252435423,CD
-3252435424,3252435455,LT
+3252435416,3252435447,CD
+3252435448,3252435455,LT
3252435456,3252435711,TZ
3252435712,3252435855,GH
3252435856,3252435871,MR
3252435872,3252435887,GH
-3252435888,3252435919,BW
+3252435888,3252435903,LT
+3252435904,3252435919,BW
3252435920,3252435935,BF
3252435936,3252435951,CF
3252435952,3252435967,LT
@@ -81054,8 +83037,8 @@
3252436352,3252436383,GN
3252436384,3252436399,LR
3252436400,3252436407,SL
-3252436408,3252436431,ML
-3252436432,3252436447,LT
+3252436408,3252436415,ML
+3252436416,3252436447,LT
3252436448,3252436479,ER
3252436480,3252436991,LT
3252436992,3252437503,NG
@@ -81065,9 +83048,7 @@
3252438528,3252438783,CM
3252438784,3252439039,LT
3252439040,3252439055,BJ
-3252439056,3252439071,LT
-3252439072,3252439079,BJ
-3252439080,3252439263,LT
+3252439056,3252439263,LT
3252439264,3252439271,SN
3252439272,3252439287,LT
3252439288,3252439295,SN
@@ -81185,7 +83166,6 @@
3252510720,3252514815,FR
3252514816,3252515071,SI
3252515072,3252515327,GB
-3252515328,3252515583,DE
3252515584,3252515839,SI
3252515840,3252516095,CH
3252516096,3252516351,FR
@@ -81362,7 +83342,36 @@
3253265920,3253270527,RU
3253270528,3253271551,BY
3253271552,3253338111,RU
-3253338112,3253469183,SE
+3253338112,3253380863,SE
+3253380864,3253381119,IT
+3253381120,3253383935,SE
+3253383936,3253384191,NO
+3253384192,3253409791,SE
+3253409792,3253410047,GB
+3253410048,3253412351,SE
+3253412352,3253412607,US
+3253412608,3253416447,SE
+3253416448,3253416703,GB
+3253416704,3253428223,SE
+3253428224,3253428479,DE
+3253428480,3253429759,SE
+3253429760,3253430015,ES
+3253430016,3253433087,SE
+3253433088,3253433343,DE
+3253433344,3253434111,SE
+3253434112,3253434367,GB
+3253434368,3253434623,IT
+3253434624,3253434879,SE
+3253434880,3253435135,IT
+3253435136,3253440511,SE
+3253440512,3253440767,FR
+3253440768,3253453311,SE
+3253453312,3253453567,NO
+3253453568,3253454079,SE
+3253454080,3253454335,GB
+3253454336,3253460735,SE
+3253460736,3253460991,IT
+3253460992,3253469183,SE
3253469184,3253471231,AO
3253471232,3253534719,PT
3253534720,3253600255,GB
@@ -81793,6 +83802,8 @@
3254785280,3254785535,KZ
3254785536,3254785791,DK
3254785792,3254786047,LU
+3254786304,3254786815,AT
+3254786816,3254787071,SM
3254796288,3254797311,SE
3254797312,3254798335,RU
3254798336,3254799359,AT
@@ -82379,7 +84390,7 @@
3255401472,3255412479,DE
3255412480,3255412735,RO
3255412736,3255413247,DE
-3255413248,3255413759,LV
+3255413248,3255413503,LV
3255413760,3255414271,GB
3255414272,3255414527,TR
3255414528,3255414783,LV
@@ -82503,11 +84514,17 @@
3255660544,3255666431,NL
3255666432,3255666687,DE
3255666688,3255697407,NL
-3255697408,3255739647,SE
+3255697408,3255710719,SE
+3255710720,3255710975,ES
+3255710976,3255724543,SE
+3255724544,3255725055,US
+3255725056,3255725311,ES
+3255725312,3255739647,SE
3255739648,3255739903,GB
3255739904,3255743231,SE
3255743232,3255743487,IT
-3255743488,3255745535,SE
+3255743488,3255743743,DE
+3255743744,3255745535,SE
3255745536,3255746047,DK
3255746048,3255762943,SE
3255762944,3255791615,DE
@@ -82581,7 +84598,6 @@
3256413184,3256413695,UA
3256413696,3256414207,PL
3256414208,3256414719,RU
-3256414720,3256415231,DE
3256415232,3256415743,PL
3256415744,3256416255,UA
3256416256,3256416767,RS
@@ -82684,7 +84700,8 @@
3256699136,3256699391,NL
3256699392,3256700415,GB
3256700416,3256700671,NL
-3256700672,3256701183,EU
+3256700672,3256700927,FR
+3256700928,3256701183,EU
3256701184,3256701439,BE
3256701440,3256701695,GB
3256701696,3256705279,EU
@@ -82816,7 +84833,6 @@
3257401344,3257466879,CH
3257466880,3257467135,DE
3257467136,3257467391,GB
-3257467392,3257467903,NL
3257467904,3257468927,IT
3257468928,3257469183,EU
3257469184,3257469439,IT
@@ -84093,11 +86109,27 @@
3259228160,3259236351,RU
3259236352,3259236863,SE
3259236864,3259237119,CH
-3259237120,3259269375,SE
+3259237120,3259237887,SE
+3259237888,3259238143,FR
+3259238144,3259248127,SE
+3259248128,3259248383,GB
+3259248384,3259258623,SE
+3259258624,3259258879,ES
+3259258880,3259262719,SE
+3259262720,3259262975,DK
+3259262976,3259269375,SE
3259269376,3259269631,FR
-3259269632,3259292415,SE
+3259269632,3259276287,SE
+3259276288,3259276543,ES
+3259276544,3259285759,SE
+3259285760,3259286015,GB
+3259286016,3259290879,SE
+3259290880,3259291135,US
+3259291136,3259292415,SE
3259292416,3259292671,IT
-3259292672,3259301887,SE
+3259292672,3259297535,SE
+3259297536,3259297791,GB
+3259297792,3259301887,SE
3259301888,3259302143,DE
3259302144,3259302399,AE
3259302400,3259303423,CH
@@ -84201,13 +86233,19 @@
3259367424,3259432959,GB
3259432960,3259435263,SE
3259435264,3259435519,IT
-3259435520,3259457279,SE
+3259435520,3259438079,SE
+3259438080,3259438335,ES
+3259438336,3259457279,SE
3259457280,3259457535,IT
3259457536,3259460351,SE
3259460352,3259460607,DE
3259460608,3259465215,SE
3259465216,3259465471,KH
-3259465472,3259492351,SE
+3259465472,3259479807,SE
+3259479808,3259480063,DK
+3259480064,3259480831,SE
+3259480832,3259481087,ES
+3259481088,3259492351,SE
3259492352,3259493375,GB
3259493376,3259498495,SE
3259498496,3259506943,GB
@@ -84439,15 +86477,7 @@
3260809216,3260874751,PL
3260874752,3260875775,DK
3260875776,3260876031,GB
-3260876032,3260891391,DK
-3260891392,3260891647,IT
-3260891648,3260891903,NL
-3260891904,3260892159,ES
-3260892160,3260892415,GB
-3260892416,3260892671,FI
-3260892672,3260892927,PT
-3260892928,3260893183,SE
-3260893184,3260893439,AT
+3260876032,3260893439,DK
3260893440,3260894207,SE
3260894208,3260895231,AT
3260895232,3260898303,SE
@@ -87681,14 +89711,21 @@
3263138560,3263138815,AT
3263138816,3263168511,DE
3263168512,3263430655,GB
-3263430656,3263436799,SE
+3263430656,3263436543,SE
+3263436544,3263436799,ES
3263436800,3263437311,GB
-3263437312,3263461631,SE
+3263437312,3263458047,SE
+3263458048,3263458303,DE
+3263458304,3263459583,SE
+3263459584,3263459839,FR
+3263459840,3263461631,SE
3263461632,3263461887,AE
3263461888,3263477759,SE
3263477760,3263478015,JP
3263478016,3263478271,AU
-3263478272,3263496191,SE
+3263478272,3263478527,SE
+3263478528,3263478783,ES
+3263478784,3263496191,SE
3263496192,3263497983,EU
3263497984,3263498239,GB
3263498240,3263498751,EU
@@ -87919,7 +89956,7 @@
3264320000,3264320255,DE
3264320256,3264321023,GB
3264321024,3264321535,DE
-3264321536,3264321791,SE
+3264321536,3264321791,GB
3264321792,3264322047,RS
3264322048,3264322303,FR
3264322304,3264322559,RO
@@ -88017,7 +90054,9 @@
3264431104,3264431615,LI
3264431616,3264446207,CH
3264446208,3264446463,FR
-3264446464,3264463871,CH
+3264446464,3264447743,CH
+3264447744,3264447999,DE
+3264448000,3264463871,CH
3264463872,3264466943,LI
3264466944,3264483071,CH
3264483072,3264483327,LI
@@ -88408,7 +90447,6 @@
3265605376,3265605631,CZ
3265605632,3265605887,PL
3265605888,3265606143,FR
-3265606144,3265606399,RU
3265606400,3265606655,DE
3265606656,3265606911,AT
3265606912,3265607167,FR
@@ -88913,8 +90951,8 @@
3267648512,3267648767,DE
3267648768,3267649023,NL
3267649024,3267649279,RU
-3267649280,3267649295,DE
-3267649296,3267649311,EU
+3267649280,3267649303,DE
+3267649304,3267649311,EU
3267649312,3267649471,DE
3267649472,3267649791,EU
3267649792,3267650303,NL
@@ -88967,8 +91005,8 @@
3267661848,3267661855,EU
3267661856,3267661887,ES
3267661888,3267662023,EU
-3267662024,3267662031,ES
-3267662032,3267662047,EU
+3267662024,3267662039,ES
+3267662040,3267662047,EU
3267662048,3267662079,ES
3267662080,3267662847,EU
3267662848,3267662879,IE
@@ -89012,9 +91050,7 @@
3267667456,3267667967,GB
3267667968,3267670015,EU
3267670016,3267671551,ZA
-3267671552,3267671679,DE
-3267671680,3267671711,EU
-3267671712,3267671807,DE
+3267671552,3267671807,DE
3267671808,3267672063,NO
3267672064,3267672223,DE
3267672224,3267672255,EU
@@ -89030,9 +91066,7 @@
3267673024,3267673087,FR
3267673088,3267673439,DE
3267673440,3267673471,EU
-3267673472,3267673479,DE
-3267673480,3267673487,EU
-3267673488,3267673503,DE
+3267673472,3267673503,DE
3267673504,3267673599,EU
3267673600,3267673759,DE
3267673760,3267673807,EU
@@ -89215,9 +91249,7 @@
3268223232,3268224767,EU
3268224768,3268225023,US
3268225024,3268226367,EU
-3268226368,3268226663,GB
-3268226664,3268226671,EU
-3268226672,3268226815,GB
+3268226368,3268226815,GB
3268226816,3268227327,EU
3268227328,3268227391,GB
3268227392,3268227519,EU
@@ -89554,7 +91586,11 @@
3268935680,3269057535,GB
3269057536,3269058047,NL
3269058048,3269066751,GB
-3269066752,3269131555,SE
+3269066752,3269118087,SE
+3269118088,3269118091,GB
+3269118092,3269122343,SE
+3269122344,3269122351,GB
+3269122352,3269131555,SE
3269131556,3269131559,NO
3269131560,3269132287,SE
3269132288,3269197823,GR
@@ -90288,9 +92324,7 @@
3271821247,3271821247,AT
3271821248,3271847487,DE
3271847488,3271847495,US
-3271847496,3271851879,DE
-3271851880,3271851887,NL
-3271851888,3271884799,DE
+3271847496,3271884799,DE
3271884800,3271901183,UA
3271901184,3271909375,ES
3271909376,3271909887,RO
@@ -90731,7 +92765,9 @@
3272358912,3272359935,NL
3272359936,3272368127,RU
3272368128,3272376319,KZ
-3272376320,3272384511,SK
+3272376320,3272376447,SK
+3272376448,3272376463,SR
+3272376464,3272384511,SK
3272384512,3272392703,LT
3272392704,3272400895,AT
3272400896,3272400903,EU
@@ -92349,7 +94385,6 @@
3275108352,3275108863,FR
3275108864,3275109375,PL
3275109376,3275109887,UA
-3275109888,3275110399,DE
3275110400,3275110911,NL
3275110912,3275111423,GB
3275111424,3275111935,IT
@@ -92392,8 +94427,10 @@
3275423752,3275423775,EU
3275423776,3275423807,GB
3275423808,3275423871,EU
-3275423872,3275424719,GB
-3275424720,3275425791,EU
+3275423872,3275424751,GB
+3275424752,3275424767,EU
+3275424768,3275424895,GB
+3275424896,3275425791,EU
3275425792,3275427271,GB
3275427272,3275427279,EU
3275427280,3275427615,GB
@@ -92432,9 +94469,7 @@
3275450880,3275451231,EU
3275451232,3275451263,GB
3275451264,3275452415,EU
-3275452416,3275453423,GB
-3275453424,3275453439,EU
-3275453440,3275454127,GB
+3275452416,3275454127,GB
3275454128,3275454143,EU
3275454144,3275457023,GB
3275457024,3275457791,FK
@@ -92444,8 +94479,8 @@
3275460608,3275460863,HK
3275460864,3275463523,GB
3275463524,3275463527,EU
-3275463528,3275463583,GB
-3275463584,3275463679,EU
+3275463528,3275463631,GB
+3275463632,3275463679,EU
3275463680,3275464031,GB
3275464032,3275464047,IE
3275464048,3275468655,GB
@@ -92456,8 +94491,8 @@
3275468768,3275468799,IE
3275468800,3275469071,GB
3275469072,3275469087,IE
-3275469088,3275471871,GB
-3275471872,3275489279,EU
+3275469088,3275472895,GB
+3275472896,3275489279,EU
3275489280,3275497471,GB
3275497472,3275505663,DE
3275505664,3275506175,PL
@@ -92474,7 +94509,6 @@
3275510016,3275510079,SE
3275510080,3275510143,ES
3275510144,3275510207,FI
-3275510208,3275510271,SE
3275510336,3275510399,IE
3275510400,3275510463,NL
3275510464,3275510527,GB
@@ -92790,9 +94824,7 @@
3275808768,3275816959,UA
3275816960,3275818207,CH
3275818208,3275818215,DE
-3275818216,3275881335,CH
-3275881336,3275881343,DE
-3275881344,3275882495,CH
+3275818216,3275882495,CH
3275882496,3275884543,DE
3275884544,3275886591,IT
3275886592,3275888639,PL
@@ -92812,7 +94844,7 @@
3275902720,3275902975,UA
3275902976,3275903231,FR
3275903232,3275903487,GB
-3275903488,3275903999,DE
+3275903744,3275903999,DE
3275904000,3275904255,RU
3275904256,3275904511,CH
3275904512,3275904767,PL
@@ -93002,7 +95034,9 @@
3276019136,3276019151,GB
3276019152,3276019463,FR
3276019464,3276019471,GB
-3276019472,3276019503,FR
+3276019472,3276019479,FR
+3276019480,3276019487,GB
+3276019488,3276019503,FR
3276019504,3276019511,GB
3276019512,3276019535,FR
3276019536,3276019543,GB
@@ -93050,7 +95084,9 @@
3276022456,3276022463,GB
3276022464,3276022479,FR
3276022480,3276022495,GB
-3276022496,3276022519,FR
+3276022496,3276022503,FR
+3276022504,3276022511,GB
+3276022512,3276022519,FR
3276022520,3276022527,GB
3276022528,3276022567,FR
3276022568,3276022639,GB
@@ -93107,9 +95143,7 @@
3276026224,3276026319,FR
3276026320,3276026351,GB
3276026352,3276026423,FR
-3276026424,3276026431,GB
-3276026432,3276026439,FR
-3276026440,3276026447,GB
+3276026424,3276026447,GB
3276026448,3276026527,FR
3276026528,3276026535,GB
3276026536,3276026543,FR
@@ -93219,8 +95253,8 @@
3276031744,3276032007,FR
3276032008,3276032015,GB
3276032016,3276032023,FR
-3276032024,3276032031,GB
-3276032032,3276032055,FR
+3276032024,3276032047,GB
+3276032048,3276032055,FR
3276032056,3276032063,GB
3276032064,3276032103,FR
3276032104,3276032111,GB
@@ -93284,7 +95318,9 @@
3276038048,3276038111,GB
3276038112,3276038143,FR
3276038144,3276038399,GB
-3276038400,3276038703,FR
+3276038400,3276038663,FR
+3276038664,3276038671,GB
+3276038672,3276038703,FR
3276038704,3276038719,GB
3276038720,3276038735,FR
3276038736,3276038767,GB
@@ -93302,9 +95338,9 @@
3276039328,3276039343,GB
3276039344,3276039391,FR
3276039392,3276039423,GB
-3276039424,3276039551,FR
-3276039552,3276039567,GB
-3276039568,3276039647,FR
+3276039424,3276039615,FR
+3276039616,3276039631,GB
+3276039632,3276039647,FR
3276039648,3276039663,GB
3276039664,3276039967,FR
3276039968,3276040031,GB
@@ -93342,8 +95378,8 @@
3276041280,3276041311,GB
3276041312,3276041391,FR
3276041392,3276041407,GB
-3276041408,3276041487,FR
-3276041488,3276041503,GB
+3276041408,3276041495,FR
+3276041496,3276041503,GB
3276041504,3276041519,FR
3276041520,3276041535,GB
3276041536,3276041551,FR
@@ -93356,18 +95392,18 @@
3276041920,3276041951,GB
3276041952,3276041967,FR
3276041968,3276041983,GB
-3276041984,3276042031,FR
-3276042032,3276042143,GB
+3276041984,3276042039,FR
+3276042040,3276042143,GB
3276042144,3276042175,FR
3276042176,3276042191,GB
3276042192,3276042207,FR
3276042208,3276042239,GB
-3276042240,3276042767,FR
-3276042768,3276042815,GB
+3276042240,3276042775,FR
+3276042776,3276042815,GB
3276042816,3276042831,FR
3276042832,3276042847,GB
-3276042848,3276044303,FR
-3276044304,3276044319,GB
+3276042848,3276044311,FR
+3276044312,3276044319,GB
3276044320,3276044351,FR
3276044352,3276044359,GB
3276044360,3276044367,FR
@@ -95665,7 +97701,8 @@
3276479224,3276479279,FR
3276479280,3276479295,EU
3276479296,3276479343,FR
-3276479344,3276479359,EU
+3276479344,3276479351,GB
+3276479352,3276479359,EU
3276479360,3276479615,FR
3276479616,3276479647,EU
3276479648,3276479743,FR
@@ -95724,9 +97761,9 @@
3276494384,3276494415,EU
3276494416,3276495503,GB
3276495504,3276495519,EU
-3276495520,3276495679,GB
-3276495680,3276495775,EU
-3276495776,3276496639,GB
+3276495520,3276495763,GB
+3276495764,3276495767,EU
+3276495768,3276496639,GB
3276496640,3276496895,EU
3276496896,3276497151,DE
3276497152,3276497215,EU
@@ -96028,8 +98065,8 @@
3276536736,3276536743,HU
3276536744,3276536831,EU
3276536832,3276536895,ES
-3276536896,3276536967,EU
-3276536968,3276536991,ES
+3276536896,3276536959,EU
+3276536960,3276536991,ES
3276536992,3276537151,EU
3276537152,3276537215,AT
3276537216,3276537343,EU
@@ -96520,7 +98557,11 @@
3276877536,3276877551,AT
3276877552,3276878079,GB
3276878080,3276878335,BG
-3276878336,3276878591,GB
+3276878336,3276878399,GB
+3276878400,3276878421,FR
+3276878422,3276878431,GB
+3276878432,3276878495,FR
+3276878496,3276878591,GB
3276878592,3276878847,FR
3276878848,3276879359,ES
3276879360,3276879423,TR
@@ -96537,11 +98578,12 @@
3276884736,3276884991,PL
3276884992,3276886015,GB
3276886016,3276886271,RO
-3276886272,3276886527,GB
-3276886528,3276886943,DE
+3276886272,3276886943,DE
3276886944,3276886959,GB
-3276886960,3276886975,DE
-3276886976,3276887071,GB
+3276886960,3276886991,DE
+3276886992,3276887047,GB
+3276887048,3276887057,DE
+3276887058,3276887071,GB
3276887072,3276888063,DE
3276888064,3276888575,GB
3276888576,3276888831,AT
@@ -96574,15 +98616,16 @@
3276900040,3276900047,GB
3276900048,3276900351,CH
3276900352,3276900607,GB
-3276900608,3276901471,CH
-3276901472,3276901631,GB
+3276900608,3276901503,CH
+3276901504,3276901519,ES
+3276901520,3276901631,GB
3276901632,3276902151,CH
3276902152,3276902159,GB
3276902160,3276902191,CH
-3276902192,3276902207,GB
-3276902208,3276902271,CH
-3276902272,3276902399,GB
-3276902400,3276902583,SE
+3276902192,3276902399,GB
+3276902400,3276902407,SE
+3276902408,3276902431,GB
+3276902432,3276902583,SE
3276902584,3276902615,GB
3276902616,3276902639,SE
3276902640,3276902655,GB
@@ -96608,7 +98651,12 @@
3276906832,3276907551,NL
3276907552,3276907567,BE
3276907568,3276907643,NL
-3276907644,3276907775,GB
+3276907644,3276907647,GB
+3276907648,3276907663,NL
+3276907664,3276907679,BE
+3276907680,3276907695,GB
+3276907696,3276907743,NL
+3276907744,3276907775,GB
3276907776,3276908159,NL
3276908160,3276908175,CH
3276908176,3276908287,GB
@@ -96617,7 +98665,9 @@
3276909568,3276910591,NL
3276910592,3276910967,IT
3276910968,3276910975,GB
-3276910976,3276912615,IT
+3276910976,3276912319,IT
+3276912320,3276912383,GB
+3276912384,3276912615,IT
3276912616,3276912623,GB
3276912624,3276913183,IT
3276913184,3276913215,GB
@@ -96666,9 +98716,7 @@
3276923448,3276923455,DE
3276923456,3276924071,FR
3276924072,3276924079,GB
-3276924080,3276926751,FR
-3276926752,3276926783,GB
-3276926784,3276926847,FR
+3276924080,3276926847,FR
3276926848,3276931071,GB
3276931072,3276939263,KZ
3276939264,3276955647,DE
@@ -96701,7 +98749,6 @@
3277179392,3277179647,DE
3277179648,3277180159,BE
3277180160,3277180415,NL
-3277180416,3277180671,GB
3277180672,3277180927,FR
3277180928,3277181183,DE
3277181184,3277181439,PL
@@ -96873,7 +98920,9 @@
3277395968,3277452647,GB
3277452648,3277452655,DK
3277452656,3277455359,GB
-3277455360,3277463551,DE
+3277455360,3277456895,DE
+3277456896,3277457151,CH
+3277457152,3277463551,DE
3277463552,3277463807,GB
3277463808,3277464063,US
3277464064,3277464575,FR
@@ -97068,16 +99117,18 @@
3277881344,3277884175,IT
3277884176,3277884191,IR
3277884192,3277885439,IT
-3277885440,3277885727,LB
+3277885440,3277885695,IQ
+3277885696,3277885727,LB
3277885728,3277885951,IT
-3277885952,3277886207,LB
-3277886208,3277886463,IT
+3277885952,3277886463,LB
3277886464,3277886719,IQ
3277886720,3277886975,IR
3277886976,3277887487,IQ
3277887488,3277888255,IT
3277888256,3277888319,LB
-3277888320,3277889535,IT
+3277888320,3277889023,IT
+3277889024,3277889279,IQ
+3277889280,3277889535,IT
3277889536,3277897727,RU
3277897728,3277905919,IT
3277905920,3277914111,BG
@@ -99017,7 +101068,7 @@
3278944036,3278944036,US
3278944037,3278944037,FR
3278944038,3278944038,GB
-3278944039,3278944039,ES
+3278944039,3278944039,DE
3278944040,3278944040,FR
3278944041,3278944041,DE
3278944042,3278944042,FR
@@ -101761,7 +103812,6 @@
3281341440,3281341695,DE
3281341696,3281341951,PL
3281341952,3281342207,DK
-3281342208,3281342463,GB
3281342464,3281343231,DE
3281343232,3281343487,FI
3281343488,3281343743,GB
@@ -102204,7 +104254,6 @@
3283495680,3283495935,NL
3283495936,3283496191,BG
3283496192,3283496447,DE
-3283496448,3283496703,FR
3283496704,3283496959,LV
3283496960,3283497215,DE
3283497216,3283497471,GB
@@ -102271,12 +104320,10 @@
3283550624,3283550655,FR
3283550656,3283550719,GB
3283550720,3283552255,AT
-3283552256,3283552279,IT
-3283552280,3283552287,EU
-3283552288,3283552319,IT
+3283552256,3283552319,IT
3283552320,3283552351,EU
-3283552352,3283552415,IT
-3283552416,3283552447,EU
+3283552352,3283552431,IT
+3283552432,3283552447,EU
3283552448,3283552575,IT
3283552576,3283552639,DE
3283552640,3283552671,IT
@@ -103291,9 +105338,7 @@
3285457664,3285457759,IT
3285457760,3285457791,EU
3285457792,3285457919,IT
-3285457920,3285457967,GB
-3285457968,3285457983,EU
-3285457984,3285458111,GB
+3285457920,3285458111,GB
3285458112,3285458175,EU
3285458176,3285458943,GB
3285458944,3285458975,DK
@@ -103360,7 +105405,8 @@
3285463312,3285463319,BE
3285463320,3285463359,EU
3285463360,3285463455,BE
-3285463456,3285463519,EU
+3285463456,3285463487,EU
+3285463488,3285463519,GB
3285463520,3285463615,BE
3285463616,3285463647,FR
3285463648,3285463743,BE
@@ -103546,7 +105592,9 @@
3285485640,3285485647,SK
3285485648,3285485727,EU
3285485728,3285485743,SK
-3285485744,3285485799,EU
+3285485744,3285485751,EU
+3285485752,3285485759,SK
+3285485760,3285485799,EU
3285485800,3285485815,SK
3285485816,3285486591,EU
3285486592,3285487103,IT
@@ -103584,8 +105632,8 @@
3285493760,3285493775,ES
3285493776,3285493783,EU
3285493784,3285493887,ES
-3285493888,3285493967,EU
-3285493968,3285493983,ES
+3285493888,3285493951,EU
+3285493952,3285493983,ES
3285493984,3285493991,GB
3285493992,3285493999,EU
3285494000,3285494015,ES
@@ -103594,9 +105642,7 @@
3285494112,3285494783,IT
3285494784,3285495807,EU
3285495808,3285496319,DE
-3285496320,3285496335,ES
-3285496336,3285496351,EU
-3285496352,3285496383,ES
+3285496320,3285496383,ES
3285496384,3285496463,EU
3285496464,3285496471,ES
3285496472,3285496479,EU
@@ -103607,9 +105653,7 @@
3285496576,3285496607,EU
3285496608,3285497855,DE
3285497856,3285497887,EU
-3285497888,3285498031,DE
-3285498032,3285498047,EU
-3285498048,3285498079,DE
+3285497888,3285498079,DE
3285498080,3285498095,EU
3285498096,3285498111,DE
3285498112,3285498367,IT
@@ -103628,9 +105672,7 @@
3285500288,3285500415,CZ
3285500416,3285500927,GB
3285500928,3285501183,DK
-3285501184,3285501311,CZ
-3285501312,3285501319,EU
-3285501320,3285501327,CZ
+3285501184,3285501327,CZ
3285501328,3285501335,EU
3285501336,3285501343,CZ
3285501344,3285501375,GB
@@ -104570,7 +106612,8 @@
3285911552,3285912575,EU
3285912576,3285913087,GB
3285913088,3285913215,ES
-3285913216,3285913343,EU
+3285913216,3285913231,GB
+3285913232,3285913343,EU
3285913344,3285913599,GB
3285913600,3285915647,EU
3285915648,3285915903,GB
@@ -104614,10 +106657,12 @@
3285926408,3285926415,ES
3285926416,3285926431,GB
3285926432,3285926463,CH
-3285926464,3285926479,GB
-3285926480,3285926783,EU
-3285926784,3285926799,GB
-3285926800,3285926847,EU
+3285926464,3285926511,GB
+3285926512,3285926639,EU
+3285926640,3285926671,GB
+3285926672,3285926783,EU
+3285926784,3285926815,GB
+3285926816,3285926847,EU
3285926848,3285926911,GB
3285926912,3285927423,DE
3285927424,3285927679,GB
@@ -104633,8 +106678,8 @@
3285928320,3285928447,EU
3285928448,3285928959,ES
3285928960,3285929983,EU
-3285929984,3285930495,GB
-3285930496,3285930559,EU
+3285929984,3285930511,GB
+3285930512,3285930559,EU
3285930560,3285930575,ES
3285930576,3285930623,GB
3285930624,3285930631,BE
@@ -104643,8 +106688,8 @@
3285930656,3285930671,NL
3285930672,3285930679,BE
3285930680,3285930687,DE
-3285930688,3285930703,GB
-3285930704,3285930751,EU
+3285930688,3285930719,GB
+3285930720,3285930751,EU
3285930752,3285931007,GB
3285931008,3285932031,EU
3285932032,3285932287,NL
@@ -104673,8 +106718,8 @@
3285939072,3285939199,EU
3285939200,3285939711,ES
3285939712,3285940223,EU
-3285940224,3285940735,ES
-3285940736,3285941247,GB
+3285940224,3285940479,ES
+3285940480,3285941247,GB
3285941248,3285942655,EU
3285942656,3285942783,IR
3285942784,3285943039,ES
@@ -104692,8 +106737,8 @@
3285945344,3285945599,ES
3285945600,3285945663,EU
3285945664,3285945695,FR
-3285945696,3285945727,GB
-3285945728,3285945855,EU
+3285945696,3285945743,GB
+3285945744,3285945855,EU
3285945856,3285946111,GB
3285946112,3285946367,ES
3285946368,3285946879,GB
@@ -104714,13 +106759,17 @@
3285949952,3285950463,ES
3285950464,3285950719,GB
3285950720,3285950783,US
-3285950784,3285950975,EU
+3285950784,3285950799,GB
+3285950800,3285950959,EU
+3285950960,3285950975,GB
3285950976,3285951231,NL
3285951232,3285951487,IT
-3285951488,3285951615,EU
+3285951488,3285951503,GB
+3285951504,3285951615,EU
3285951616,3285951647,GB
3285951648,3285951679,ES
-3285951680,3285951743,EU
+3285951680,3285951695,GB
+3285951696,3285951743,EU
3285951744,3285951999,GB
3285952000,3285952255,IT
3285952256,3285952511,SA
@@ -104734,7 +106783,11 @@
3285956864,3285957631,PT
3285957632,3285957887,PL
3285957888,3285958143,GB
-3285958144,3285958847,EU
+3285958144,3285958655,EU
+3285958656,3285958671,GB
+3285958672,3285958783,EU
+3285958784,3285958799,GB
+3285958800,3285958847,EU
3285958848,3285958895,NL
3285958896,3285959039,GB
3285959040,3285959167,DE
@@ -104755,7 +106808,10 @@
3285967616,3285968383,BE
3285968384,3285968639,ES
3285968640,3285968895,PL
-3285968896,3285971199,EU
+3285968896,3285971007,EU
+3285971008,3285971023,GB
+3285971024,3285971183,EU
+3285971184,3285971199,GB
3285971200,3285971455,FR
3285971456,3285971711,DE
3285971712,3285971967,GB
@@ -104763,7 +106819,13 @@
3285972224,3285972479,EU
3285972480,3285972735,PL
3285972736,3285972991,FR
-3285972992,3285975039,GB
+3285972992,3285973095,GB
+3285973096,3285973247,EU
+3285973248,3285973767,GB
+3285973768,3285973791,EU
+3285973792,3285973823,GB
+3285973824,3285974015,EU
+3285974016,3285975039,GB
3285975040,3286106111,FR
3286106112,3286106687,EE
3286106688,3286106691,FI
@@ -104805,7 +106867,6 @@
3286313984,3286314495,CH
3286314496,3286315007,IL
3286315008,3286315519,UA
-3286315520,3286316031,DE
3286316032,3286316543,UA
3286316544,3286317055,NL
3286317056,3286317567,RU
@@ -104889,7 +106950,7 @@
3286423808,3286424063,CZ
3286424064,3286424319,LV
3286424320,3286424575,FR
-3286424576,3286424831,UA
+3286424576,3286424831,RU
3286424832,3286425087,TR
3286425088,3286425343,RU
3286425344,3286425599,IT
@@ -105358,8 +107419,7 @@
3287481344,3287482367,PL
3287482368,3287499279,DE
3287499280,3287499287,FR
-3287499288,3287499295,US
-3287499296,3287499439,DE
+3287499288,3287499439,DE
3287499440,3287499471,GB
3287499472,3287499487,DE
3287499488,3287499503,GB
@@ -105980,6 +108040,11 @@
3291205632,3291206143,ZA
3291206144,3291206399,AO
3291206400,3291206911,KE
+3291207168,3291207423,MG
+3291207424,3291207679,NG
+3291207680,3291207935,BW
+3291207936,3291208447,KE
+3291208448,3291208703,EG
3291217920,3291230207,ZA
3291230208,3291234303,GH
3291234304,3291242495,ZA
@@ -106053,7 +108118,6 @@
3291437568,3291437823,NA
3291437824,3291439103,ZA
3291447296,3291463679,CI
-3291480064,3291480319,MU
3291742208,3292004351,ZA
3300917248,3300921343,MU
3300925440,3300929535,MG
@@ -106182,9 +108246,12 @@
3302954240,3302954495,KE
3302954496,3302955007,ZA
3302955008,3302955263,LS
+3302955264,3302955519,UG
3305111552,3307208703,TN
+3307208704,3309305855,EG
3309305856,3310354431,ZA
3311403008,3312451583,ZA
+3312451584,3312975871,DZ
3312975872,3313500159,EG
3313500160,3313762303,MA
3313762304,3314024447,EG
@@ -106197,23 +108264,30 @@
3318218752,3318743039,DZ
3319529472,3319537663,ZM
3319537664,3319545855,UG
+3319545856,3319554047,SO
+3319554048,3319562239,KE
+3319562240,3319570431,LS
3319652352,3319660543,ZW
3319660544,3319791615,EG
3319791616,3320053759,MU
3320578048,3320643583,ZA
3320643584,3320709119,KE
3320709120,3320840191,ZA
+3321364480,3321430015,KE
+3321430016,3321495551,MZ
+3321692160,3321708543,NG
3321708544,3321724927,GH
3321724928,3321757695,MA
3321757696,3321790463,KE
3321790464,3321806847,LS
3321806848,3321823231,SD
3321823232,3321839615,NG
-3321839616,3321855999,MU
+3321839616,3321855999,GH
3321856000,3321860095,CV
3321860096,3321864191,ZA
3321864192,3321868287,NG
3321868288,3321872383,CG
+3321872384,3321876479,GM
3321954304,3321970687,US
3322019840,3322023935,US
3322023936,3322028031,CL
@@ -106318,7 +108392,9 @@
3324379136,3324380159,CA
3324380160,3324391423,US
3324395520,3324399615,US
-3324411904,3324579839,US
+3324411904,3324470271,US
+3324470272,3324471295,GB
+3324471296,3324579839,US
3324579840,3324583935,NZ
3324583936,3324588031,CL
3324592128,3324596223,US
@@ -107137,7 +109213,9 @@
3341778944,3341807615,US
3341807616,3341808639,CA
3341808640,3341828095,US
-3341844480,3341854551,US
+3341844480,3341854079,US
+3341854080,3341854207,SG
+3341854208,3341854551,US
3341854552,3341854559,SG
3341854560,3341863935,US
3341863936,3341864959,AG
@@ -107172,7 +109250,63 @@
3342605312,3342605567,US
3342605568,3342663679,CA
3342663680,3343007743,US
-3343024128,3343055871,US
+3343024128,3343046915,US
+3343046916,3343046919,GB
+3343046920,3343046927,IT
+3343046928,3343046939,US
+3343046940,3343046943,RU
+3343046944,3343046947,KW
+3343046948,3343046951,PT
+3343046952,3343046955,US
+3343046956,3343046959,IT
+3343046960,3343046963,BE
+3343046964,3343046967,US
+3343046968,3343046971,NL
+3343046972,3343046979,US
+3343046980,3343046983,GB
+3343046984,3343046987,US
+3343046988,3343046991,CA
+3343046992,3343046999,US
+3343047000,3343047003,RU
+3343047004,3343047011,US
+3343047012,3343047015,AU
+3343047016,3343047039,US
+3343047040,3343047047,CA
+3343047048,3343047079,US
+3343047080,3343047087,GR
+3343047088,3343047111,US
+3343047112,3343047127,SG
+3343047128,3343047143,US
+3343047144,3343047159,IT
+3343047160,3343047327,US
+3343047328,3343047343,IT
+3343047344,3343047423,US
+3343047424,3343047439,RU
+3343047440,3343047455,UA
+3343047456,3343047471,IE
+3343047472,3343047519,US
+3343047520,3343047535,IN
+3343047536,3343047599,US
+3343047600,3343047615,GB
+3343047616,3343047687,US
+3343047688,3343047695,CA
+3343047696,3343047727,US
+3343047728,3343047735,CA
+3343047736,3343047743,US
+3343047744,3343047751,AU
+3343047752,3343047759,BR
+3343047760,3343047791,US
+3343047792,3343047799,PL
+3343047800,3343047847,US
+3343047848,3343047855,IT
+3343047856,3343047863,US
+3343047864,3343047871,RU
+3343047872,3343047879,AU
+3343047880,3343047903,US
+3343047904,3343047911,AR
+3343047912,3343047935,US
+3343047936,3343047967,CA
+3343047968,3343055871,US
3343055872,3343056895,CA
3343056896,3343167487,US
3343167488,3343169535,CA
@@ -107226,9 +109360,7 @@
3344637952,3344642047,US
3344662528,3344670719,US
3344670720,3344671743,GP
-3344671744,3344673919,US
-3344673920,3344673983,GB
-3344673984,3344676863,US
+3344671744,3344676863,US
3344676864,3344678911,CA
3344678912,3344681983,US
3344681984,3344685055,CA
@@ -107309,9 +109441,30 @@
3346241536,3346243583,CA
3346243584,3346282495,US
3346282496,3346284543,PR
-3346333696,3346923519,US
+3346300928,3346323455,US
+3346323456,3346325503,CA
+3346325504,3346327551,US
+3346327552,3346328575,CA
+3346328576,3346481151,US
+3346497536,3346498559,CA
+3346498560,3346499583,US
+3346499584,3346501631,VI
+3346501632,3346520063,US
+3346520064,3346521087,CA
+3346521088,3346524159,US
+3346524160,3346525183,CA
+3346525184,3346528255,US
+3346528256,3346529279,PR
+3346529280,3346530303,CA
+3346530304,3346923519,US
3346923520,3346989055,CA
3346989056,3347005439,US
+3347021824,3347022847,CA
+3347022848,3347033087,US
+3347033088,3347034111,CA
+3347034112,3347039231,US
+3347039232,3347040255,DM
+3347040256,3347044351,US
3347054592,3349268479,US
3349268480,3349268991,CA
3349268992,3349273087,US
@@ -107487,7 +109640,9 @@
3352066048,3352067071,CA
3352067072,3352068095,US
3352068096,3352069119,CA
-3352069120,3352082431,US
+3352069120,3352069919,US
+3352069920,3352069935,CO
+3352069936,3352082431,US
3352082432,3352083455,JM
3352083456,3352088575,US
3352088576,3352090623,CA
@@ -108749,7 +110904,7 @@
3362529280,3362533375,PA
3362537472,3362545663,AR
3362545664,3362549759,PE
-3362549760,3362551807,AR
+3362549760,3362553855,AR
3362553856,3362557951,PY
3362562048,3362563071,BZ
3362563072,3362563199,PA
@@ -113799,7 +115954,7 @@
3419878144,3419878399,IN
3419878400,3419879423,GU
3419879424,3419880447,JP
-3419880448,3419881471,MY
+3419880448,3419881471,MM
3419881472,3419897855,PH
3419897856,3419899903,JP
3419899904,3419900159,FR
@@ -114031,7 +116186,9 @@
3423161480,3423161487,HK
3423161488,3423161613,US
3423161614,3423161621,CA
-3423161622,3423162303,US
+3423161622,3423162159,US
+3423162160,3423162167,MX
+3423162168,3423162303,US
3423162304,3423162311,GB
3423162312,3423162367,US
3423162368,3423163391,CA
@@ -114512,17 +116669,29 @@
3423652000,3423653887,CA
3423653888,3423705599,US
3423705600,3423705855,CA
-3423705856,3423797247,US
-3423797248,3423823359,CA
+3423705856,3423797503,US
+3423797504,3423823359,CA
3423823360,3423823871,US
3423823872,3423827711,CA
3423827712,3423827967,US
-3423827968,3423848447,CA
+3423827968,3423830271,CA
+3423830272,3423830527,US
+3423830528,3423838719,CA
+3423838720,3423838975,US
+3423838976,3423848447,CA
3423848448,3423849471,KN
-3423849984,3423858175,CA
+3423849984,3423850495,CA
+3423850496,3423850751,US
+3423850752,3423854335,CA
+3423854336,3423854591,US
+3423854592,3423858175,CA
3423858176,3423858687,US
-3423858688,3423862783,CA
-3423862784,3424334847,US
+3423858688,3423858943,CA
+3423858944,3423859455,US
+3423859456,3423859711,CA
+3423859712,3423859967,US
+3423859968,3423862527,CA
+3423862528,3424334847,US
3424334848,3424335871,CA
3424335872,3424378879,US
3424378880,3424379135,PR
@@ -114538,7 +116707,9 @@
3425830816,3425830831,US
3425830832,3425855231,CA
3425855232,3425855487,US
-3425855488,3425869167,CA
+3425855488,3425864711,CA
+3425864712,3425864719,US
+3425864720,3425869167,CA
3425869168,3425869183,US
3425869184,3425875391,CA
3425875392,3425875407,US
@@ -114560,9 +116731,11 @@
3426388992,3426617855,US
3426618368,3426618687,US
3426618688,3426618703,NZ
-3426618704,3426618911,US
-3426618912,3426618943,NZ
-3426618944,3426646015,US
+3426618704,3426618735,US
+3426618736,3426618751,NZ
+3426618752,3426618911,US
+3426618912,3426619071,NZ
+3426619072,3426646015,US
3426646016,3426647039,CA
3426647040,3426744319,US
3426744320,3426746367,CA
@@ -114674,8 +116847,7 @@
3427773696,3427773951,FR
3427773952,3427774719,US
3427774720,3427775231,DE
-3427775232,3427775999,US
-3427776000,3427776511,HK
+3427775232,3427776511,US
3427776512,3427776767,CZ
3427776768,3427777023,US
3427777024,3427777279,NL
@@ -114960,7 +117132,7 @@
3428646016,3428646079,CA
3428646080,3428646143,US
3428646144,3428646911,CA
-3428646912,3428739327,US
+3428679680,3428739327,US
3428739328,3428739343,GB
3428739344,3428743167,US
3428743168,3428744191,CA
@@ -115013,7 +117185,9 @@
3430703872,3430704127,PR
3430704128,3430705151,US
3430705152,3430706175,MX
-3430706176,3430747903,US
+3430706176,3430722303,US
+3430722304,3430722559,CA
+3430722560,3430747903,US
3430747904,3430748159,CA
3430748160,3430749951,US
3430749952,3430750207,CA
@@ -115387,7 +117561,9 @@
3437792280,3437792287,SE
3437792288,3437792415,US
3437792416,3437792423,AU
-3437792424,3437792735,US
+3437792424,3437792527,US
+3437792528,3437792535,MX
+3437792536,3437792735,US
3437792736,3437792743,CA
3437792744,3437792775,US
3437792776,3437792783,CA
@@ -115758,7 +117934,9 @@
3448563016,3448563031,GB
3448563032,3448569055,US
3448569056,3448569087,MX
-3448569088,3449001245,US
+3448569088,3448569735,US
+3448569736,3448569743,GB
+3448569744,3449001245,US
3449001246,3449001246,MC
3449001247,3449159679,US
3449159680,3449160703,CA
@@ -117289,10 +119467,7 @@
3461332736,3461332991,SG
3461332992,3461408767,US
3461410816,3461414911,CA
-3461414912,3461435647,US
-3461435648,3461435903,CA
-3461435904,3461436159,US
-3461436416,3461513215,US
+3461414912,3461513215,US
3461513216,3461513727,CA
3461513728,3461513983,BF
3461513984,3461514495,CA
@@ -117466,8 +119641,8 @@
3464128000,3464128255,DE
3464128256,3464129535,US
3464129536,3464130047,DE
-3464130048,3464167423,US
-3464167424,3464171775,CA
+3464130048,3464167679,US
+3464167680,3464171775,CA
3464171776,3464172031,US
3464172032,3464180735,CA
3464180736,3464184487,US
@@ -117484,8 +119659,11 @@
3464191808,3464191815,US
3464191816,3464191823,CA
3464191824,3464191831,US
-3464191832,3464191847,CA
-3464191848,3464195543,US
+3464191832,3464191839,CA
+3464191840,3464191911,US
+3464191912,3464191919,ES
+3464191920,3464191927,SG
+3464191928,3464195543,US
3464195544,3464195551,IT
3464195552,3464195887,US
3464195888,3464195895,PR
@@ -117634,7 +119812,9 @@
3466283328,3466283391,CA
3466283392,3466286103,US
3466286104,3466286111,DE
-3466286112,3466313727,US
+3466286112,3466290687,US
+3466290688,3466290943,CH
+3466290944,3466313727,US
3466313728,3466317823,CA
3466317824,3466489855,US
3466489856,3466490111,CA
@@ -118095,13 +120275,11 @@
3470150656,3470150911,CA
3470150912,3470151295,US
3470151296,3470151359,CA
-3470151360,3470151935,US
-3470151936,3470152703,CA
+3470151360,3470151679,US
+3470151680,3470152703,CA
3470152704,3470152959,US
3470152960,3470152975,CA
-3470152976,3470153983,US
-3470153984,3470154239,CA
-3470154240,3470184454,US
+3470152976,3470184454,US
3470184455,3470184458,LK
3470184459,3470184460,RU
3470184461,3470184476,US
@@ -118610,8 +120788,7 @@
3470362560,3470362623,CA
3470362624,3470362719,US
3470362720,3470362727,CA
-3470362728,3470362783,US
-3470362784,3470362791,AF
+3470362728,3470362791,US
3470362792,3470362799,SG
3470362800,3470362847,US
3470362848,3470362855,AR
@@ -118657,7 +120834,8 @@
3470645632,3470645655,US
3470645656,3470645663,RU
3470645664,3470645687,US
-3470645688,3470645703,ES
+3470645688,3470645695,ES
+3470645696,3470645703,NL
3470645704,3470645731,US
3470645732,3470645735,AU
3470645736,3470645739,CN
@@ -118713,8 +120891,7 @@
3470646608,3470646623,ZA
3470646624,3470646631,DE
3470646632,3470646639,BR
-3470646640,3470646663,US
-3470646664,3470646671,PL
+3470646640,3470646671,US
3470646672,3470646679,BR
3470646680,3470646687,CA
3470646688,3470646703,US
@@ -119080,7 +121257,9 @@
3476722528,3476722543,AU
3476722544,3476722591,US
3476722592,3476722607,GB
-3476722608,3476722759,US
+3476722608,3476722719,US
+3476722720,3476722727,CO
+3476722728,3476722759,US
3476722760,3476722767,IN
3476722768,3476722775,US
3476722776,3476722783,GB
@@ -119102,7 +121281,17 @@
3476725400,3476725415,CA
3476725416,3476725423,US
3476725424,3476725431,GB
-3476725432,3476732373,US
+3476725432,3476731909,US
+3476731910,3476731913,IN
+3476731914,3476732049,US
+3476732050,3476732053,IN
+3476732054,3476732073,US
+3476732074,3476732077,IN
+3476732078,3476732113,US
+3476732114,3476732117,IN
+3476732118,3476732341,US
+3476732342,3476732345,MX
+3476732346,3476732373,US
3476732374,3476732377,MX
3476732378,3476733603,US
3476733604,3476733604,MX
@@ -119128,7 +121317,9 @@
3478114304,3478118399,PE
3478118400,3478192127,US
3478192128,3478257663,CA
-3478257664,3478294527,US
+3478257664,3478261855,US
+3478261856,3478261887,SG
+3478261888,3478294527,US
3478294528,3478294543,GB
3478294544,3478323391,US
3478323392,3478323399,CA
@@ -120199,7 +122390,9 @@
3491780608,3491781631,EC
3491781632,3491826687,US
3491826688,3491826943,AN
-3491826944,3491921663,US
+3491826944,3491832575,US
+3491832576,3491832583,PR
+3491832584,3491921663,US
3491921664,3491921919,PR
3491921920,3491955711,US
3491955712,3491956735,CO
@@ -120299,7 +122492,9 @@
3493901952,3493901983,CA
3493901984,3493902215,US
3493902216,3493902223,CA
-3493902224,3493903551,US
+3493902224,3493902295,US
+3493902296,3493902303,NG
+3493902304,3493903551,US
3493903552,3493903567,KW
3493903568,3493914239,US
3493914240,3493914367,CA
@@ -120346,7 +122541,9 @@
3494101408,3494101415,CO
3494101416,3494101429,US
3494101430,3494101437,GB
-3494101438,3494102623,US
+3494101438,3494102481,US
+3494102482,3494102489,CA
+3494102490,3494102623,US
3494102624,3494102639,SB
3494102640,3494102687,US
3494102688,3494102701,PE
@@ -120472,9 +122669,7 @@
3494299728,3494299735,SC
3494299736,3494300367,US
3494300368,3494300383,TW
-3494300384,3494300927,US
-3494300928,3494301055,TW
-3494301056,3494301247,US
+3494300384,3494301247,US
3494301248,3494301311,SG
3494301312,3494301439,US
3494301440,3494301695,TW
@@ -120702,7 +122897,7 @@
3494744064,3494744399,US
3494744400,3494744407,AU
3494744408,3494744703,US
-3494744704,3494744711,DK
+3494744704,3494744711,DE
3494744712,3494745151,US
3494745152,3494745159,AU
3494745160,3494745303,US
@@ -120823,9 +123018,7 @@
3495098368,3495100415,CA
3495100416,3495120895,US
3495120896,3495122943,AG
-3495122944,3495136455,US
-3495136456,3495136463,IN
-3495136464,3495136471,US
+3495122944,3495136471,US
3495136472,3495136479,AR
3495136480,3495136495,US
3495136496,3495136503,IN
@@ -120884,13 +123077,19 @@
3495235824,3495235831,GB
3495235832,3495235903,US
3495235904,3495235911,CA
-3495235912,3495235991,US
-3495235992,3495235999,CA
-3495236000,3495236015,US
-3495236016,3495236023,GB
-3495236024,3495236367,US
+3495235912,3495235975,US
+3495235976,3495235983,VN
+3495235984,3495235999,US
+3495236000,3495236007,HK
+3495236008,3495236015,US
+3495236016,3495236031,GB
+3495236032,3495236247,US
+3495236248,3495236255,AZ
+3495236256,3495236367,US
3495236368,3495236375,CA
-3495236376,3495251967,US
+3495236376,3495236431,US
+3495236432,3495236439,IN
+3495236440,3495251967,US
3495251968,3495254015,CA
3495254016,3495260159,US
3495260160,3495261183,CA
@@ -121032,13 +123231,22 @@
3495547472,3495547479,GB
3495547480,3495547605,US
3495547606,3495547606,BD
-3495547607,3495548205,US
+3495547607,3495547633,US
+3495547634,3495547635,CO
+3495547636,3495548126,US
+3495548127,3495548129,NO
+3495548130,3495548205,US
3495548206,3495548207,ID
-3495548208,3495548544,US
+3495548208,3495548437,US
+3495548438,3495548438,ES
+3495548439,3495548544,US
3495548545,3495548545,BD
-3495548546,3495548549,US
+3495548546,3495548548,US
+3495548549,3495548549,ES
3495548550,3495548550,BD
-3495548551,3495548586,US
+3495548551,3495548558,US
+3495548559,3495548559,ES
+3495548560,3495548586,US
3495548587,3495548588,LK
3495548589,3495548635,US
3495548636,3495548637,BD
@@ -121072,11 +123280,9 @@
3495653376,3495654399,CA
3495654400,3495657551,US
3495657552,3495657567,GB
-3495657568,3495658015,US
-3495658016,3495658023,IN
-3495658024,3495658319,US
-3495658320,3495658327,IN
-3495658328,3495673855,US
+3495657568,3495658527,US
+3495658528,3495658559,FR
+3495658560,3495673855,US
3495673856,3495674623,GP
3495674624,3495674879,MF
3495674880,3495675903,VG
@@ -121198,9 +123404,7 @@
3496886448,3496886463,TR
3496886464,3496886495,US
3496886496,3496886503,CA
-3496886504,3496886511,US
-3496886512,3496886527,GB
-3496886528,3496886607,US
+3496886504,3496886607,US
3496886608,3496886623,CA
3496886624,3496886655,US
3496886656,3496886671,IN
@@ -121208,9 +123412,7 @@
3496886712,3496886727,AU
3496886728,3496886823,US
3496886824,3496886831,IN
-3496886832,3496886919,US
-3496886920,3496886927,PK
-3496886928,3496886935,US
+3496886832,3496886935,US
3496886936,3496886943,PK
3496886944,3496887135,US
3496887136,3496887167,AU
@@ -121367,7 +123569,9 @@
3497156864,3497156879,NL
3497156880,3497156983,US
3497156984,3497157006,DZ
-3497157007,3497160191,US
+3497157007,3497157375,US
+3497157376,3497158655,A2
+3497158656,3497160191,US
3497160192,3497160351,NL
3497160352,3497161215,US
3497161216,3497161343,HK
@@ -121573,17 +123777,21 @@
3500809992,3500809999,CA
3500810000,3500810247,US
3500810248,3500810255,CA
-3500810256,3500921279,US
+3500810256,3500812175,US
+3500812176,3500812183,GB
+3500812184,3500921279,US
3500921280,3500921311,AU
3500921312,3501146951,US
3501146952,3501146959,CA
3501146960,3501146975,GB
-3501146976,3501181703,US
+3501146976,3501147039,US
+3501147040,3501147071,CA
+3501147072,3501181703,US
3501181704,3501181711,AU
3501181712,3501181727,KR
3501181728,3501181743,US
-3501181744,3501181759,JP
-3501181760,3501182975,US
+3501181744,3501181791,JP
+3501181792,3501182975,US
3501182976,3501183007,SG
3501183008,3501183023,US
3501183024,3501183047,SG
@@ -121774,29 +123982,9 @@
3507101920,3507101935,IL
3507101936,3507290111,US
3507290112,3507355647,AR
-3507355648,3507479075,US
-3507479076,3507479076,CA
-3507479077,3507479079,US
-3507479080,3507479080,CA
-3507479081,3507479108,US
-3507479109,3507479109,CA
-3507479110,3507479154,US
-3507479155,3507479155,CA
-3507479156,3507479184,US
-3507479185,3507479185,CA
-3507479186,3507481766,US
-3507481767,3507481767,CA
-3507481768,3507482153,US
-3507482154,3507482155,CA
-3507482156,3507482197,US
-3507482198,3507482198,CA
-3507482199,3507482303,US
-3507482304,3507482304,CA
-3507482305,3507484047,US
-3507484048,3507484063,CA
-3507484064,3507485103,US
-3507485104,3507485119,CA
-3507485120,3507540015,US
+3507355648,3507470335,US
+3507470336,3507486719,CA
+3507486720,3507540015,US
3507540016,3507540031,IN
3507540032,3507585023,US
3507585024,3507598911,CA
@@ -122586,8 +124774,8 @@
3509779008,3509779039,IN
3509779040,3509822335,US
3509822336,3509822351,DE
-3509822352,3509825791,US
-3509825792,3509826303,CN
+3509822352,3509826047,US
+3509826048,3509826303,CN
3509826304,3509829503,US
3509829504,3509829535,GB
3509829536,3509830287,US
@@ -123316,7 +125504,9 @@
3512269824,3512270847,US
3512270848,3512336383,CA
3512336384,3512369151,US
-3512369152,3512385535,CA
+3512369152,3512378435,CA
+3512378436,3512378436,US
+3512378437,3512385535,CA
3512385536,3512397823,US
3512397824,3512399375,CA
3512399376,3512399383,US
@@ -123788,11 +125978,11 @@
3514007552,3514040319,CA
3514040320,3514367999,US
3514368000,3514433535,CA
-3514433536,3514583479,US
-3514583480,3514583487,PA
-3514583488,3514583535,US
+3514433536,3514583535,US
3514583536,3514583543,JE
-3514583544,3514587511,US
+3514583544,3514585359,US
+3514585360,3514585375,GB
+3514585376,3514587511,US
3514587512,3514587519,PA
3514587520,3514589439,US
3514589440,3514589695,GT
@@ -123932,7 +126122,9 @@
3517100620,3517100635,CA
3517100636,3517100648,US
3517100649,3517100668,CA
-3517100669,3517100811,US
+3517100669,3517100720,US
+3517100721,3517100730,CA
+3517100731,3517100811,US
3517100812,3517100829,GB
3517100830,3517101597,US
3517101598,3517101613,GB
@@ -124055,8 +126247,8 @@
3517416712,3517416727,US
3517416728,3517416735,CA
3517416736,3517416743,US
-3517416744,3517416775,CA
-3517416776,3517416783,US
+3517416744,3517416767,CA
+3517416768,3517416783,US
3517416784,3517416791,CA
3517416792,3517416799,US
3517416800,3517416823,CA
@@ -124377,9 +126569,7 @@
3518911744,3518911999,GB
3518912000,3518912511,US
3518912512,3518912767,IN
-3518912768,3518921447,US
-3518921448,3518921455,CN
-3518921456,3518929535,US
+3518912768,3518929535,US
3518929536,3518929599,CA
3518929600,3518995695,US
3518995696,3518995703,GB
@@ -124465,7 +126655,9 @@
3519412736,3519412751,RU
3519412752,3519412799,US
3519412800,3519412815,RU
-3519412816,3519413759,US
+3519412816,3519412999,US
+3519413000,3519413007,CY
+3519413008,3519413759,US
3519413760,3519414271,CA
3519414272,3519417071,US
3519417072,3519417075,PT
@@ -124532,9 +126724,7 @@
3519879768,3519879775,US
3519879776,3519879807,CA
3519879808,3519879815,US
-3519879816,3519879863,CA
-3519879864,3519879871,US
-3519879872,3519880767,CA
+3519879816,3519880767,CA
3519880768,3519880831,DE
3519880832,3519881375,CA
3519881376,3519881407,US
@@ -125050,7 +127240,9 @@
3521937261,3521937406,EG
3521937407,3521965055,US
3521965056,3521966079,DE
-3521966080,3522029439,US
+3521966080,3521989631,US
+3521989632,3521989887,A2
+3521989888,3522029439,US
3522029440,3522029503,FI
3522029504,3522029567,CA
3522029568,3522029823,US
@@ -125555,10 +127747,12 @@
3556984640,3556984647,DE
3556984648,3556984651,FR
3556984652,3556984655,DE
-3556984656,3556984663,FR
-3556984664,3556984671,DE
-3556984672,3556984719,FR
-3556984720,3556985663,DE
+3556984656,3556984719,FR
+3556984720,3556985127,DE
+3556985128,3556985135,ES
+3556985136,3556985207,DE
+3556985208,3556985215,ES
+3556985216,3556985663,DE
3556985664,3556985671,HU
3556985672,3556990975,DE
3556990976,3556999167,UA
@@ -125672,8 +127866,8 @@
3557336192,3557336255,EU
3557336256,3557336319,BE
3557336320,3557336575,EU
-3557336576,3557336663,BE
-3557336664,3557336703,EU
+3557336576,3557336671,BE
+3557336672,3557336703,EU
3557336704,3557336831,BE
3557336832,3557338111,EU
3557338112,3557338367,BE
@@ -125693,8 +127887,8 @@
3557340192,3557340927,BE
3557340928,3557341183,EU
3557341184,3557341439,BE
-3557341440,3557341471,EU
-3557341472,3557341527,BE
+3557341440,3557341455,EU
+3557341456,3557341527,BE
3557341528,3557341535,EU
3557341536,3557341551,BE
3557341552,3557341559,EU
@@ -125735,8 +127929,8 @@
3557360560,3557360575,JE
3557360576,3557360680,GB
3557360681,3557360687,JE
-3557360688,3557360863,GB
-3557360864,3557360895,JE
+3557360688,3557360871,GB
+3557360872,3557360895,JE
3557360896,3557360927,GB
3557360928,3557360943,JE
3557360944,3557360959,GB
@@ -125769,8 +127963,8 @@
3557363672,3557363679,JE
3557363680,3557364103,GB
3557364104,3557364107,JE
-3557364108,3557364135,GB
-3557364136,3557364223,JE
+3557364108,3557364143,GB
+3557364144,3557364223,JE
3557364224,3557364479,GB
3557364480,3557364495,JE
3557364496,3557364527,GB
@@ -125901,7 +128095,9 @@
3557860832,3557860847,FI
3557860848,3557860863,SE
3557860864,3557861119,NO
-3557861120,3557867519,SE
+3557861120,3557864799,SE
+3557864800,3557864831,FI
+3557864832,3557867519,SE
3557867520,3557875711,RU
3557875712,3557883903,DE
3557883904,3557892095,RU
@@ -125960,7 +128156,9 @@
3558155048,3558155055,A2
3558155056,3558155059,AF
3558155060,3558155063,DE
-3558155064,3558155135,A2
+3558155064,3558155103,A2
+3558155104,3558155119,DE
+3558155120,3558155135,A2
3558155136,3558155263,SD
3558155264,3558155391,ET
3558155392,3558155399,A2
@@ -126010,7 +128208,9 @@
3558158336,3558158847,SE
3558158848,3558159359,DE
3558159360,3558159519,AF
-3558159520,3558159871,A2
+3558159520,3558159807,A2
+3558159808,3558159839,DE
+3558159840,3558159871,A2
3558159872,3558160127,SL
3558160128,3558160383,DE
3558160384,3558161151,A2
@@ -126043,9 +128243,7 @@
3558196368,3558196415,IT
3558196416,3558196543,ES
3558196544,3558196607,IT
-3558196608,3558196719,ES
-3558196720,3558196727,IT
-3558196728,3558196735,ES
+3558196608,3558196735,ES
3558196736,3558203391,US
3558203392,3558211583,ES
3558211584,3558219775,GB
@@ -126084,17 +128282,13 @@
3558288320,3558288383,CH
3558288384,3558288423,US
3558288424,3558288447,GB
-3558288448,3558288471,US
-3558288472,3558288479,GB
-3558288480,3558288483,US
+3558288448,3558288483,US
3558288484,3558288487,GB
3558288488,3558288639,US
-3558288640,3558288671,GB
+3558288640,3558288671,BE
3558288672,3558288687,DE
3558288688,3558288895,BE
-3558288896,3558289087,FR
-3558289088,3558289103,GB
-3558289104,3558289111,FR
+3558288896,3558289111,FR
3558289112,3558289119,GB
3558289120,3558289151,FR
3558289152,3558289407,GB
@@ -126493,7 +128687,9 @@
3559088376,3559088379,GB
3559088380,3559089023,BE
3559089024,3559089027,GB
-3559089028,3559089351,BE
+3559089028,3559089079,BE
+3559089080,3559089087,GB
+3559089088,3559089351,BE
3559089352,3559089359,GB
3559089360,3559089407,BE
3559089408,3559089411,GB
@@ -126569,7 +128765,9 @@
3559092160,3559092160,GB
3559092161,3559092222,BE
3559092223,3559092223,GB
-3559092224,3559092287,BE
+3559092224,3559092271,BE
+3559092272,3559092279,GB
+3559092280,3559092287,BE
3559092288,3559092303,GB
3559092304,3559092311,BE
3559092312,3559092319,GB
@@ -126614,7 +128812,8 @@
3559093220,3559093239,BE
3559093240,3559093243,GB
3559093244,3559093511,BE
-3559093512,3559093567,GB
+3559093512,3559093535,GB
+3559093536,3559093567,BE
3559093568,3559093599,IT
3559093600,3559093663,BE
3559093664,3559093671,GB
@@ -126790,9 +128989,7 @@
3559490816,3559491071,ES
3559491072,3559491135,NL
3559491136,3559491167,ES
-3559491168,3559491327,NL
-3559491328,3559491359,ES
-3559491360,3559491439,NL
+3559491168,3559491439,NL
3559491440,3559491455,ES
3559491456,3559491647,NL
3559491648,3559491711,ES
@@ -126883,9 +129080,7 @@
3559877968,3559882751,LT
3559882752,3559890943,AZ
3559890944,3559899135,CH
-3559899136,3559899391,UA
-3559899392,3559899395,EE
-3559899396,3559899487,UA
+3559899136,3559899487,UA
3559899488,3559899519,EE
3559899520,3559899903,UA
3559899904,3559899907,EE
@@ -126938,8 +129133,8 @@
3559902240,3559902431,UA
3559902432,3559902463,EE
3559902464,3559902975,UA
-3559902976,3559903295,EE
-3559903296,3559903487,UA
+3559902976,3559903359,EE
+3559903360,3559903487,UA
3559903488,3559903999,EE
3559904000,3559904015,UA
3559904016,3559904023,EE
@@ -126966,8 +129161,8 @@
3559905300,3559905317,EE
3559905318,3559905319,LT
3559905320,3559905323,UA
-3559905324,3559905327,EE
-3559905328,3559905535,UA
+3559905324,3559905331,EE
+3559905332,3559905535,UA
3559905536,3559905623,EE
3559905624,3559905631,UA
3559905632,3559905695,EE
@@ -127428,8 +129623,7 @@
3560941124,3560941127,FR
3560941128,3560941131,DE
3560941132,3560941135,GB
-3560941136,3560941139,ES
-3560941140,3560941147,DE
+3560941136,3560941147,DE
3560941148,3560941151,IT
3560941152,3560941155,DK
3560941156,3560941159,ES
@@ -129721,8 +131915,9 @@
3562242048,3562258431,FR
3562258432,3562263975,NL
3562263976,3562263983,BE
-3562263984,3562283007,NL
-3562283008,3562291199,IT
+3562263984,3562274767,NL
+3562274768,3562274775,DE
+3562274776,3562283007,NL
3562291200,3562307583,GB
3562307584,3562315775,NL
3562315776,3562321231,GB
@@ -129915,9 +132110,7 @@
3563372544,3563380735,SA
3563380736,3563381951,GB
3563381952,3563381959,IT
-3563381960,3563382383,GB
-3563382384,3563382391,AU
-3563382392,3563382495,GB
+3563381960,3563382495,GB
3563382496,3563382503,AT
3563382504,3563382583,GB
3563382584,3563382587,AT
@@ -130159,10 +132352,14 @@
3564024104,3564024135,GB
3564024136,3564024143,IT
3564024144,3564027903,GB
-3564027904,3564041215,DE
+3564027904,3564036351,DE
+3564036352,3564039423,A2
+3564039424,3564039679,DE
+3564039680,3564041215,A2
3564041216,3564041727,RU
-3564041728,3564044031,DE
-3564044032,3564044287,GB
+3564041728,3564043263,A2
+3564043264,3564043519,DE
+3564043520,3564044287,A2
3564044288,3564052479,CZ
3564052480,3564060671,GB
3564060672,3564068863,RU
@@ -130191,7 +132388,9 @@
3564153200,3564153207,NL
3564153208,3564156415,SE
3564156416,3564156419,NO
-3564156420,3564156919,SE
+3564156420,3564156815,SE
+3564156816,3564156819,FI
+3564156820,3564156919,SE
3564156920,3564156927,FI
3564156928,3564157207,SE
3564157208,3564157215,NO
@@ -130637,8 +132836,8 @@
3564881232,3564881247,NL
3564881248,3564881343,GB
3564881344,3564881359,NL
-3564881360,3564881375,GB
-3564881376,3564881439,NL
+3564881360,3564881391,GB
+3564881392,3564881439,NL
3564881440,3564881455,GB
3564881456,3564881463,NL
3564881464,3564881471,GB
@@ -130837,8 +133036,8 @@
3564896256,3564904447,RU
3564904448,3564912639,DE
3564912640,3564920831,BG
-3564920832,3564922879,ES
-3564922880,3564929023,US
+3564920832,3564921855,ES
+3564921856,3564929023,US
3564929024,3564937215,AT
3564937216,3564945407,RS
3564945408,3564947175,GB
@@ -131057,7 +133256,9 @@
3565037568,3565037823,IE
3565037824,3565038591,GB
3565038592,3565038663,IE
-3565038664,3565039615,GB
+3565038664,3565038687,GB
+3565038688,3565038719,IE
+3565038720,3565039615,GB
3565039616,3565042175,IE
3565042176,3565043711,GB
3565043712,3565047807,AT
@@ -132839,15 +135040,7 @@
3572826112,3572891647,IT
3572891648,3572957175,FI
3572957176,3572957183,AX
-3572957184,3572975359,SE
-3572975360,3572975615,A2
-3572975616,3572980991,SE
-3572980992,3572981247,A2
-3572981248,3572984319,SE
-3572984320,3572984575,A2
-3572984576,3572986367,SE
-3572986368,3572986623,A2
-3572986624,3573022719,SE
+3572957184,3573022719,SE
3573022720,3573055487,RU
3573055488,3573088255,GB
3573088256,3573088263,CH
@@ -133914,14 +136107,14 @@
3576131584,3576135679,CH
3576135680,3576168447,DE
3576168448,3576233983,GB
-3576233984,3576236671,FR
-3576236672,3576236719,GB
+3576233984,3576236687,FR
+3576236688,3576236719,GB
3576236720,3576236743,FR
3576236744,3576236751,GB
3576236752,3576236775,FR
3576236776,3576236783,GB
-3576236784,3576236879,FR
-3576236880,3576236927,GB
+3576236784,3576236887,FR
+3576236888,3576236927,GB
3576236928,3576237063,FR
3576237064,3576237071,GB
3576237072,3576237087,FR
@@ -133948,9 +136141,7 @@
3576238512,3576238527,GB
3576238528,3576238559,FR
3576238560,3576238575,GB
-3576238576,3576238615,FR
-3576238616,3576238623,GB
-3576238624,3576238639,FR
+3576238576,3576238639,FR
3576238640,3576238655,GB
3576238656,3576238863,FR
3576238864,3576238879,GB
@@ -134003,9 +136194,7 @@
3576242320,3576242327,GB
3576242328,3576242335,FR
3576242336,3576242343,GB
-3576242344,3576243967,FR
-3576243968,3576243983,GB
-3576243984,3576244103,FR
+3576242344,3576244103,FR
3576244104,3576244111,GB
3576244112,3576244127,FR
3576244128,3576244143,GB
@@ -134065,7 +136254,9 @@
3576255408,3576255423,GB
3576255424,3576255431,FR
3576255432,3576255439,GB
-3576255440,3576255519,FR
+3576255440,3576255471,FR
+3576255472,3576255479,GB
+3576255480,3576255519,FR
3576255520,3576255527,GB
3576255528,3576255543,FR
3576255544,3576255551,GB
@@ -134105,9 +136296,7 @@
3576256896,3576256959,GB
3576256960,3576256991,FR
3576256992,3576257007,GB
-3576257008,3576257103,FR
-3576257104,3576257111,GB
-3576257112,3576257135,FR
+3576257008,3576257135,FR
3576257136,3576257151,GB
3576257152,3576257159,FR
3576257160,3576257167,GB
@@ -134120,9 +136309,7 @@
3576257376,3576257455,FR
3576257456,3576257471,GB
3576257472,3576257487,FR
-3576257488,3576257495,GB
-3576257496,3576257503,FR
-3576257504,3576257535,GB
+3576257488,3576257535,GB
3576257536,3576257551,FR
3576257552,3576257583,GB
3576257584,3576257631,FR
@@ -134137,10 +136324,8 @@
3576257888,3576257903,GB
3576257904,3576257975,FR
3576257976,3576258015,GB
-3576258016,3576258055,FR
-3576258056,3576258063,GB
-3576258064,3576258079,FR
-3576258080,3576258095,GB
+3576258016,3576258087,FR
+3576258088,3576258095,GB
3576258096,3576258167,FR
3576258168,3576258175,GB
3576258176,3576258351,FR
@@ -134248,8 +136433,8 @@
3576263744,3576263751,FR
3576263752,3576263759,GB
3576263760,3576263791,FR
-3576263792,3576263887,GB
-3576263888,3576263911,FR
+3576263792,3576263903,GB
+3576263904,3576263911,FR
3576263912,3576263919,GB
3576263920,3576264295,FR
3576264296,3576264319,GB
@@ -134445,8 +136630,8 @@
3577625208,3577625215,GB
3577625216,3577625231,EU
3577625232,3577625599,GB
-3577625600,3577625823,EU
-3577625824,3577626623,GB
+3577625600,3577625791,EU
+3577625792,3577626623,GB
3577626624,3577627135,FR
3577627136,3577627391,EU
3577627392,3577627647,GB
@@ -134487,17 +136672,11 @@
3577640720,3577640735,EU
3577640736,3577641151,FR
3577641152,3577641159,EU
-3577641160,3577641199,FR
-3577641200,3577641215,EU
-3577641216,3577641391,FR
+3577641160,3577641391,FR
3577641392,3577641399,EU
-3577641400,3577641423,FR
-3577641424,3577641983,EU
-3577641984,3577642023,GB
-3577642024,3577642031,EU
-3577642032,3577642111,GB
-3577642112,3577642175,EU
-3577642176,3577642239,GB
+3577641400,3577641439,FR
+3577641440,3577641983,EU
+3577641984,3577642239,GB
3577642240,3577642495,EU
3577642496,3577642623,FR
3577642624,3577642751,EU
@@ -134903,11 +137082,11 @@
3580200960,3580201983,LT
3580201984,3580203519,SE
3580203520,3580204543,RU
-3580204544,3580205055,SE
+3580204544,3580205055,NL
3580205056,3580207103,HR
3580207104,3580208127,SE
-3580208128,3580208639,EE
-3580208640,3580213247,SE
+3580208128,3580209151,EE
+3580209152,3580213247,SE
3580213248,3580214271,CH
3580214272,3580214783,LV
3580214784,3580223487,SE
@@ -135076,7 +137255,11 @@
3582050304,3582058495,NL
3582058496,3582066687,AT
3582066688,3582074879,UA
-3582074880,3582078631,GB
+3582074880,3582076863,GB
+3582076864,3582076895,DE
+3582076896,3582077439,GB
+3582077440,3582077471,DE
+3582077472,3582078631,GB
3582078632,3582078639,DE
3582078640,3582081023,GB
3582081024,3582081535,ES
@@ -135103,23 +137286,15 @@
3582156800,3582164991,GB
3582164992,3582173183,SE
3582173184,3582181375,GB
-3582181376,3582190847,DE
-3582190848,3582190879,CH
-3582190880,3582190927,DE
+3582181376,3582190927,DE
3582190928,3582190931,FR
3582190932,3582191023,DE
3582191024,3582191031,BE
3582191032,3582192127,DE
3582192128,3582192143,NL
-3582192144,3582192287,DE
-3582192288,3582192303,CH
-3582192304,3582194775,DE
+3582192144,3582194775,DE
3582194776,3582194783,CY
-3582194784,3582194863,DE
-3582194864,3582194879,CH
-3582194880,3582195135,DE
-3582195136,3582195143,CH
-3582195144,3582196183,DE
+3582194784,3582196183,DE
3582196184,3582196191,BE
3582196192,3582197127,DE
3582197128,3582197135,BZ
@@ -135137,7 +137312,9 @@
3582223968,3582223975,NO
3582223976,3582224375,SE
3582224376,3582224379,FI
-3582224380,3582226599,SE
+3582224380,3582225719,SE
+3582225720,3582225727,FI
+3582225728,3582226599,SE
3582226600,3582226607,FI
3582226608,3582230527,SE
3582230528,3582238719,BE
@@ -135380,9 +137557,7 @@
3582566752,3582566767,BE
3582566768,3582566783,EU
3582566784,3582566847,BE
-3582566848,3582566863,EU
-3582566864,3582566879,BE
-3582566880,3582566911,EU
+3582566848,3582566911,EU
3582566912,3582567019,BE
3582567020,3582567023,EU
3582567024,3582567039,BE
@@ -135426,8 +137601,7 @@
3582569472,3582569535,FR
3582569536,3582569983,EU
3582569984,3582570239,FR
-3582570240,3582570367,DE
-3582570368,3582570399,EU
+3582570240,3582570399,GB
3582570400,3582570431,FR
3582570432,3582570463,EU
3582570464,3582570471,FR
@@ -135748,8 +137922,7 @@
3583705848,3583705855,NA
3583705856,3583705859,UA
3583705860,3583705863,NA
-3583705864,3583705903,UA
-3583705904,3583705911,NA
+3583705864,3583705911,UA
3583705912,3583705919,RU
3583705920,3583706023,UA
3583706024,3583706031,NA
@@ -135853,9 +138026,7 @@
3583709728,3583709743,NA
3583709744,3583709759,UA
3583709760,3583709767,NA
-3583709768,3583709791,UA
-3583709792,3583709799,NA
-3583709800,3583709839,UA
+3583709768,3583709839,UA
3583709840,3583709863,NA
3583709864,3583709871,RU
3583709872,3583709879,NA
@@ -135892,9 +138063,7 @@
3583710856,3583710863,NA
3583710864,3583710887,UA
3583710888,3583710895,NA
-3583710896,3583710991,UA
-3583710992,3583710999,NA
-3583711000,3583711007,UA
+3583710896,3583711007,UA
3583711008,3583711015,RU
3583711016,3583711023,NA
3583711024,3583711247,UA
@@ -136267,9 +138436,7 @@
3584958464,3584966655,DE
3584966656,3584974847,DK
3584974848,3584983039,FR
-3584983040,3584988255,US
-3584988256,3584988287,UA
-3584988288,3584988575,US
+3584983040,3584988575,US
3584988576,3584988591,UA
3584988592,3584988623,US
3584988624,3584988639,UA
@@ -136685,7 +138852,8 @@
3586478592,3586478847,HU
3586478848,3586479103,SK
3586479104,3586479359,TR
-3586479360,3586490367,HU
+3586479360,3586479615,SK
+3586479616,3586490367,HU
3586490368,3586506751,LT
3586506752,3586523135,NL
3586523136,3586542559,DE
@@ -136734,7 +138902,9 @@
3586678688,3586678783,GB
3586678784,3586679039,IT
3586679040,3586679103,FR
-3586679104,3586679167,DE
+3586679104,3586679143,DE
+3586679144,3586679151,FR
+3586679152,3586679167,DE
3586679168,3586679327,FR
3586679328,3586679343,DK
3586679344,3586679359,FR
@@ -136758,9 +138928,7 @@
3586680768,3586680831,ES
3586680832,3586681087,FR
3586681088,3586681343,IT
-3586681344,3586682111,FR
-3586682112,3586682175,US
-3586682176,3586682239,FR
+3586681344,3586682239,FR
3586682240,3586682367,US
3586682368,3586682399,AT
3586682400,3586682879,FR
@@ -136783,40 +138951,13 @@
3586883584,3586899967,IT
3586899968,3586900287,DE
3586900288,3586900351,NL
-3586900352,3586902271,DE
-3586902272,3586902335,CH
-3586902336,3586902411,DE
-3586902412,3586902415,CH
-3586902416,3586903263,DE
-3586903264,3586903295,CH
-3586903296,3586904223,DE
-3586904224,3586904255,CH
-3586904256,3586904319,DE
-3586904320,3586904415,CH
-3586904416,3586904831,DE
+3586900352,3586904831,DE
3586904832,3586904839,VG
-3586904840,3586905039,DE
-3586905040,3586905055,CH
-3586905056,3586905071,DE
-3586905072,3586905079,CH
-3586905080,3586905087,DE
-3586905088,3586905119,CH
-3586905120,3586905167,DE
-3586905168,3586905199,CH
+3586904840,3586905199,DE
3586905200,3586905215,GB
-3586905216,3586905247,DE
-3586905248,3586905279,CH
-3586905280,3586905287,DE
+3586905216,3586905287,DE
3586905288,3586905295,CY
-3586905296,3586906391,DE
-3586906392,3586906399,CH
-3586906400,3586906423,DE
-3586906424,3586906427,CH
-3586906428,3586906719,DE
-3586906720,3586906735,CH
-3586906736,3586907903,DE
-3586907904,3586908031,CH
-3586908032,3586909695,DE
+3586905296,3586909695,DE
3586909696,3586909823,CH
3586909824,3586910559,DE
3586910560,3586910567,NL
@@ -136930,11 +139071,14 @@
3587179456,3587179463,AT
3587179464,3587179471,CH
3587179472,3587186687,AT
-3587186688,3587190783,DE
-3587190784,3587191039,GB
-3587191040,3587194495,DE
+3587186688,3587186815,DE
+3587186816,3587187199,A2
+3587187200,3587187455,DE
+3587187456,3587188479,A2
+3587188480,3587188735,DE
+3587188736,3587194495,A2
3587194496,3587194511,RU
-3587194512,3587194879,DE
+3587194512,3587194879,A2
3587194880,3587211263,GB
3587211264,3587211531,AT
3587211532,3587211535,DE
@@ -136942,7 +139086,9 @@
3587213912,3587213919,UY
3587213920,3587219455,AT
3587219456,3587227647,RU
-3587227648,3587227759,NL
+3587227648,3587227663,NL
+3587227664,3587227679,GB
+3587227680,3587227759,NL
3587227760,3587227775,GB
3587227776,3587227903,NL
3587227904,3587227967,GB
@@ -137055,11 +139201,13 @@
3587238608,3587238911,GB
3587238912,3587239303,NL
3587239304,3587239311,GB
-3587239312,3587239903,NL
-3587239904,3587239935,GB
-3587239936,3587239975,NL
+3587239312,3587239911,NL
+3587239912,3587239919,GB
+3587239920,3587239975,NL
3587239976,3587239983,GB
-3587239984,3587240087,NL
+3587239984,3587240063,NL
+3587240064,3587240071,GB
+3587240072,3587240087,NL
3587240088,3587240095,GB
3587240096,3587240103,NL
3587240104,3587240107,GB
@@ -137073,7 +139221,9 @@
3587240512,3587240575,GB
3587240576,3587240615,NL
3587240616,3587240623,GB
-3587240624,3587241143,NL
+3587240624,3587241071,NL
+3587241072,3587241087,GB
+3587241088,3587241143,NL
3587241144,3587241151,GB
3587241152,3587241223,NL
3587241224,3587241247,GB
@@ -137347,7 +139497,9 @@
3588588568,3588588575,IT
3588588576,3588590175,ES
3588590176,3588590207,BE
-3588590208,3588598607,ES
+3588590208,3588590591,ES
+3588590592,3588590847,FR
+3588590848,3588598607,ES
3588598608,3588598615,IT
3588598616,3588603903,ES
3588603904,3588620287,SI
@@ -137370,7 +139522,9 @@
3588782272,3588782279,A2
3588782280,3588784127,GB
3588784128,3588800511,CH
-3588800512,3588816895,RU
+3588800512,3588802687,RU
+3588802688,3588802815,CH
+3588802816,3588816895,RU
3588816896,3588833279,IT
3588833280,3588848767,RO
3588848768,3588848775,FR
@@ -137870,7 +140024,9 @@
3590157856,3590157951,RS
3590157952,3590158079,SI
3590158080,3590158343,RS
-3590158344,3590158407,SI
+3590158344,3590158359,SI
+3590158360,3590158367,RS
+3590158368,3590158407,SI
3590158408,3590158415,RS
3590158416,3590158431,SI
3590158432,3590158439,RS
@@ -137899,10 +140055,7 @@
3590245312,3590245439,US
3590245440,3590245503,FR
3590245504,3590245567,GB
-3590245568,3590245631,US
-3590245632,3590245887,FR
-3590245888,3590245983,US
-3590245984,3590246175,FR
+3590245568,3590246175,FR
3590246176,3590246207,AU
3590246208,3590246271,FR
3590246272,3590246287,DE
@@ -138016,16 +140169,18 @@
3590308392,3590308399,A2
3590308400,3590308407,IQ
3590308408,3590308415,A2
-3590308416,3590308455,IQ
+3590308416,3590308431,IQ
+3590308432,3590308439,A2
+3590308440,3590308455,IQ
3590308456,3590308463,A2
3590308464,3590308471,IQ
3590308472,3590308479,A2
3590308480,3590308487,IQ
-3590308488,3590308503,A2
-3590308504,3590308511,IQ
-3590308512,3590308519,A2
+3590308488,3590308519,A2
3590308520,3590308527,IQ
-3590308528,3590308551,A2
+3590308528,3590308535,A2
+3590308536,3590308543,IQ
+3590308544,3590308551,A2
3590308552,3590308559,IQ
3590308560,3590308567,A2
3590308568,3590308583,IQ
@@ -138071,8 +140226,8 @@
3590309712,3590309719,IQ
3590309720,3590309727,A2
3590309728,3590309759,IQ
-3590309760,3590309767,A2
-3590309768,3590309791,IQ
+3590309760,3590309775,A2
+3590309776,3590309791,IQ
3590309792,3590309799,A2
3590309800,3590309807,IQ
3590309808,3590309815,A2
@@ -138087,8 +140242,7 @@
3590310184,3590310215,IQ
3590310216,3590310223,A2
3590310224,3590310255,IQ
-3590310256,3590310263,A2
-3590310264,3590310271,SD
+3590310256,3590310271,A2
3590310272,3590310279,IQ
3590310280,3590310287,A2
3590310288,3590310303,IQ
@@ -138099,8 +140253,8 @@
3590310336,3590310343,IQ
3590310344,3590310351,A2
3590310352,3590310367,IQ
-3590310368,3590310383,A2
-3590310384,3590310391,IQ
+3590310368,3590310375,A2
+3590310376,3590310391,IQ
3590310392,3590310655,A2
3590310656,3590310911,GB
3590310912,3590310919,IQ
@@ -138379,7 +140533,9 @@
3624376656,3624376679,GB
3624376680,3624377319,US
3624377320,3624377323,GB
-3624377324,3624377863,US
+3624377324,3624377599,US
+3624377600,3624377855,A2
+3624377856,3624377863,US
3624377864,3624377871,GB
3624377872,3624377879,US
3624377880,3624377887,GB
@@ -138421,9 +140577,7 @@
3624380936,3624380943,SA
3624380944,3624380967,GB
3624380968,3624380983,TW
-3624380984,3624381471,US
-3624381472,3624381487,AU
-3624381488,3624381567,US
+3624380984,3624381567,US
3624381568,3624381583,MY
3624381584,3624381631,US
3624381632,3624381647,GB
@@ -138516,8 +140670,8 @@
3624549080,3624549087,A2
3624549088,3624549103,US
3624549104,3624549111,A2
-3624549112,3624549375,US
-3624549376,3624550143,A2
+3624549112,3624549383,US
+3624549384,3624550143,A2
3624550144,3624587263,US
3624587264,3624591359,JM
3624595456,3624730623,US
@@ -138528,7 +140682,9 @@
3624820736,3624820799,CY
3624820800,3624821695,US
3624821696,3624821703,GB
-3624821704,3624825097,US
+3624821704,3624822783,US
+3624822784,3624823039,SG
+3624823040,3624825097,US
3624825098,3624825102,BR
3624825103,3624827296,US
3624827297,3624827299,RS
@@ -139362,7 +141518,8 @@
3626385098,3626385101,IN
3626385102,3626385113,US
3626385114,3626385117,JP
-3626385118,3626385125,US
+3626385118,3626385121,US
+3626385122,3626385125,IN
3626385126,3626385129,ID
3626385130,3626385133,GR
3626385134,3626385137,CA
@@ -139605,7 +141762,9 @@
3627524988,3627532287,US
3627532288,3627544575,CA
3627544576,3627659263,US
-3627659264,3627663359,CA
+3627659264,3627661951,CA
+3627661952,3627662015,US
+3627662016,3627663359,CA
3627663360,3627665407,US
3627665408,3627665439,CA
3627665440,3627666255,US
@@ -139623,13 +141782,13 @@
3627745376,3627745439,US
3627745440,3627745471,IN
3627745472,3627745503,CA
-3627745504,3627745919,US
-3627745920,3627745983,IL
-3627745984,3627746399,US
+3627745504,3627746399,US
3627746400,3627746431,CA
3627746432,3627747159,US
3627747160,3627747167,IN
-3627747168,3627753471,US
+3627747168,3627747583,US
+3627747584,3627747615,FR
+3627747616,3627753471,US
3627753472,3627753727,AR
3627753728,3627755007,US
3627755008,3627755135,IE
@@ -139732,8 +141891,7 @@
3628179456,3628187647,CA
3628187648,3628208127,US
3628208128,3628208383,IT
-3628208384,3628208639,CN
-3628208640,3628223983,US
+3628208384,3628223983,US
3628223984,3628223999,CA
3628224000,3628224735,US
3628224736,3628224743,IT
@@ -140490,7 +142648,9 @@
3631333376,3631333679,CA
3631333680,3631333695,US
3631333696,3631341567,CA
-3631341568,3631435007,US
+3631341568,3631415295,US
+3631415296,3631419391,A2
+3631419392,3631435007,US
3631435008,3631435263,GB
3631435264,3631480831,US
3631482880,3631484927,CA
@@ -140720,7 +142880,7 @@
3632484384,3632484391,GB
3632484392,3632484623,US
3632484624,3632484639,GB
-3632484640,3632484647,CA
+3632484640,3632484647,SG
3632484648,3632484655,JP
3632484656,3632484687,US
3632484688,3632484695,GI
@@ -141367,7 +143527,9 @@
3635533536,3635533551,IN
3635533552,3635658751,US
3635658752,3635660799,CN
-3635660800,3635847791,US
+3635660800,3635661823,HK
+3635661824,3635662847,JP
+3635662848,3635847791,US
3635847792,3635847807,CA
3635847808,3635856511,US
3635856512,3635856543,CA
@@ -141513,11 +143675,7 @@
3636266880,3636266911,HK
3636266912,3636284415,US
3636284416,3636284671,FR
-3636284672,3636290815,US
-3636290816,3636291327,FR
-3636291328,3636296959,US
-3636296960,3636297727,FR
-3636297728,3636396031,US
+3636284672,3636396031,US
3636396032,3636461567,CA
3636461568,3636577647,US
3636577648,3636577663,CA
@@ -142121,7 +144279,9 @@
3640028336,3640028343,CA
3640028344,3640028447,US
3640028448,3640028455,GB
-3640028456,3640028591,US
+3640028456,3640028519,US
+3640028520,3640028527,BR
+3640028528,3640028591,US
3640028592,3640028599,CA
3640028600,3640057855,US
3640057856,3640066047,CA
@@ -142216,7 +144376,9 @@
3640450048,3640451071,US
3640451072,3640459263,A2
3640459264,3640557567,US
-3640557568,3640560511,CA
+3640557568,3640559567,CA
+3640559568,3640559575,US
+3640559576,3640560511,CA
3640560512,3640560527,US
3640560528,3640564455,CA
3640564456,3640564463,US
@@ -142325,9 +144487,7 @@
3641354328,3641354335,GB
3641354336,3641354339,A2
3641354340,3641354367,GB
-3641354368,3641354383,A2
-3641354384,3641354479,IT
-3641354480,3641354495,A2
+3641354368,3641354495,A2
3641354496,3641354751,GB
3641354752,3641355263,NG
3641355264,3641355519,AO
@@ -142539,8 +144699,10 @@
3641956864,3641957631,GB
3641957632,3641957887,MD
3641957888,3641958399,GB
-3641958400,3641960699,BE
-3641960700,3641960703,NL
+3641958400,3641960447,BE
+3641960448,3641960519,NL
+3641960520,3641960527,BE
+3641960528,3641960703,NL
3641960704,3641961727,BE
3641961728,3641961743,NL
3641961744,3641961791,BE
@@ -142590,10 +144752,11 @@
3642064896,3642068991,SE
3642068992,3642073087,AL
3642073088,3642077183,LV
-3642077184,3642081271,BE
+3642077184,3642078999,BE
+3642079000,3642079007,NL
+3642079008,3642081271,BE
3642081272,3642081278,US
-3642081279,3642081279,BE
-3642081280,3642085375,NL
+3642081279,3642085375,NL
3642085376,3642089471,RU
3642089472,3642093567,SE
3642093568,3642097663,NL
@@ -142704,10 +144867,8 @@
3642253312,3642257407,FI
3642257408,3642261503,RU
3642261504,3642265599,BA
-3642265600,3642266111,AE
-3642266112,3642266367,IR
-3642266368,3642266623,AE
-3642266624,3642269695,IR
+3642265600,3642265855,AE
+3642265856,3642269695,IR
3642269696,3642273791,UA
3642273792,3642277887,RU
3642277888,3642290175,DE
@@ -142750,7 +144911,6 @@
3642415636,3642415651,GB
3642415652,3642415655,MT
3642415656,3642417151,GB
-3642417152,3642421247,IT
3642421248,3642423091,A2
3642423092,3642423099,NG
3642423100,3642424151,A2
@@ -142820,9 +144980,7 @@
3642552848,3642553095,UA
3642553096,3642553099,LV
3642553100,3642553103,UA
-3642553104,3642553139,LV
-3642553140,3642553143,UA
-3642553144,3642553161,LV
+3642553104,3642553161,LV
3642553162,3642553163,UA
3642553164,3642553175,LV
3642553176,3642553183,UA
@@ -142928,7 +145086,8 @@
3642555496,3642555503,PL
3642555504,3642555647,UA
3642555648,3642555683,SE
-3642555684,3642555691,UA
+3642555684,3642555685,GB
+3642555686,3642555691,UA
3642555692,3642555695,SE
3642555696,3642555703,UA
3642555704,3642555707,FI
@@ -143219,7 +145378,7 @@
3645435904,3645439999,GB
3645440000,3645444095,SE
3645444096,3645448191,SK
-3645448192,3645456383,DE
+3645448192,3645452287,DE
3645456384,3645460479,GB
3645460480,3645464575,UA
3645464576,3645468671,SE
@@ -143270,7 +145429,9 @@
3645594712,3645594719,SR
3645594720,3645594743,SK
3645594744,3645594751,SR
-3645594752,3645595647,SK
+3645594752,3645594863,SK
+3645594864,3645594871,SR
+3645594872,3645595647,SK
3645595648,3645597751,SE
3645597752,3645597759,GB
3645597760,3645601471,SE
@@ -143849,8 +146010,8 @@
3645764262,3645764262,BE
3645764263,3645764264,IT
3645764265,3645764265,TR
-3645764266,3645764268,DE
-3645764269,3645764270,ES
+3645764266,3645764269,DE
+3645764270,3645764270,ES
3645764271,3645764271,IT
3645764272,3645764272,DE
3645764273,3645764273,IT
@@ -144331,9 +146492,7 @@
3647965296,3647965303,DE
3647965304,3647965311,ES
3647965312,3647965319,DE
-3647965320,3647965359,ES
-3647965360,3647965375,DE
-3647965376,3647965407,ES
+3647965320,3647965407,ES
3647965408,3647965439,DE
3647965440,3647965695,ES
3647965696,3647966207,CH
@@ -144352,15 +146511,17 @@
3647972200,3647972259,GB
3647972260,3647972263,DE
3647972264,3647972351,GB
-3647972352,3647973623,IT
-3647973624,3647973631,DE
-3647973632,3647973679,IT
-3647973680,3647973711,DE
+3647972352,3647973679,IT
+3647973680,3647973695,DE
+3647973696,3647973703,IT
+3647973704,3647973711,DE
3647973712,3647973735,IT
3647973736,3647973743,DE
3647973744,3647973783,IT
3647973784,3647973791,DE
-3647973792,3647973967,IT
+3647973792,3647973815,IT
+3647973816,3647973823,DE
+3647973824,3647973967,IT
3647973968,3647973975,DE
3647973976,3647974047,IT
3647974048,3647974055,DE
@@ -144394,8 +146555,8 @@
3647978776,3647978783,DE
3647978784,3647978895,NL
3647978896,3647978911,DE
-3647978912,3647978951,NL
-3647978952,3647979007,DE
+3647978912,3647978943,NL
+3647978944,3647979007,DE
3647979008,3647979136,IT
3647979137,3647979519,DE
3647979520,3647980215,FR
@@ -144415,7 +146576,9 @@
3647982592,3647983615,IT
3647983616,3647984639,NL
3647984640,3647985151,DK
-3647985152,3647985663,BE
+3647985152,3647985415,BE
+3647985416,3647985423,AT
+3647985424,3647985663,BE
3647985664,3647985919,ES
3647985920,3647985935,BE
3647985936,3647986431,ES
@@ -144423,14 +146586,19 @@
3647986688,3647986943,DE
3647986944,3647986951,ES
3647986952,3647986975,DE
-3647986976,3647986999,ES
-3647987000,3647987455,DE
+3647986976,3647987031,ES
+3647987032,3647987039,DE
+3647987040,3647987055,ES
+3647987056,3647987455,DE
3647987456,3647987527,ES
3647987528,3647987543,DE
3647987544,3647987711,ES
3647987712,3647988735,IT
-3647988736,3647989759,BE
-3647989760,3647995903,DE
+3647988736,3647988991,DE
+3647988992,3647989063,BE
+3647989064,3647989071,DE
+3647989072,3647989087,BE
+3647989088,3647995903,DE
3647995904,3648004223,RU
3648004224,3648004607,GB
3648004608,3648006271,RU
@@ -144503,9 +146671,7 @@
3648086016,3648090111,AT
3648090112,3648094207,RU
3648094208,3648102399,PL
-3648102400,3648104767,GB
-3648104768,3648104783,IE
-3648104784,3648104791,GB
+3648102400,3648104791,GB
3648104792,3648104799,IE
3648104800,3648106495,GB
3648106496,3648110591,DE
@@ -144575,8 +146741,7 @@
3648182824,3648182831,RU
3648182832,3648182847,DE
3648182848,3648182879,AT
-3648182880,3648182911,SG
-3648182912,3648183551,DE
+3648182880,3648183551,DE
3648183552,3648183679,BR
3648183680,3648183871,DE
3648183872,3648183935,GB
@@ -144635,7 +146800,9 @@
3648356352,3648360447,PL
3648360448,3648362251,FR
3648362252,3648362255,GB
-3648362256,3648364543,FR
+3648362256,3648362263,FR
+3648362264,3648362271,GB
+3648362272,3648364543,FR
3648364544,3648368639,CH
3648368640,3648372735,RU
3648372736,3648376831,LU
@@ -144760,7 +146927,6 @@
3650093056,3650097151,JO
3650097152,3650101247,SK
3650101248,3650105343,DE
-3650105344,3650109439,CH
3650109440,3650113535,NO
3650113536,3650117631,GB
3650117632,3650121727,RU
@@ -144793,7 +146959,9 @@
3650228224,3650228735,US
3650228736,3650228991,A2
3650228992,3650232319,US
-3650232320,3650236415,RU
+3650232320,3650233343,RU
+3650233344,3650233599,CY
+3650233600,3650236415,RU
3650236416,3650240511,GB
3650240512,3650244607,EE
3650244608,3650256895,GB
@@ -145061,7 +147229,8 @@
3651204224,3651204351,DE
3651204352,3651204607,PL
3651204608,3651205119,ES
-3651205120,3651207167,DE
+3651205120,3651205375,GB
+3651205376,3651207167,DE
3651207168,3651207199,GB
3651207200,3651207223,EU
3651207224,3651207295,GB
@@ -145378,7 +147547,9 @@
3652050536,3652050567,IE
3652050568,3652050615,GB
3652050616,3652050619,IE
-3652050620,3652050671,GB
+3652050620,3652050627,GB
+3652050628,3652050631,IE
+3652050632,3652050671,GB
3652050672,3652050943,IE
3652050944,3652055039,LI
3652055040,3652059135,NO
@@ -145712,7 +147883,9 @@
3653664768,3653664895,DE
3653664896,3653665023,NL
3653665024,3653665071,DE
-3653665072,3653668863,NL
+3653665072,3653666815,NL
+3653666816,3653667327,DE
+3653667328,3653668863,NL
3653668864,3653672959,SE
3653672960,3653681151,RU
3653681152,3653685247,ES
@@ -145773,7 +147946,9 @@
3654608128,3654608383,SE
3654608384,3654608895,PL
3654608896,3654609919,NO
-3654609920,3654613007,SE
+3654609920,3654610431,SE
+3654610432,3654610943,FR
+3654610944,3654613007,SE
3654613008,3654613015,RU
3654613016,3654613055,SE
3654613056,3654613071,RU
@@ -145798,8 +147973,7 @@
3656234000,3656234007,NL
3656234008,3656236527,DE
3656236528,3656236535,GB
-3656236536,3656236543,US
-3656236544,3656633487,DE
+3656236536,3656633487,DE
3656633488,3656633495,GB
3656633496,3656633503,US
3656633504,3656650583,DE
diff --git a/src/or/Makefile.am b/src/or/Makefile.am
index a9ac3cdee..a12d56b73 100644
--- a/src/or/Makefile.am
+++ b/src/or/Makefile.am
@@ -15,16 +15,45 @@ else
evdns_source=eventdns.c
endif
-libtor_a_SOURCES = buffers.c circuitbuild.c circuitlist.c \
- circuituse.c command.c config.c \
- connection.c connection_edge.c connection_or.c control.c \
- cpuworker.c directory.c dirserv.c dirvote.c \
- dns.c dnsserv.c geoip.c hibernate.c main.c $(tor_platform_source) \
- microdesc.c \
- networkstatus.c onion.c policies.c \
- reasons.c relay.c rendcommon.c rendclient.c rendmid.c \
- rendservice.c rephist.c router.c routerlist.c routerparse.c \
- $(evdns_source) config_codedigest.c
+libtor_a_SOURCES = \
+ buffers.c \
+ circuitbuild.c \
+ circuitlist.c \
+ circuituse.c \
+ command.c \
+ config.c \
+ connection.c \
+ connection_edge.c \
+ connection_or.c \
+ control.c \
+ cpuworker.c \
+ directory.c \
+ dirserv.c \
+ dirvote.c \
+ dns.c \
+ dnsserv.c \
+ geoip.c \
+ hibernate.c \
+ main.c \
+ microdesc.c \
+ networkstatus.c \
+ nodelist.c \
+ onion.c \
+ policies.c \
+ reasons.c \
+ relay.c \
+ rendclient.c \
+ rendcommon.c \
+ rendmid.c \
+ rendservice.c \
+ rephist.c \
+ router.c \
+ routerlist.c \
+ routerparse.c \
+ status.c \
+ $(evdns_source) \
+ $(tor_platform_source) \
+ config_codedigest.c
#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \
# ../common/libor-event.a
@@ -40,18 +69,54 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# This seems to matter nowhere but on windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
+
tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
tor_LDADD = ./libtor.a ../common/libor.a ../common/libor-crypto.a \
../common/libor-event.a \
- @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
-
-noinst_HEADERS = buffers.h circuitbuild.h circuitlist.h circuituse.h \
- command.h config.h connection_edge.h connection.h connection_or.h \
- control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \
- dnsserv.h geoip.h hibernate.h main.h microdesc.h networkstatus.h \
- ntmain.h onion.h policies.h reasons.h relay.h rendclient.h \
- rendcommon.h rendmid.h rendservice.h rephist.h router.h routerlist.h \
- routerparse.h or.h eventdns.h eventdns_tor.h micro-revision.i
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS = \
+ buffers.h \
+ circuitbuild.h \
+ circuitlist.h \
+ circuituse.h \
+ command.h \
+ config.h \
+ connection.h \
+ connection_edge.h \
+ connection_or.h \
+ control.h \
+ cpuworker.h \
+ directory.h \
+ dirserv.h \
+ dirvote.h \
+ dns.h \
+ dnsserv.h \
+ eventdns.h \
+ eventdns_tor.h \
+ geoip.h \
+ hibernate.h \
+ main.h \
+ microdesc.h \
+ networkstatus.h \
+ nodelist.h \
+ ntmain.h \
+ onion.h \
+ or.h \
+ policies.h \
+ reasons.h \
+ relay.h \
+ rendclient.h \
+ rendcommon.h \
+ rendmid.h \
+ rendservice.h \
+ rephist.h \
+ router.h \
+ routerlist.h \
+ routerparse.h \
+ status.h \
+ micro-revision.i
config_codedigest.o: or_sha1.i
diff --git a/src/or/buffers.c b/src/or/buffers.c
index db926955b..73127490c 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -23,9 +23,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
//#define PARANOIA
@@ -56,6 +53,13 @@
* forever.
*/
+static int parse_socks(const char *data, size_t datalen, socks_request_t *req,
+ int log_sockstype, int safe_socks, ssize_t *drain_out,
+ size_t *want_length_out);
+static int parse_socks_client(const uint8_t *data, size_t datalen,
+ int state, char **reason,
+ ssize_t *drain_out);
+
/* Chunk manipulation functions */
/** A single chunk on a buffer or in a freelist. */
@@ -64,8 +68,8 @@ typedef struct chunk_t {
size_t datalen; /**< The number of bytes stored in this chunk */
size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */
char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */
- char mem[1]; /**< The actual memory used for storage in this chunk. May be
- * more than one byte long. */
+ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in
+ * this chunk. */
} chunk_t;
#define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0])
@@ -547,6 +551,7 @@ buf_free(buf_t *buf)
{
if (!buf)
return;
+
buf_clear(buf);
buf->magic = 0xdeadbeef;
tor_free(buf);
@@ -578,38 +583,18 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
return chunk;
}
-/** If we're using readv and writev, how many chunks are we willing to
- * read/write at a time? */
-#define N_IOV 3
-
/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
* <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
* *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
* and the number of bytes read otherwise. */
static INLINE int
-read_to_chunk(buf_t *buf, chunk_t *chunk, int fd, size_t at_most,
+read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
int *reached_eof, int *socket_error)
{
ssize_t read_result;
-#if 0 && defined(HAVE_READV) && !defined(WIN32)
- struct iovec iov[N_IOV];
- int i;
- size_t remaining = at_most;
- for (i=0; chunk && i < N_IOV && remaining; ++i) {
- iov[i].iov_base = CHUNK_WRITE_PTR(chunk);
- if (remaining > CHUNK_REMAINING_CAPACITY(chunk))
- iov[i].iov_len = CHUNK_REMAINING_CAPACITY(chunk);
- else
- iov[i].iov_len = remaining;
- remaining -= iov[i].iov_len;
- chunk = chunk->next;
- }
- read_result = readv(fd, iov, i);
-#else
if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
at_most = CHUNK_REMAINING_CAPACITY(chunk);
read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
-#endif
if (read_result < 0) {
int e = tor_socket_errno(fd);
@@ -628,14 +613,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, int fd, size_t at_most,
return 0;
} else { /* actually got bytes. */
buf->datalen += read_result;
-#if 0 && defined(HAVE_READV) && !defined(WIN32)
- while ((size_t)read_result > CHUNK_REMAINING_CAPACITY(chunk)) {
- chunk->datalen += CHUNK_REMAINING_CAPACITY(chunk);
- read_result -= CHUNK_REMAINING_CAPACITY(chunk);
- chunk = chunk->next;
- tor_assert(chunk);
- }
-#endif
chunk->datalen += read_result;
log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
(int)buf->datalen);
@@ -668,7 +645,7 @@ read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
*/
/* XXXX023 indicate "read blocked" somehow? */
int
-read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof,
+read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
int *socket_error)
{
/* XXXX023 It's stupid to overload the return values for these functions:
@@ -767,29 +744,14 @@ read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf)
* written on success, 0 on blocking, -1 on failure.
*/
static INLINE int
-flush_chunk(int s, buf_t *buf, chunk_t *chunk, size_t sz,
+flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
size_t *buf_flushlen)
{
ssize_t write_result;
-#if 0 && defined(HAVE_WRITEV) && !defined(WIN32)
- struct iovec iov[N_IOV];
- int i;
- size_t remaining = sz;
- for (i=0; chunk && i < N_IOV && remaining; ++i) {
- iov[i].iov_base = chunk->data;
- if (remaining > chunk->datalen)
- iov[i].iov_len = chunk->datalen;
- else
- iov[i].iov_len = remaining;
- remaining -= iov[i].iov_len;
- chunk = chunk->next;
- }
- write_result = writev(s, iov, i);
-#else
+
if (sz > chunk->datalen)
sz = chunk->datalen;
write_result = tor_socket_send(s, chunk->data, sz, 0);
-#endif
if (write_result < 0) {
int e = tor_socket_errno(s);
@@ -854,7 +816,7 @@ flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
* -1 on failure. Return 0 if write() would block.
*/
int
-flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen)
+flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen)
{
/* XXXX023 It's stupid to overload the return values for these functions:
* "error status" and "number of bytes flushed" are not mutually exclusive.
@@ -1056,6 +1018,103 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
return 1;
}
+#ifdef USE_BUFFEREVENTS
+/** Try to read <b>n</b> bytes from <b>buf</b> at <b>pos</b> (which may be
+ * NULL for the start of the buffer), copying the data only if necessary. Set
+ * *<b>data</b> to a pointer to the desired bytes. Set <b>free_out</b> to 1
+ * if we needed to malloc *<b>data</b> because the original bytes were
+ * noncontiguous; 0 otherwise. Return the number of bytes actually available
+ * at <b>data</b>.
+ */
+static ssize_t
+inspect_evbuffer(struct evbuffer *buf, char **data, size_t n, int *free_out,
+ struct evbuffer_ptr *pos)
+{
+ int n_vecs, i;
+
+ if (evbuffer_get_length(buf) < n)
+ n = evbuffer_get_length(buf);
+ if (n == 0)
+ return 0;
+ n_vecs = evbuffer_peek(buf, n, pos, NULL, 0);
+ tor_assert(n_vecs > 0);
+ if (n_vecs == 1) {
+ struct evbuffer_iovec v;
+ i = evbuffer_peek(buf, n, pos, &v, 1);
+ tor_assert(i == 1);
+ *data = v.iov_base;
+ *free_out = 0;
+ return v.iov_len;
+ } else {
+ struct evbuffer_iovec *vecs =
+ tor_malloc(sizeof(struct evbuffer_iovec)*n_vecs);
+ size_t copied = 0;
+ i = evbuffer_peek(buf, n, NULL, vecs, n_vecs);
+ tor_assert(i == n_vecs);
+ *data = tor_malloc(n);
+ for (i=0; i < n_vecs; ++i) {
+ size_t copy = n - copied;
+ if (copy > vecs[i].iov_len)
+ copy = vecs[i].iov_len;
+ tor_assert(copied+copy <= n);
+ memcpy(data+copied, vecs[i].iov_base, copy);
+ copied += copy;
+ }
+ *free_out = 1;
+ return copied;
+ }
+}
+
+/** As fetch_var_cell_from_buf, buf works on an evbuffer. */
+int
+fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto)
+{
+ char *hdr = NULL;
+ int free_hdr = 0;
+ size_t n;
+ size_t buf_len;
+ uint8_t command;
+ uint16_t cell_length;
+ var_cell_t *cell;
+ int result = 0;
+ if (linkproto == 1)
+ return 0;
+
+ *out = NULL;
+ buf_len = evbuffer_get_length(buf);
+ if (buf_len < VAR_CELL_HEADER_SIZE)
+ return 0;
+
+ n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL);
+ tor_assert(n >= VAR_CELL_HEADER_SIZE);
+
+ command = get_uint8(hdr+2);
+ if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) {
+ goto done;
+ }
+
+ cell_length = ntohs(get_uint16(hdr+3));
+ if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) {
+ result = 1; /* Not all here yet. */
+ goto done;
+ }
+
+ cell = var_cell_new(cell_length);
+ cell->command = command;
+ cell->circ_id = ntohs(get_uint16(hdr));
+ evbuffer_drain(buf, VAR_CELL_HEADER_SIZE);
+ evbuffer_remove(buf, cell->payload, cell_length);
+ *out = cell;
+ result = 1;
+
+ done:
+ if (free_hdr && hdr)
+ tor_free(hdr);
+ return result;
+}
+#endif
+
/** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to
* <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately.
* Return the number of bytes actually copied.
@@ -1063,8 +1122,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
int
move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
{
- /* XXXX we can do way better here, but this doesn't turn up in any
- * profiles. */
+ /* We can do way better here, but this doesn't turn up in any profiles. */
char b[4096];
size_t cp, len;
len = *buf_flushlen;
@@ -1299,6 +1357,94 @@ fetch_from_buf_http(buf_t *buf,
return 1;
}
+#ifdef USE_BUFFEREVENTS
+/** As fetch_from_buf_http, buf works on an evbuffer. */
+int
+fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete)
+{
+ struct evbuffer_ptr crlf, content_length;
+ size_t headerlen, bodylen, contentlen;
+
+ /* Find the first \r\n\r\n in the buffer */
+ crlf = evbuffer_search(buf, "\r\n\r\n", 4, NULL);
+ if (crlf.pos < 0) {
+ /* We didn't find one. */
+ if (evbuffer_get_length(buf) > max_headerlen)
+ return -1; /* Headers too long. */
+ return 0; /* Headers not here yet. */
+ } else if (crlf.pos > (int)max_headerlen) {
+ return -1; /* Headers too long. */
+ }
+
+ headerlen = crlf.pos + 4; /* Skip over the \r\n\r\n */
+ bodylen = evbuffer_get_length(buf) - headerlen;
+ if (bodylen > max_bodylen)
+ return -1; /* body too long */
+
+ /* Look for the first occurrence of CONTENT_LENGTH insize buf before the
+ * crlfcrlf */
+ content_length = evbuffer_search_range(buf, CONTENT_LENGTH,
+ strlen(CONTENT_LENGTH), NULL, &crlf);
+
+ if (content_length.pos >= 0) {
+ /* We found a content_length: parse it and figure out if the body is here
+ * yet. */
+ struct evbuffer_ptr eol;
+ char *data = NULL;
+ int free_data = 0;
+ int n, i;
+ n = evbuffer_ptr_set(buf, &content_length, strlen(CONTENT_LENGTH),
+ EVBUFFER_PTR_ADD);
+ tor_assert(n == 0);
+ eol = evbuffer_search_eol(buf, &content_length, NULL, EVBUFFER_EOL_CRLF);
+ tor_assert(eol.pos > content_length.pos);
+ tor_assert(eol.pos <= crlf.pos);
+ inspect_evbuffer(buf, &data, eol.pos - content_length.pos, &free_data,
+ &content_length);
+
+ i = atoi(data);
+ if (free_data)
+ tor_free(data);
+ if (i < 0) {
+ log_warn(LD_PROTOCOL, "Content-Length is less than zero; it looks like "
+ "someone is trying to crash us.");
+ return -1;
+ }
+ contentlen = i;
+ /* if content-length is malformed, then our body length is 0. fine. */
+ log_debug(LD_HTTP,"Got a contentlen of %d.",(int)contentlen);
+ if (bodylen < contentlen) {
+ if (!force_complete) {
+ log_debug(LD_HTTP,"body not all here yet.");
+ return 0; /* not all there yet */
+ }
+ }
+ if (bodylen > contentlen) {
+ bodylen = contentlen;
+ log_debug(LD_HTTP,"bodylen reduced to %d.",(int)bodylen);
+ }
+ }
+
+ if (headers_out) {
+ *headers_out = tor_malloc(headerlen+1);
+ evbuffer_remove(buf, *headers_out, headerlen);
+ (*headers_out)[headerlen] = '\0';
+ }
+ if (body_out) {
+ tor_assert(headers_out);
+ tor_assert(body_used);
+ *body_used = bodylen;
+ *body_out = tor_malloc(bodylen+1);
+ evbuffer_remove(buf, *body_out, bodylen);
+ (*body_out)[bodylen] = '\0';
+ }
+ return 1;
+}
+#endif
+
/**
* Wait this many seconds before warning the user about using SOCKS unsafely
* again (requires that WarnUnsafeSocks is turned on). */
@@ -1313,7 +1459,7 @@ log_unsafe_socks_warning(int socks_protocol, const char *address,
{
static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *m = NULL;
if (! options->WarnUnsafeSocks)
return;
@@ -1369,6 +1515,128 @@ int
fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks)
{
+ int res;
+ ssize_t n_drain;
+ size_t want_length = 128;
+
+ if (buf->datalen < 2) /* version and another byte */
+ return 0;
+
+ do {
+ n_drain = 0;
+ buf_pullup(buf, want_length, 0);
+ tor_assert(buf->head && buf->head->datalen >= 2);
+ want_length = 0;
+
+ res = parse_socks(buf->head->data, buf->head->datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (n_drain < 0)
+ buf_clear(buf);
+ else if (n_drain > 0)
+ buf_remove_from_front(buf, n_drain);
+
+ } while (res == 0 && buf->head &&
+ buf->datalen > buf->head->datalen &&
+ want_length < buf->head->datalen);
+
+ return res;
+}
+
+#ifdef USE_BUFFEREVENTS
+/* As fetch_from_buf_socks(), but targets an evbuffer instead. */
+int
+fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
+ int log_sockstype, int safe_socks)
+{
+ char *data;
+ ssize_t n_drain;
+ size_t datalen, buflen, want_length;
+ int res;
+
+ buflen = evbuffer_get_length(buf);
+ if (buflen < 2)
+ return 0;
+
+ {
+ /* See if we can find the socks request in the first chunk of the buffer.
+ */
+ struct evbuffer_iovec v;
+ int i;
+ want_length = evbuffer_get_contiguous_space(buf);
+ n_drain = 0;
+ i = evbuffer_peek(buf, want_length, NULL, &v, 1);
+ tor_assert(i == 1);
+ data = v.iov_base;
+ datalen = v.iov_len;
+
+ res = parse_socks(data, datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (n_drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+ else if (n_drain > 0)
+ evbuffer_drain(buf, n_drain);
+
+ if (res)
+ return res;
+ }
+
+ /* Okay, the first chunk of the buffer didn't have a complete socks request.
+ * That means that either we don't have a whole socks request at all, or
+ * it's gotten split up. We're going to try passing parse_socks() bigger
+ * and bigger chunks until either it says "Okay, I got it", or it says it
+ * will need more data than we currently have. */
+
+ /* Loop while we have more data that we haven't given parse_socks() yet. */
+ while (evbuffer_get_length(buf) > datalen) {
+ int free_data = 0;
+ n_drain = 0;
+ data = NULL;
+ datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL);
+
+ res = parse_socks(data, datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (free_data)
+ tor_free(data);
+
+ if (n_drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+ else if (n_drain > 0)
+ evbuffer_drain(buf, n_drain);
+
+ if (res) /* If res is nonzero, parse_socks() made up its mind. */
+ return res;
+
+ /* If parse_socks says that we want less data than we actually tried to
+ give it, we've got some kind of weird situation; just exit the loop for
+ now.
+ */
+ if (want_length <= datalen)
+ break;
+ /* Otherwise, it wants more data than we gave it. If we can provide more
+ * data than we gave it, we'll try to do so in the next iteration of the
+ * loop. If we can't, the while loop will exit. It's okay if it asked for
+ * more than we have total; maybe it doesn't really need so much. */
+ }
+
+ return res;
+}
+#endif
+
+/** Implementation helper to implement fetch_from_*_socks. Instead of looking
+ * at a buffer's contents, we look at the <b>datalen</b> bytes of data in
+ * <b>data</b>. Instead of removing data from the buffer, we set
+ * <b>drain_out</b> to the amount of data that should be removed (or -1 if the
+ * buffer should be cleared). Instead of pulling more data into the first
+ * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes
+ * we'd like to see in the input buffer, if they're available. */
+static int
+parse_socks(const char *data, size_t datalen, socks_request_t *req,
+ int log_sockstype, int safe_socks, ssize_t *drain_out,
+ size_t *want_length_out)
+{
unsigned int len;
char tmpbuf[TOR_ADDR_BUF_LEN+1];
tor_addr_t destaddr;
@@ -1378,25 +1646,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
char *next, *startaddr;
struct in_addr in;
- if (buf->datalen < 2) /* version and another byte */
- return 0;
-
- buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
- tor_assert(buf->head && buf->head->datalen >= 2);
-
- socksver = *buf->head->data;
+ socksver = *data;
switch (socksver) { /* which version of socks? */
case 5: /* socks5 */
if (req->socks_version != 5) { /* we need to negotiate a method */
- unsigned char nummethods = (unsigned char)*(buf->head->data+1);
+ unsigned char nummethods = (unsigned char)*(data+1);
tor_assert(!req->socks_version);
- if (buf->datalen < 2u+nummethods)
+ if (datalen < 2u+nummethods) {
+ *want_length_out = 2u+nummethods;
return 0;
- buf_pullup(buf, 2u+nummethods, 0);
- if (!nummethods || !memchr(buf->head->data+2, 0, nummethods)) {
+ }
+ if (!nummethods || !memchr(data+2, 0, nummethods)) {
log_warn(LD_APP,
"socks5: offered methods don't include 'no auth'. "
"Rejecting.");
@@ -1407,7 +1670,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
}
/* remove packet from buf. also remove any other extraneous
* bytes, to support broken socks clients. */
- buf_clear(buf);
+ *drain_out = -1;
req->replylen = 2; /* 2 bytes of response */
req->reply[0] = 5; /* socks5 reply */
@@ -1418,10 +1681,11 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
}
/* we know the method; read in the request */
log_debug(LD_APP,"socks5: checking request");
- if (buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */
+ if (datalen < 8) {/* basic info plus >=2 for addr plus 2 for port */
+ *want_length_out = 8;
return 0; /* not yet */
- tor_assert(buf->head->datalen >= 8);
- req->command = (unsigned char) *(buf->head->data+1);
+ }
+ req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE &&
req->command != SOCKS_COMMAND_RESOLVE_PTR) {
@@ -1430,19 +1694,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->command);
return -1;
}
- switch (*(buf->head->data+3)) { /* address type */
+ switch (*(data+3)) { /* address type */
case 1: /* IPv4 address */
case 4: /* IPv6 address */ {
- const int is_v6 = *(buf->head->data+3) == 4;
+ const int is_v6 = *(data+3) == 4;
const unsigned addrlen = is_v6 ? 16 : 4;
log_debug(LD_APP,"socks5: ipv4 address type");
- if (buf->datalen < 6+addrlen) /* ip/port there? */
+ if (datalen < 6+addrlen) {/* ip/port there? */
+ *want_length_out = 6+addrlen;
return 0; /* not yet */
+ }
if (is_v6)
- tor_addr_from_ipv6_bytes(&destaddr, buf->head->data+4);
+ tor_addr_from_ipv6_bytes(&destaddr, data+4);
else
- tor_addr_from_ipv4n(&destaddr, get_uint32(buf->head->data+4));
+ tor_addr_from_ipv4n(&destaddr, get_uint32(data+4));
tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
@@ -1454,8 +1720,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
strlcpy(req->address,tmpbuf,sizeof(req->address));
- req->port = ntohs(get_uint16(buf->head->data+4+addrlen));
- buf_remove_from_front(buf, 6+addrlen);
+ req->port = ntohs(get_uint16(data+4+addrlen));
+ *drain_out = 6+addrlen;
if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
!addressmap_have_mapping(req->address,0)) {
log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
@@ -1471,21 +1737,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
"hostname type. Rejecting.");
return -1;
}
- len = (unsigned char)*(buf->head->data+4);
- if (buf->datalen < 7+len) /* addr/port there? */
+ len = (unsigned char)*(data+4);
+ if (datalen < 7+len) { /* addr/port there? */
+ *want_length_out = 7+len;
return 0; /* not yet */
- buf_pullup(buf, 7+len, 0);
- tor_assert(buf->head->datalen >= 7+len);
+ }
if (len+1 > MAX_SOCKS_ADDR_LEN) {
log_warn(LD_APP,
"socks5 hostname is %d bytes, which doesn't fit in "
"%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN);
return -1;
}
- memcpy(req->address,buf->head->data+5,len);
+ memcpy(req->address,data+5,len);
req->address[len] = 0;
- req->port = ntohs(get_uint16(buf->head->data+5+len));
- buf_remove_from_front(buf, 5+len+2);
+ req->port = ntohs(get_uint16(data+5+len));
+ *drain_out = 5+len+2;
if (!tor_strisprint(req->address) || strchr(req->address,'\"')) {
log_warn(LD_PROTOCOL,
"Your application (using socks5 to port %d) gave Tor "
@@ -1501,7 +1767,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return 1;
default: /* unsupported */
log_warn(LD_APP,"socks5: unsupported address type %d. Rejecting.",
- (int) *(buf->head->data+3));
+ (int) *(data+3));
return -1;
}
tor_assert(0);
@@ -1510,10 +1776,12 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
/* http://archive.socks.permeo.com/protocol/socks4a.protocol */
req->socks_version = 4;
- if (buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */
+ if (datalen < SOCKS4_NETWORK_LEN) {/* basic info available? */
+ *want_length_out = SOCKS4_NETWORK_LEN;
return 0; /* not yet */
- buf_pullup(buf, 1280, 0);
- req->command = (unsigned char) *(buf->head->data+1);
+ }
+ // buf_pullup(buf, 1280, 0);
+ req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE) {
/* not a connect or resolve? we don't support it. (No resolve_ptr with
@@ -1523,8 +1791,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
- req->port = ntohs(get_uint16(buf->head->data+2));
- destip = ntohl(get_uint32(buf->head->data+4));
+ req->port = ntohs(get_uint16(data+2));
+ destip = ntohl(get_uint32(data+4));
if ((!req->port && req->command!=SOCKS_COMMAND_RESOLVE) || !destip) {
log_warn(LD_APP,"socks4: Port or DestIP is zero. Rejecting.");
return -1;
@@ -1544,17 +1812,18 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
socks4_prot = socks4;
}
- next = memchr(buf->head->data+SOCKS4_NETWORK_LEN, 0,
- buf->head->datalen-SOCKS4_NETWORK_LEN);
+ next = memchr(data+SOCKS4_NETWORK_LEN, 0,
+ datalen-SOCKS4_NETWORK_LEN);
if (!next) {
- if (buf->head->datalen >= 1024) {
+ if (datalen >= 1024) {
log_debug(LD_APP, "Socks4 user name too long; rejecting.");
return -1;
}
log_debug(LD_APP,"socks4: Username not here yet.");
+ *want_length_out = datalen+1024; /* ???? */
return 0;
}
- tor_assert(next < CHUNK_WRITE_PTR(buf->head));
+ tor_assert(next < data+datalen);
startaddr = NULL;
if (socks4_prot != socks4a &&
@@ -1565,18 +1834,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
if (socks4_prot == socks4a) {
- if (next+1 == CHUNK_WRITE_PTR(buf->head)) {
+ if (next+1 == data+datalen) {
log_debug(LD_APP,"socks4: No part of destaddr here yet.");
+ *want_length_out = datalen + 1024; /* More than we need, but safe */
return 0;
}
startaddr = next+1;
- next = memchr(startaddr, 0, CHUNK_WRITE_PTR(buf->head)-startaddr);
+ next = memchr(startaddr, 0, data + datalen - startaddr);
if (!next) {
- if (buf->head->datalen >= 1024) {
+ if (datalen >= 1024) {
log_debug(LD_APP,"socks4: Destaddr too long.");
return -1;
}
log_debug(LD_APP,"socks4: Destaddr not all here yet.");
+ *want_length_out = datalen + 1024;
return 0;
}
if (MAX_SOCKS_ADDR_LEN <= next-startaddr) {
@@ -1602,7 +1873,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
/* next points to the final \0 on inbuf */
- buf_remove_from_front(buf, next - buf->head->data + 1);
+ *drain_out = next - data + 1;
return 1;
case 'G': /* get */
@@ -1640,9 +1911,10 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
default: /* version is not socks4 or socks5 */
log_warn(LD_APP,
"Socks version %d not recognized. (Tor is not an http proxy.)",
- *(buf->head->data));
+ *(data));
{
- char *tmp = tor_strndup(buf->head->data, 8); /*XXXX what if longer?*/
+ /* Tell the controller the first 8 bytes. */
+ char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
control_event_client_status(LOG_WARN,
"SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
escaped(tmp));
@@ -1664,21 +1936,67 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int
fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
{
- unsigned char *data;
- size_t addrlen;
-
+ ssize_t drain = 0;
+ int r;
if (buf->datalen < 2)
return 0;
buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
tor_assert(buf->head && buf->head->datalen >= 2);
- data = (unsigned char *) buf->head->data;
+ r = parse_socks_client((uint8_t*)buf->head->data, buf->head->datalen,
+ state, reason, &drain);
+ if (drain > 0)
+ buf_remove_from_front(buf, drain);
+ else if (drain < 0)
+ buf_clear(buf);
+
+ return r;
+}
+
+#ifdef USE_BUFFEREVENTS
+/** As fetch_from_buf_socks_client, buf works on an evbuffer */
+int
+fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
+ char **reason)
+{
+ ssize_t drain = 0;
+ uint8_t *data;
+ size_t datalen;
+ int r;
+
+ /* Linearize the SOCKS response in the buffer, up to 128 bytes.
+ * (parse_socks_client shouldn't need to see anything beyond that.) */
+ datalen = evbuffer_get_length(buf);
+ if (datalen > MAX_SOCKS_MESSAGE_LEN)
+ datalen = MAX_SOCKS_MESSAGE_LEN;
+ data = evbuffer_pullup(buf, datalen);
+
+ r = parse_socks_client(data, datalen, state, reason, &drain);
+ if (drain > 0)
+ evbuffer_drain(buf, drain);
+ else if (drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+
+ return r;
+}
+#endif
+
+/** Implementation logic for fetch_from_*_socks_client. */
+static int
+parse_socks_client(const uint8_t *data, size_t datalen,
+ int state, char **reason,
+ ssize_t *drain_out)
+{
+ unsigned int addrlen;
+ *drain_out = 0;
+ if (datalen < 2)
+ return 0;
switch (state) {
case PROXY_SOCKS4_WANT_CONNECT_OK:
/* Wait for the complete response */
- if (buf->head->datalen < 8)
+ if (datalen < 8)
return 0;
if (data[1] != 0x5a) {
@@ -1687,7 +2005,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
/* Success */
- buf_remove_from_front(buf, 8);
+ *drain_out = 8;
return 1;
case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
@@ -1699,7 +2017,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
@@ -1709,11 +2027,11 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
case 0x00:
log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
"doesn't require authentication.");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case 0x02:
log_info(LD_NET, "SOCKS 5 client: need authentication.");
- buf_clear(buf);
+ *drain_out = -1;
return 2;
/* fall through */
}
@@ -1730,7 +2048,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
log_info(LD_NET, "SOCKS 5 client: authentication successful.");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case PROXY_SOCKS5_WANT_CONNECT_OK:
@@ -1739,7 +2057,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
* the data used */
/* wait for address type field to arrive */
- if (buf->datalen < 4)
+ if (datalen < 4)
return 0;
switch (data[3]) {
@@ -1750,7 +2068,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
addrlen = 16;
break;
case 0x03: /* fqdn (can this happen here?) */
- if (buf->datalen < 5)
+ if (datalen < 5)
return 0;
addrlen = 1 + data[4];
break;
@@ -1760,7 +2078,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
/* wait for address and port */
- if (buf->datalen < 6 + addrlen)
+ if (datalen < 6 + addrlen)
return 0;
if (data[1] != 0x00) {
@@ -1768,7 +2086,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
return -1;
}
- buf_remove_from_front(buf, 6 + addrlen);
+ *drain_out = 6 + addrlen;
return 1;
}
@@ -1794,6 +2112,27 @@ peek_buf_has_control0_command(buf_t *buf)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+int
+peek_evbuffer_has_control0_command(struct evbuffer *buf)
+{
+ int result = 0;
+ if (evbuffer_get_length(buf) >= 4) {
+ int free_out = 0;
+ char *data = NULL;
+ size_t n = inspect_evbuffer(buf, &data, 4, &free_out, NULL);
+ uint16_t cmd;
+ tor_assert(n >= 4);
+ cmd = ntohs(get_uint16(data+2));
+ if (cmd <= 0x14)
+ result = 1;
+ if (free_out)
+ tor_free(data);
+ }
+ return result;
+}
+#endif
+
/** Return the index within <b>buf</b> at which <b>ch</b> first appears,
* or -1 if <b>ch</b> does not appear on buf. */
static off_t
@@ -1811,12 +2150,12 @@ buf_find_offset_of_char(buf_t *buf, char ch)
return -1;
}
-/** Try to read a single LF-terminated line from <b>buf</b>, and write it,
- * NUL-terminated, into the *<b>data_len</b> byte buffer at <b>data_out</b>.
- * Set *<b>data_len</b> to the number of bytes in the line, not counting the
- * terminating NUL. Return 1 if we read a whole line, return 0 if we don't
- * have a whole line yet, and return -1 if the line length exceeds
- * *<b>data_len</b>.
+/** Try to read a single LF-terminated line from <b>buf</b>, and write it
+ * (including the LF), NUL-terminated, into the *<b>data_len</b> byte buffer
+ * at <b>data_out</b>. Set *<b>data_len</b> to the number of bytes in the
+ * line, not counting the terminating NUL. Return 1 if we read a whole line,
+ * return 0 if we don't have a whole line yet, and return -1 if the line
+ * length exceeds *<b>data_len</b>.
*/
int
fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
@@ -1890,6 +2229,59 @@ write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
return 0;
}
+#ifdef USE_BUFFEREVENTS
+int
+write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+ const char *data, size_t data_len,
+ int done)
+{
+ char *next;
+ size_t old_avail, avail;
+ int over = 0, n;
+ struct evbuffer_iovec vec[1];
+ do {
+ {
+ size_t cap = data_len / 4;
+ if (cap < 128)
+ cap = 128;
+ /* XXXX NM this strategy is fragmentation-prone. We should really have
+ * two iovecs, and write first into the one, and then into the
+ * second if the first gets full. */
+ n = evbuffer_reserve_space(buf, cap, vec, 1);
+ tor_assert(n == 1);
+ }
+
+ next = vec[0].iov_base;
+ avail = old_avail = vec[0].iov_len;
+
+ switch (tor_zlib_process(state, &next, &avail, &data, &data_len, done)) {
+ case TOR_ZLIB_DONE:
+ over = 1;
+ break;
+ case TOR_ZLIB_ERR:
+ return -1;
+ case TOR_ZLIB_OK:
+ if (data_len == 0)
+ over = 1;
+ break;
+ case TOR_ZLIB_BUF_FULL:
+ if (avail) {
+ /* Zlib says we need more room (ZLIB_BUF_FULL). Start a new chunk
+ * automatically, whether were going to or not. */
+ }
+ break;
+ }
+
+ /* XXXX possible infinite loop on BUF_FULL. */
+ vec[0].iov_len = old_avail - avail;
+ evbuffer_commit_space(buf, vec, 1);
+
+ } while (!over);
+ check();
+ return 0;
+}
+#endif
+
/** Log an error and exit if <b>buf</b> is corrupted.
*/
void
diff --git a/src/or/buffers.h b/src/or/buffers.h
index e50b9ff6f..613001066 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -24,11 +24,11 @@ size_t buf_datalen(const buf_t *buf);
size_t buf_allocation(const buf_t *buf);
size_t buf_slack(const buf_t *buf);
-int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof,
+int read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
int *socket_error);
int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf);
-int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen);
+int flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen);
int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen);
int write_to_buf(const char *string, size_t string_len, buf_t *buf);
@@ -48,6 +48,23 @@ int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
int peek_buf_has_control0_command(buf_t *buf);
+#ifdef USE_BUFFEREVENTS
+int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto);
+int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
+ int log_sockstype, int safe_socks);
+int fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
+ char **reason);
+int fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete);
+int peek_evbuffer_has_control0_command(struct evbuffer *buf);
+int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+ const char *data, size_t data_len,
+ int done);
+#endif
+
void assert_buf_ok(buf_t *buf);
#ifdef BUFFERS_PRIVATE
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 08bfb9881..4ec45bc08 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -23,6 +23,7 @@
#include "directory.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "policies.h"
#include "relay.h"
@@ -55,8 +56,8 @@ extern circuit_t *global_circuitlist;
/** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just
- * use a routerinfo_t, since we want to remember these even when we
- * don't have a directory. */
+ * use a node_t, since we want to remember these even when we
+ * don't have any directory info. */
typedef struct {
char nickname[MAX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
@@ -95,7 +96,7 @@ static int circuit_deliver_create_cell(circuit_t *circ,
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
-static int count_acceptable_routers(smartlist_t *routers);
+static int count_acceptable_nodes(smartlist_t *routers);
static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static void entry_guards_changed(void);
@@ -262,7 +263,7 @@ circuit_build_times_test_frequency(void)
}
/**
- * Retrieve and bounds-check the cbtmintimeout consensus paramter.
+ * Retrieve and bounds-check the cbtmintimeout consensus parameter.
*
* Effect: This is the minimum allowed timeout value in milliseconds.
* The minimum is to prevent rounding to 0 (we only check once
@@ -678,7 +679,15 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt,
log_notice(LD_CIRC, "The number of circuit times that this Tor version "
"uses to calculate build times is less than the number stored "
"in your state file. Decreasing the circuit time history from "
- "%d to %d.", num_times, CBT_NCIRCUITS_TO_OBSERVE);
+ "%lu to %d.", (unsigned long)num_times,
+ CBT_NCIRCUITS_TO_OBSERVE);
+ }
+
+ if (n > INT_MAX-1) {
+ log_warn(LD_CIRC, "For some insane reasons, you had %lu circuit build "
+ "observations in your state file. That's far too many; probably "
+ "there's a bug here.", (unsigned long)n);
+ n = INT_MAX-1;
}
/* This code can only be run on a compact array */
@@ -1493,7 +1502,7 @@ get_unique_circ_id_by_conn(or_connection_t *conn)
}
/** If <b>verbose</b> is false, allocate and return a comma-separated list of
- * the currently built elements of circuit_t. If <b>verbose</b> is true, also
+ * the currently built elements of <b>circ</b>. If <b>verbose</b> is true, also
* list information about link status in a more verbose format using spaces.
* If <b>verbose_names</b> is false, give nicknames for Named routers and hex
* digests for others; if <b>verbose_names</b> is true, use $DIGEST=Name style
@@ -1524,10 +1533,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
hop = circ->cpath;
do {
- routerinfo_t *ri;
- routerstatus_t *rs;
char *elt;
const char *id;
+ const node_t *node;
if (!hop)
break;
if (!verbose && hop->state != CPATH_STATE_OPEN)
@@ -1537,10 +1545,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
id = hop->extend_info->identity_digest;
if (verbose_names) {
elt = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1);
- if ((ri = router_get_by_digest(id))) {
- router_get_verbose_nickname(elt, ri);
- } else if ((rs = router_get_consensus_status_by_id(id))) {
- routerstatus_get_verbose_nickname(elt, rs);
+ if ((node = node_get_by_id(id))) {
+ node_get_verbose_nickname(node, elt);
} else if (is_legal_nickname(hop->extend_info->nickname)) {
elt[0] = '$';
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
@@ -1552,9 +1558,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
}
} else { /* ! verbose_names */
- if ((ri = router_get_by_digest(id)) &&
- ri->is_named) {
- elt = tor_strdup(hop->extend_info->nickname);
+ node = node_get_by_id(id);
+ if (node && node_is_named(node)) {
+ elt = tor_strdup(node_get_nickname(node));
} else {
elt = tor_malloc(HEX_DIGEST_LEN+2);
elt[0] = '$';
@@ -1582,7 +1588,7 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
}
/** If <b>verbose</b> is false, allocate and return a comma-separated
- * list of the currently built elements of circuit_t. If
+ * list of the currently built elements of <b>circ</b>. If
* <b>verbose</b> is true, also list information about link status in
* a more verbose format using spaces.
*/
@@ -1593,7 +1599,7 @@ circuit_list_path(origin_circuit_t *circ, int verbose)
}
/** Allocate and return a comma-separated list of the currently built elements
- * of circuit_t, giving each as a verbose nickname.
+ * of <b>circ</b>, giving each as a verbose nickname.
*/
char *
circuit_list_path_for_controller(origin_circuit_t *circ)
@@ -1602,7 +1608,7 @@ circuit_list_path_for_controller(origin_circuit_t *circ)
}
/** Log, at severity <b>severity</b>, the nicknames of each router in
- * circ's cpath. Also log the length of the cpath, and the intended
+ * <b>circ</b>'s cpath. Also log the length of the cpath, and the intended
* exit point.
*/
void
@@ -1614,7 +1620,7 @@ circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
}
/** Tell the rep(utation)hist(ory) module about the status of the links
- * in circ. Hops that have become OPEN are marked as successfully
+ * in <b>circ</b>. Hops that have become OPEN are marked as successfully
* extended; the _first_ hop that isn't open (if any) is marked as
* unable to extend.
*/
@@ -1623,31 +1629,28 @@ void
circuit_rep_hist_note_result(origin_circuit_t *circ)
{
crypt_path_t *hop;
- char *prev_digest = NULL;
- routerinfo_t *router;
+ const char *prev_digest = NULL;
hop = circ->cpath;
if (!hop) /* circuit hasn't started building yet. */
return;
if (server_mode(get_options())) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return;
prev_digest = me->cache_info.identity_digest;
}
do {
- router = router_get_by_digest(hop->extend_info->identity_digest);
- if (router) {
+ const node_t *node = node_get_by_id(hop->extend_info->identity_digest);
+ if (node) { /* Why do we check this? We know the identity. -NM XXXX */
if (prev_digest) {
if (hop->state == CPATH_STATE_OPEN)
- rep_hist_note_extend_succeeded(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_succeeded(prev_digest, node->identity);
else {
- rep_hist_note_extend_failed(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_failed(prev_digest, node->identity);
break;
}
}
- prev_digest = router->cache_info.identity_digest;
+ prev_digest = node->identity;
} else {
prev_digest = NULL;
}
@@ -1753,10 +1756,9 @@ circuit_handle_first_hop(origin_circuit_t *circ)
if (!n_conn) {
/* not currently connected in a useful way. */
- const char *name = strlen(firsthop->extend_info->nickname) ?
- firsthop->extend_info->nickname : fmt_addr(&firsthop->extend_info->addr);
log_info(LD_CIRC, "Next router is %s: %s",
- safe_str_client(name), msg?msg:"???");
+ safe_str_client(extend_info_describe(firsthop->extend_info)),
+ msg?msg:"???");
circ->_base.n_hop = extend_info_dup(firsthop->extend_info);
if (should_launch) {
@@ -1917,7 +1919,7 @@ int
inform_testing_reachability(void)
{
char dirbuf[128];
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
control_event_server_status(LOG_NOTICE,
@@ -1946,7 +1948,7 @@ inform_testing_reachability(void)
static INLINE int
should_use_create_fast_for_circuit(origin_circuit_t *circ)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
@@ -1989,7 +1991,7 @@ int
circuit_send_next_onion_skin(origin_circuit_t *circ)
{
crypt_path_t *hop;
- routerinfo_t *router;
+ const node_t *node;
char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
char *onionskin;
size_t payload_len;
@@ -2005,7 +2007,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
else
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
- router = router_get_by_digest(circ->_base.n_conn->identity_digest);
+ node = node_get_by_id(circ->_base.n_conn->identity_digest);
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We are an OR and we know the right onion key: we should
@@ -2039,7 +2041,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
fast ? "CREATE_FAST" : "CREATE",
- router ? router->nickname : "<unnamed>");
+ node ? node_describe(node) : "<unnamed>");
} else {
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
@@ -2081,7 +2083,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
if (circ->build_state->onehop_tunnel)
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0);
if (!can_complete_circuit && !circ->build_state->onehop_tunnel) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
can_complete_circuit=1;
/* FFFF Log a count of known routers here */
log_notice(LD_GENERAL,
@@ -2516,12 +2518,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
*/
static int
new_route_len(uint8_t purpose, extend_info_t *exit,
- smartlist_t *routers)
+ smartlist_t *nodes)
{
int num_acceptable_routers;
int routelen;
- tor_assert(routers);
+ tor_assert(nodes);
routelen = DEFAULT_ROUTE_LEN;
if (exit &&
@@ -2529,10 +2531,10 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
routelen++;
- num_acceptable_routers = count_acceptable_routers(routers);
+ num_acceptable_routers = count_acceptable_nodes(nodes);
log_debug(LD_CIRC,"Chosen route length %d (%d/%d routers suitable).",
- routelen, num_acceptable_routers, smartlist_len(routers));
+ routelen, num_acceptable_routers, smartlist_len(nodes));
if (num_acceptable_routers < 2) {
log_info(LD_CIRC,
@@ -2550,24 +2552,12 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
return routelen;
}
-/** Fetch the list of predicted ports, dup it into a smartlist of
- * uint16_t's, remove the ones that are already handled by an
- * existing circuit, and return it.
- */
+/** Return a newly allocated list of uint16_t * for each predicted port not
+ * handled by a current circuit. */
static smartlist_t *
circuit_get_unhandled_ports(time_t now)
{
- smartlist_t *source = rep_hist_get_predicted_ports(now);
- smartlist_t *dest = smartlist_create();
- uint16_t *tmp;
- int i;
-
- for (i = 0; i < smartlist_len(source); ++i) {
- tmp = tor_malloc(sizeof(uint16_t));
- memcpy(tmp, smartlist_get(source, i), sizeof(uint16_t));
- smartlist_add(dest, tmp);
- }
-
+ smartlist_t *dest = rep_hist_get_predicted_ports(now);
circuit_remove_handled_ports(dest);
return dest;
}
@@ -2601,12 +2591,12 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
return enough;
}
-/** Return 1 if <b>router</b> can handle one or more of the ports in
+/** Return 1 if <b>node</b> can handle one or more of the ports in
* <b>needed_ports</b>, else return 0.
*/
static int
-router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
-{
+node_handles_some_port(const node_t *node, smartlist_t *needed_ports)
+{ /* XXXX MOVE */
int i;
uint16_t port;
@@ -2616,7 +2606,10 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
needed_ports is explicitly a smartlist of uint16_t's */
port = *(uint16_t *)smartlist_get(needed_ports, i);
tor_assert(port);
- r = compare_addr_to_addr_policy(0, port, router->exit_policy);
+ if (node)
+ r = compare_addr_to_node_policy(0, port, node);
+ else
+ continue;
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 1;
}
@@ -2649,18 +2642,17 @@ ap_stream_wants_exit_attention(connection_t *conn)
*
* Return NULL if we can't find any suitable routers.
*/
-static routerinfo_t *
-choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
- int need_capacity)
+static const node_t *
+choose_good_exit_server_general(int need_uptime, int need_capacity)
{
int *n_supported;
- int i;
int n_pending_connections = 0;
smartlist_t *connections;
int best_support = -1;
int n_best_support=0;
- routerinfo_t *router;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ const smartlist_t *the_nodes;
+ const node_t *node=NULL;
connections = get_connection_array();
@@ -2681,10 +2673,11 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*
* -1 means "Don't use this router at all."
*/
- n_supported = tor_malloc(sizeof(int)*smartlist_len(dir->routers));
- for (i = 0; i < smartlist_len(dir->routers); ++i) {/* iterate over routers */
- router = smartlist_get(dir->routers, i);
- if (router_is_me(router)) {
+ the_nodes = nodelist_get_list();
+ n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes));
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ const int i = node_sl_idx;
+ if (router_digest_is_me(node->identity)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s -- it's me.", router->nickname);
/* XXX there's probably a reverse predecessor attack here, but
@@ -2692,41 +2685,45 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*/
continue;
}
- if (!router->is_running || router->is_bad_exit) {
+ if (!node_has_descriptor(node)) {
+ n_supported[i] = -1;
+ continue;
+ }
+ if (!node->is_running || node->is_bad_exit) {
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
-
if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, router)) {
+ routerset_contains_node(options->_ExcludeExitNodesUnion, node)) {
n_supported[i] = -1;
continue; /* user asked us not to use it, no matter what */
}
if (options->ExitNodes &&
- !routerset_contains_router(options->ExitNodes, router)) {
+ !routerset_contains_node(options->ExitNodes, node)) {
n_supported[i] = -1;
continue; /* not one of our chosen exit nodes */
}
- if (router_is_unreliable(router, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
n_supported[i] = -1;
continue; /* skip routers that are not suitable. Don't worry if
* this makes us reject all the possible routers: if so,
* we'll retry later in this function with need_update and
* need_capacity set to 0. */
}
- if (!(router->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
+ if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
/* if it's invalid and we don't want it */
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.",
// router->nickname, i);
continue; /* skip invalid routers */
}
- if (options->ExcludeSingleHopRelays && router->allow_single_hop_exits) {
+ if (options->ExcludeSingleHopRelays &&
+ node_allows_single_hop_exits(node)) {
n_supported[i] = -1;
continue;
}
- if (router_exit_policy_rejects_all(router)) {
+ if (node_exit_policy_rejects_all(node)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
// router->nickname, i);
@@ -2734,11 +2731,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
n_supported[i] = 0;
/* iterate over connections */
- SMARTLIST_FOREACH(connections, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) {
if (!ap_stream_wants_exit_attention(conn))
continue; /* Skip everything but APs in CIRCUIT_WAIT */
- if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) {
+ if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), node)) {
++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]);
@@ -2746,7 +2742,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
// log_fn(LOG_DEBUG,"%s (index %d) would reject this stream.",
// router->nickname, i);
}
- }); /* End looping over connections. */
+ } SMARTLIST_FOREACH_END(conn);
if (n_pending_connections > 0 && n_supported[i] == 0) {
/* Leave best_support at -1 if that's where it is, so we can
* distinguish it later. */
@@ -2763,7 +2759,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* count of equally good routers.*/
++n_best_support;
}
- }
+ } SMARTLIST_FOREACH_END(node);
log_info(LD_CIRC,
"Found %d servers that might support %d/%d pending connections.",
n_best_support, best_support >= 0 ? best_support : 0,
@@ -2774,11 +2770,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
if (best_support > 0) {
smartlist_t *supporting = smartlist_create();
- for (i = 0; i < smartlist_len(dir->routers); i++)
- if (n_supported[i] == best_support)
- smartlist_add(supporting, smartlist_get(dir->routers, i));
+ SMARTLIST_FOREACH(the_nodes, const node_t *, node, {
+ if (n_supported[node_sl_idx] == best_support)
+ smartlist_add(supporting, (void*)node);
+ });
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
smartlist_free(supporting);
} else {
/* Either there are no pending connections, or no routers even seem to
@@ -2796,7 +2793,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
need_capacity?", fast":"",
need_uptime?", stable":"");
tor_free(n_supported);
- return choose_good_exit_server_general(dir, 0, 0);
+ return choose_good_exit_server_general(0, 0);
}
log_notice(LD_CIRC, "All routers are down or won't exit%s -- "
"choosing a doomed exit at random.",
@@ -2807,18 +2804,17 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
for (attempt = 0; attempt < 2; attempt++) {
/* try once to pick only from routers that satisfy a needed port,
* then if there are none, pick from any that support exiting. */
- for (i = 0; i < smartlist_len(dir->routers); i++) {
- router = smartlist_get(dir->routers, i);
- if (n_supported[i] != -1 &&
- (attempt || router_handles_some_port(router, needed_ports))) {
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ if (n_supported[node_sl_idx] != -1 &&
+ (attempt || node_handles_some_port(node, needed_ports))) {
// log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.",
// try, router->nickname);
- smartlist_add(supporting, router);
+ smartlist_add(supporting, (void*)node);
}
- }
+ } SMARTLIST_FOREACH_END(node);
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
- if (router)
+ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ if (node)
break;
smartlist_clear(supporting);
}
@@ -2828,9 +2824,9 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
tor_free(n_supported);
- if (router) {
- log_info(LD_CIRC, "Chose exit server '%s'", router->nickname);
- return router;
+ if (node) {
+ log_info(LD_CIRC, "Chose exit server '%s'", node_describe(node));
+ return node;
}
if (options->ExitNodes) {
log_warn(LD_CIRC,
@@ -2851,12 +2847,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* For client-side rendezvous circuits, choose a random node, weighted
* toward the preferences in 'options'.
*/
-static routerinfo_t *
-choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
+static const node_t *
+choose_good_exit_server(uint8_t purpose,
int need_uptime, int need_capacity, int is_internal)
{
- or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_DESC;
if (need_uptime)
flags |= CRN_NEED_UPTIME;
if (need_capacity)
@@ -2869,7 +2865,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
if (is_internal) /* pick it like a middle hop */
return router_choose_random_node(NULL, options->ExcludeNodes, flags);
else
- return choose_good_exit_server_general(dir,need_uptime,need_capacity);
+ return choose_good_exit_server_general(need_uptime,need_capacity);
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS)
flags |= CRN_ALLOW_INVALID;
@@ -2885,7 +2881,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
static void
warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
routerset_t *rs = options->ExcludeNodes;
const char *description;
uint8_t purpose = circ->_base.purpose;
@@ -2936,7 +2932,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit)
log_warn(LD_BUG, "Using %s '%s' which is listed in ExcludeNodes%s, "
"even though StrictNodes is set. Please report. "
"(Circuit purpose: %s)",
- description, exit->nickname,
+ description, extend_info_describe(exit),
rs==options->ExcludeNodes?"":" or ExcludeExitNodes",
circuit_purpose_to_string(purpose));
} else {
@@ -2945,7 +2941,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit)
"prevent this (and possibly break your Tor functionality), "
"set the StrictNodes configuration option. "
"(Circuit purpose: %s)",
- description, exit->nickname,
+ description, extend_info_describe(exit),
rs==options->ExcludeNodes?"":" or ExcludeExitNodes",
circuit_purpose_to_string(purpose));
}
@@ -2962,13 +2958,12 @@ static int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
{
cpath_build_state_t *state = circ->build_state;
- routerlist_t *rl = router_get_routerlist();
if (state->onehop_tunnel) {
log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel.");
state->desired_path_len = 1;
} else {
- int r = new_route_len(circ->_base.purpose, exit, rl->routers);
+ int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list());
if (r < 1) /* must be at least 1 */
return -1;
state->desired_path_len = r;
@@ -2976,17 +2971,19 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
if (exit) { /* the circuit-builder pre-requested one */
warn_if_last_router_excluded(circ, exit);
- log_info(LD_CIRC,"Using requested exit node '%s'", exit->nickname);
+ log_info(LD_CIRC,"Using requested exit node '%s'",
+ extend_info_describe(exit));
exit = extend_info_dup(exit);
} else { /* we have to decide one */
- routerinfo_t *router =
- choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
+ const node_t *node =
+ choose_good_exit_server(circ->_base.purpose, state->need_uptime,
state->need_capacity, state->is_internal);
- if (!router) {
+ if (!node) {
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
}
- exit = extend_info_from_router(router);
+ exit = extend_info_from_node(node);
+ tor_assert(exit);
}
state->chosen_exit = exit;
return 0;
@@ -3025,8 +3022,8 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit)
circuit_append_new_exit(circ, exit);
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
if ((err_reason = circuit_send_next_onion_skin(circ))<0) {
- log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.",
- exit->nickname);
+ log_warn(LD_CIRC, "Couldn't extend circuit to new point %s.",
+ extend_info_describe(exit));
circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
return -1;
}
@@ -3037,35 +3034,30 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit)
* and available for building circuits through.
*/
static int
-count_acceptable_routers(smartlist_t *routers)
+count_acceptable_nodes(smartlist_t *nodes)
{
- int i, n;
int num=0;
- routerinfo_t *r;
- n = smartlist_len(routers);
- for (i=0;i<n;i++) {
- r = smartlist_get(routers, i);
-// log_debug(LD_CIRC,
+ SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
+ // log_debug(LD_CIRC,
// "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname);
- if (r->is_running == 0) {
+ if (! node->is_running)
// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
- goto next_i_loop;
- }
- if (r->is_valid == 0) {
+ continue;
+ if (! node->is_valid)
// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
- goto next_i_loop;
+ continue;
+ if (! node_has_descriptor(node))
+ continue;
/* XXX This clause makes us count incorrectly: if AllowInvalidRouters
* allows this node in some places, then we're getting an inaccurate
* count. For now, be conservative and don't count it. But later we
* should try to be smarter. */
- }
- num++;
+ ++num;
+ } SMARTLIST_FOREACH_END(node);
+
// log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num);
- next_i_loop:
- ; /* C requires an explicit statement after the label */
- }
return num;
}
@@ -3093,31 +3085,31 @@ onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
* circuit. In particular, make sure we don't pick the exit node or its
* family, and make sure we don't duplicate any previous nodes or their
* families. */
-static routerinfo_t *
+static const node_t *
choose_good_middle_server(uint8_t purpose,
cpath_build_state_t *state,
crypt_path_t *head,
int cur_len)
{
int i;
- routerinfo_t *r, *choice;
+ const node_t *r, *choice;
crypt_path_t *cpath;
smartlist_t *excluded;
- or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_DESC;
tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose &&
purpose <= _CIRCUIT_PURPOSE_MAX);
log_debug(LD_CIRC, "Contemplating intermediate hop: random choice.");
excluded = smartlist_create();
- if ((r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((r = build_state_get_exit_node(state))) {
+ smartlist_add(excluded, (void*) r);
+ nodelist_add_node_family(excluded, r);
}
for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) {
- if ((r = router_get_by_digest(cpath->extend_info->identity_digest))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
+ smartlist_add(excluded, (void*)r);
+ nodelist_add_node_family(excluded, r);
}
}
@@ -3140,44 +3132,45 @@ choose_good_middle_server(uint8_t purpose,
* If <b>state</b> is NULL, we're choosing a router to serve as an entry
* guard, not for any particular circuit.
*/
-static routerinfo_t *
+static const node_t *
choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
{
- routerinfo_t *r, *choice;
+ const node_t *choice;
smartlist_t *excluded;
- or_options_t *options = get_options();
- router_crn_flags_t flags = CRN_NEED_GUARD;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC;
+ const node_t *node;
if (state && options->UseEntryGuards &&
(purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) {
+ /* This is request for an entry server to use for a regular circuit,
+ * and we use entry guard nodes. Just return one of the guard nodes. */
return choose_random_entry(state);
}
excluded = smartlist_create();
- if (state && (r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if (state && (node = build_state_get_exit_node(state))) {
+ /* Exclude the exit node from the state, if we have one. Also exclude its
+ * family. */
+ smartlist_add(excluded, (void*)node);
+ nodelist_add_node_family(excluded, node);
}
if (firewall_is_fascist_or()) {
- /*XXXX This could slow things down a lot; use a smarter implementation */
- /* exclude all ORs that listen on the wrong port, if anybody notices. */
- routerlist_t *rl = router_get_routerlist();
- int i;
-
- for (i=0; i < smartlist_len(rl->routers); i++) {
- r = smartlist_get(rl->routers, i);
- if (!fascist_firewall_allows_or(r))
- smartlist_add(excluded, r);
- }
+ /* Exclude all ORs that we can't reach through our firewall */
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (!fascist_firewall_allows_node(node))
+ smartlist_add(excluded, (void*)node);
+ });
}
- /* and exclude current entry guards, if applicable */
+ /* and exclude current entry guards and their families, if applicable */
if (options->UseEntryGuards && entry_guards) {
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
{
- if ((r = router_get_by_digest(entry->identity))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((node = node_get_by_id(entry->identity))) {
+ smartlist_add(excluded, (void*)node);
+ nodelist_add_node_family(excluded, node);
}
});
}
@@ -3233,14 +3226,18 @@ onion_extend_cpath(origin_circuit_t *circ)
if (cur_len == state->desired_path_len - 1) { /* Picking last node */
info = extend_info_dup(state->chosen_exit);
} else if (cur_len == 0) { /* picking first node */
- routerinfo_t *r = choose_good_entry_server(purpose, state);
- if (r)
- info = extend_info_from_router(r);
+ const node_t *r = choose_good_entry_server(purpose, state);
+ if (r) {
+ info = extend_info_from_node(r);
+ tor_assert(info);
+ }
} else {
- routerinfo_t *r =
+ const node_t *r =
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
- if (r)
- info = extend_info_from_router(r);
+ if (r) {
+ info = extend_info_from_node(r);
+ tor_assert(info);
+ }
}
if (!info) {
@@ -3250,7 +3247,8 @@ onion_extend_cpath(origin_circuit_t *circ)
}
log_debug(LD_CIRC,"Chose router %s for hop %d (exit is %s)",
- info->nickname, cur_len+1, build_state_get_exit_nickname(state));
+ extend_info_describe(info),
+ cur_len+1, build_state_get_exit_nickname(state));
onion_append_hop(&circ->cpath, info);
extend_info_free(info);
@@ -3299,7 +3297,7 @@ extend_info_alloc(const char *nickname, const char *digest,
/** Allocate and return a new extend_info_t that can be used to build a
* circuit to or through the router <b>r</b>. */
extend_info_t *
-extend_info_from_router(routerinfo_t *r)
+extend_info_from_router(const routerinfo_t *r)
{
tor_addr_t addr;
tor_assert(r);
@@ -3308,6 +3306,29 @@ extend_info_from_router(routerinfo_t *r)
r->onion_pkey, &addr, r->or_port);
}
+/** Allocate and return a new extend_info that can be used to build a ircuit
+ * to or through the node <b>node</b>. May return NULL if there is not
+ * enough info about <b>node</b> to extend to it--for example, if there
+ * is no routerinfo_t or microdesc_t.
+ **/
+extend_info_t *
+extend_info_from_node(const node_t *node)
+{
+ if (node->ri) {
+ return extend_info_from_router(node->ri);
+ } else if (node->rs && node->md) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return extend_info_alloc(node->rs->nickname,
+ node->identity,
+ node->md->onion_pkey,
+ &addr,
+ node->rs->or_port);
+ } else {
+ return NULL;
+ }
+}
+
/** Release storage held by an extend_info_t struct. */
void
extend_info_free(extend_info_t *info)
@@ -3338,12 +3359,12 @@ extend_info_dup(extend_info_t *info)
* If there is no chosen exit, or if we don't know the routerinfo_t for
* the chosen exit, return NULL.
*/
-routerinfo_t *
-build_state_get_exit_router(cpath_build_state_t *state)
+const node_t *
+build_state_get_exit_node(cpath_build_state_t *state)
{
if (!state || !state->chosen_exit)
return NULL;
- return router_get_by_digest(state->chosen_exit->identity_digest);
+ return node_get_by_id(state->chosen_exit->identity_digest);
}
/** Return the nickname for the chosen exit router in <b>state</b>. If
@@ -3365,10 +3386,10 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
*
* If it's not usable, set *<b>reason</b> to a static string explaining why.
*/
-/*XXXX take a routerstatus, not a routerinfo. */
static int
-entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
- time_t now, or_options_t *options, const char **reason)
+entry_guard_set_status(entry_guard_t *e, const node_t *node,
+ time_t now, const or_options_t *options,
+ const char **reason)
{
char buf[HEX_DIGEST_LEN+1];
int changed = 0;
@@ -3376,16 +3397,19 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
*reason = NULL;
/* Do we want to mark this guard as bad? */
- if (!ri)
+ if (!node)
*reason = "unlisted";
- else if (!ri->is_running)
+ else if (!node->is_running)
*reason = "down";
- else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE)
+ else if (options->UseBridges && (!node->ri ||
+ node->ri->purpose != ROUTER_PURPOSE_BRIDGE))
*reason = "not a bridge";
- else if (!options->UseBridges && !ri->is_possible_guard &&
- !routerset_contains_router(options->EntryNodes,ri))
+ else if (options->UseBridges && !node_is_a_configured_bridge(node))
+ *reason = "not a configured bridge";
+ else if (!options->UseBridges && !node->is_possible_guard &&
+ !routerset_contains_node(options->EntryNodes,node))
*reason = "not recommended as a guard";
- else if (routerset_contains_router(options->ExcludeNodes, ri))
+ else if (routerset_contains_node(options->ExcludeNodes, node))
*reason = "excluded";
if (*reason && ! e->bad_since) {
@@ -3429,7 +3453,7 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
return now > (e->last_attempted + 36*60*60);
}
-/** Return the router corresponding to <b>e</b>, if <b>e</b> is
+/** Return the node corresponding to <b>e</b>, if <b>e</b> is
* working well enough that we are willing to use it as an entry
* right now. (Else return NULL.) In particular, it must be
* - Listed as either up or never yet contacted;
@@ -3443,12 +3467,12 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
*
* If the answer is no, set *<b>msg</b> to an explanation of why.
*/
-static INLINE routerinfo_t *
+static INLINE const node_t *
entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
int assume_reachable, const char **msg)
{
- routerinfo_t *r;
- or_options_t *options = get_options();
+ const node_t *node;
+ const or_options_t *options = get_options();
tor_assert(msg);
if (e->bad_since) {
@@ -3461,33 +3485,40 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
*msg = "unreachable";
return NULL;
}
- r = router_get_by_digest(e->identity);
- if (!r) {
+ node = node_get_by_id(e->identity);
+ if (!node || !node_has_descriptor(node)) {
*msg = "no descriptor";
return NULL;
}
- if (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) {
- *msg = "not a bridge";
- return NULL;
- }
- if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) {
- *msg = "not general-purpose";
- return NULL;
+ if (get_options()->UseBridges) {
+ if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) {
+ *msg = "not a bridge";
+ return NULL;
+ }
+ if (!node_is_a_configured_bridge(node)) {
+ *msg = "not a configured bridge";
+ return NULL;
+ }
+ } else { /* !get_options()->UseBridges */
+ if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) {
+ *msg = "not general-purpose";
+ return NULL;
+ }
}
if (options->EntryNodes &&
- routerset_contains_router(options->EntryNodes, r)) {
+ routerset_contains_node(options->EntryNodes, node)) {
/* they asked for it, they get it */
need_uptime = need_capacity = 0;
}
- if (router_is_unreliable(r, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
*msg = "not fast/stable";
return NULL;
}
- if (!fascist_firewall_allows_or(r)) {
+ if (!fascist_firewall_allows_node(node)) {
*msg = "unreachable by config";
return NULL;
}
- return r;
+ return node;
}
/** Return the number of entry guards that we think are usable. */
@@ -3526,20 +3557,24 @@ log_entry_guards(int severity)
smartlist_t *elements = smartlist_create();
char *s;
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e)
{
const char *msg = NULL;
char *cp;
if (entry_is_live(e, 0, 1, 0, &msg))
- tor_asprintf(&cp, "%s (up %s)",
+ tor_asprintf(&cp, "%s [%s] (up %s)",
e->nickname,
+ hex_str(e->identity, DIGEST_LEN),
e->made_contact ? "made-contact" : "never-contacted");
else
- tor_asprintf(&cp, "%s (%s, %s)",
- e->nickname, msg,
+ tor_asprintf(&cp, "%s [%s] (%s, %s)",
+ e->nickname,
+ hex_str(e->identity, DIGEST_LEN),
+ msg,
e->made_contact ? "made-contact" : "never-contacted");
smartlist_add(elements, cp);
- });
+ }
+ SMARTLIST_FOREACH_END(e);
s = smartlist_join_strings(elements, ",", 0, NULL);
SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp));
@@ -3563,7 +3598,7 @@ control_event_guard_deferred(void)
#if 0
int n = 0;
const char *msg;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!entry_guards)
return;
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
@@ -3585,15 +3620,15 @@ control_event_guard_deferred(void)
* If <b>chosen</b> is defined, use that one, and if it's not
* already in our entry_guards list, put it at the *beginning*.
* Else, put the one we pick at the end of the list. */
-static routerinfo_t *
-add_an_entry_guard(routerinfo_t *chosen, int reset_status)
+static const node_t *
+add_an_entry_guard(const node_t *chosen, int reset_status)
{
- routerinfo_t *router;
+ const node_t *node;
entry_guard_t *entry;
if (chosen) {
- router = chosen;
- entry = is_an_entry_guard(router->cache_info.identity_digest);
+ node = chosen;
+ entry = is_an_entry_guard(node->identity);
if (entry) {
if (reset_status) {
entry->bad_since = 0;
@@ -3602,14 +3637,15 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
return NULL;
}
} else {
- router = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
- if (!router)
+ node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
+ if (!node)
return NULL;
}
entry = tor_malloc_zero(sizeof(entry_guard_t));
- log_info(LD_CIRC, "Chose '%s' as new entry guard.", router->nickname);
- strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname));
- memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN);
+ log_info(LD_CIRC, "Chose %s as new entry guard.",
+ node_describe(node));
+ strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname));
+ memcpy(entry->identity, node->identity, DIGEST_LEN);
/* Choose expiry time smudged over the past month. The goal here
* is to a) spread out when Tor clients rotate their guards, so they
* don't all select them on the same day, and b) avoid leaving a
@@ -3624,13 +3660,13 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
log_entry_guards(LOG_INFO);
- return router;
+ return node;
}
/** If the use of entry guards is configured, choose more entry guards
* until we have enough in the list. */
static void
-pick_entry_guards(or_options_t *options)
+pick_entry_guards(const or_options_t *options)
{
int changed = 0;
@@ -3763,10 +3799,9 @@ remove_dead_entry_guards(time_t now)
* think that things are unlisted.
*/
void
-entry_guards_compute_status(or_options_t *options, time_t now)
+entry_guards_compute_status(const or_options_t *options, time_t now)
{
int changed = 0;
- int severity = LOG_DEBUG;
digestmap_t *reasons;
if (! entry_guards)
@@ -3778,7 +3813,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
reasons = digestmap_new();
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry)
{
- routerinfo_t *r = router_get_by_digest(entry->identity);
+ const node_t *r = node_get_by_id(entry->identity);
const char *reason = NULL;
if (entry_guard_set_status(entry, r, now, options, &reason))
changed = 1;
@@ -3793,15 +3828,14 @@ entry_guards_compute_status(or_options_t *options, time_t now)
if (remove_dead_entry_guards(now))
changed = 1;
- severity = changed ? LOG_DEBUG : LOG_INFO;
-
if (changed) {
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *reason = digestmap_get(reasons, entry->identity);
const char *live_msg = "";
- routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
- log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s%s%s, and %s%s.",
+ const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
+ log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.",
entry->nickname,
+ hex_str(entry->identity, DIGEST_LEN),
entry->unreachable_since ? "unreachable" : "reachable",
entry->bad_since ? "unusable" : "usable",
reason ? ", ": "",
@@ -3916,7 +3950,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
break;
if (e->made_contact) {
const char *msg;
- routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg);
+ const node_t *r = entry_is_live(e, 0, 1, 1, &msg);
if (r && e->unreachable_since) {
refuse_conn = 1;
e->can_retry = 1;
@@ -3955,9 +3989,9 @@ entry_nodes_should_be_added(void)
/** Add all nodes in EntryNodes that aren't currently guard nodes to the list
* of guard nodes, at the front. */
static void
-entry_guards_prepend_from_config(or_options_t *options)
+entry_guards_prepend_from_config(const or_options_t *options)
{
- smartlist_t *entry_routers, *entry_fps;
+ smartlist_t *entry_nodes, *entry_fps;
smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
tor_assert(entry_guards);
@@ -3977,7 +4011,7 @@ entry_guards_prepend_from_config(or_options_t *options)
tor_free(string);
}
- entry_routers = smartlist_create();
+ entry_nodes = smartlist_create();
entry_fps = smartlist_create();
old_entry_guards_on_list = smartlist_create();
old_entry_guards_not_on_list = smartlist_create();
@@ -3990,10 +4024,11 @@ entry_guards_prepend_from_config(or_options_t *options)
* Perhaps we should do this calculation once whenever the list of routers
* changes or the entrynodes setting changes.
*/
- routerset_get_all_routers(entry_routers, options->EntryNodes,
- options->ExcludeNodes, 0);
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri,
- smartlist_add(entry_fps,ri->cache_info.identity_digest));
+ routerset_get_all_nodes(entry_nodes, options->EntryNodes,
+ options->ExcludeNodes, 0);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
+ smartlist_add(entry_fps, (void*)node->identity));
+
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, {
if (smartlist_digest_isin(entry_fps, e->identity))
smartlist_add(old_entry_guards_on_list, e);
@@ -4002,9 +4037,9 @@ entry_guards_prepend_from_config(or_options_t *options)
});
/* Remove all currently configured entry guards from entry_routers. */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- if (is_an_entry_guard(ri->cache_info.identity_digest)) {
- SMARTLIST_DEL_CURRENT(entry_routers, ri);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
+ if (is_an_entry_guard(node->identity)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
}
});
@@ -4013,15 +4048,15 @@ entry_guards_prepend_from_config(or_options_t *options)
/* First, the previously configured guards that are in EntryNodes. */
smartlist_add_all(entry_guards, old_entry_guards_on_list);
/* Next, the rest of EntryNodes */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- add_an_entry_guard(ri, 0);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
+ add_an_entry_guard(node, 0);
});
/* Finally, free the remaining previously configured guards that are not in
* EntryNodes. */
SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
entry_guard_free(e));
- smartlist_free(entry_routers);
+ smartlist_free(entry_nodes);
smartlist_free(entry_fps);
smartlist_free(old_entry_guards_on_list);
smartlist_free(old_entry_guards_not_on_list);
@@ -4033,7 +4068,7 @@ entry_guards_prepend_from_config(or_options_t *options)
* list already and we must stick to it.
*/
int
-entry_list_is_constrained(or_options_t *options)
+entry_list_is_constrained(const or_options_t *options)
{
if (options->EntryNodes)
return 1;
@@ -4047,20 +4082,21 @@ entry_list_is_constrained(or_options_t *options)
* make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random
* guard (likely a bridge). */
-routerinfo_t *
+const node_t *
choose_random_entry(cpath_build_state_t *state)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *live_entry_guards = smartlist_create();
smartlist_t *exit_family = smartlist_create();
- routerinfo_t *chosen_exit = state?build_state_get_exit_router(state) : NULL;
- routerinfo_t *r = NULL;
+ const node_t *chosen_exit =
+ state?build_state_get_exit_node(state) : NULL;
+ const node_t *node = NULL;
int need_uptime = state ? state->need_uptime : 0;
int need_capacity = state ? state->need_capacity : 0;
int preferred_min, consider_exit_family = 0;
if (chosen_exit) {
- routerlist_add_family(exit_family, chosen_exit);
+ nodelist_add_node_family(exit_family, chosen_exit);
consider_exit_family = 1;
}
@@ -4076,19 +4112,18 @@ choose_random_entry(cpath_build_state_t *state)
retry:
smartlist_clear(live_entry_guards);
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
- {
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *msg;
- r = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
- if (!r)
+ node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
+ if (!node)
continue; /* down, no point */
- if (r == chosen_exit)
+ if (node == chosen_exit)
continue; /* don't pick the same node for entry and exit */
- if (consider_exit_family && smartlist_isin(exit_family, r))
+ if (consider_exit_family && smartlist_isin(exit_family, node))
continue; /* avoid relays that are family members of our exit */
#if 0 /* since EntryNodes is always strict now, this clause is moot */
if (options->EntryNodes &&
- !routerset_contains_router(options->EntryNodes, r)) {
+ !routerset_contains_node(options->EntryNodes, node)) {
/* We've come to the end of our preferred entry nodes. */
if (smartlist_len(live_entry_guards))
goto choose_and_finish; /* only choose from the ones we like */
@@ -4102,7 +4137,7 @@ choose_random_entry(cpath_build_state_t *state)
}
}
#endif
- smartlist_add(live_entry_guards, r);
+ smartlist_add(live_entry_guards, (void*)node);
if (!entry->made_contact) {
/* Always start with the first not-yet-contacted entry
* guard. Otherwise we might add several new ones, pick
@@ -4112,7 +4147,7 @@ choose_random_entry(cpath_build_state_t *state)
}
if (smartlist_len(live_entry_guards) >= options->NumEntryGuards)
break; /* we have enough */
- });
+ } SMARTLIST_FOREACH_END(entry);
if (entry_list_is_constrained(options)) {
/* If we prefer the entry nodes we've got, and we have at least
@@ -4132,8 +4167,8 @@ choose_random_entry(cpath_build_state_t *state)
/* XXX if guard doesn't imply fast and stable, then we need
* to tell add_an_entry_guard below what we want, or it might
* be a long time til we get it. -RD */
- r = add_an_entry_guard(NULL, 0);
- if (r) {
+ node = add_an_entry_guard(NULL, 0);
+ if (node) {
entry_guards_changed();
/* XXX we start over here in case the new node we added shares
* a family with our exit node. There's a chance that we'll just
@@ -4143,11 +4178,11 @@ choose_random_entry(cpath_build_state_t *state)
goto retry;
}
}
- if (!r && need_uptime) {
+ if (!node && need_uptime) {
need_uptime = 0; /* try without that requirement */
goto retry;
}
- if (!r && need_capacity) {
+ if (!node && need_capacity) {
/* still no? last attempt, try without requiring capacity */
need_capacity = 0;
goto retry;
@@ -4156,10 +4191,10 @@ choose_random_entry(cpath_build_state_t *state)
/* Removing this retry logic: if we only allow one exit, and it is in the
same family as all our entries, then we are just plain not going to win
here. */
- if (!r && entry_list_is_constrained(options) && consider_exit_family) {
- /* still no? if we're using bridges,
- * and our chosen exit is in the same family as all our
- * bridges, then be flexible about families. */
+ if (!node && entry_list_is_constrained(options) && consider_exit_family) {
+ /* still no? if we're using bridges or have strictentrynodes
+ * set, and our chosen exit is in the same family as all our
+ * bridges/entry guards, then be flexible about families. */
consider_exit_family = 0;
goto retry;
}
@@ -4171,16 +4206,16 @@ choose_random_entry(cpath_build_state_t *state)
if (entry_list_is_constrained(options)) {
/* We need to weight by bandwidth, because our bridges or entryguards
* were not already selected proportional to their bandwidth. */
- r = routerlist_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
+ node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
} else {
/* We choose uniformly at random here, because choose_good_entry_server()
* already weights its choices by bandwidth, so we don't want to
* *double*-weight our guard selection. */
- r = smartlist_choose(live_entry_guards);
+ node = smartlist_choose(live_entry_guards);
}
smartlist_free(live_entry_guards);
smartlist_free(exit_family);
- return r;
+ return node;
}
/** Parse <b>state</b> and learn about the entry guards it describes.
@@ -4427,7 +4462,7 @@ getinfo_helper_entry_guards(control_connection_t *conn,
char *c = tor_malloc(len);
const char *status = NULL;
time_t when = 0;
- routerinfo_t *ri;
+ const node_t *node;
if (!e->made_contact) {
status = "never-connected";
@@ -4438,9 +4473,9 @@ getinfo_helper_entry_guards(control_connection_t *conn,
status = "up";
}
- ri = router_get_by_digest(e->identity);
- if (ri) {
- router_get_verbose_nickname(nbuf, ri);
+ node = node_get_by_id(e->identity);
+ if (node) {
+ node_get_verbose_nickname(node, nbuf);
} else {
nbuf[0] = '$';
base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN);
@@ -4549,7 +4584,7 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
* it up via router descriptor <b>ri</b>. */
static bridge_info_t *
-get_configured_bridge_by_routerinfo(routerinfo_t *ri)
+get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -4559,11 +4594,29 @@ get_configured_bridge_by_routerinfo(routerinfo_t *ri)
/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
int
-routerinfo_is_a_configured_bridge(routerinfo_t *ri)
+routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
{
return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
}
+/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */
+int
+node_is_a_configured_bridge(const node_t *node)
+{
+ tor_addr_t addr;
+ uint16_t orport;
+ if (!node)
+ return 0;
+ if (node_get_addr(node, &addr) < 0)
+ return 0;
+ orport = node_get_orport(node);
+ if (orport == 0)
+ return 0;
+
+ return get_configured_bridge_by_addr_port_digest(
+ &addr, orport, node->identity) != NULL;
+}
+
/** We made a connection to a router at <b>addr</b>:<b>port</b>
* without knowing its digest. Its digest turned out to be <b>digest</b>.
* If it was a bridge, and we still don't know its digest, record it.
@@ -4642,7 +4695,7 @@ static void
launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
{
char *address;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (connection_get_by_type_addr_port_purpose(
CONN_TYPE_DIR, &bridge->addr, bridge->port,
@@ -4683,9 +4736,9 @@ retry_bridge_descriptor_fetch_directly(const char *digest)
* descriptor, fetch a new copy of its descriptor -- either directly
* from the bridge or via a bridge authority. */
void
-fetch_bridge_descriptors(or_options_t *options, time_t now)
+fetch_bridge_descriptors(const or_options_t *options, time_t now)
{
- int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY);
+ int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO);
int ask_bridge_directly;
int can_use_bridge_authority;
@@ -4750,26 +4803,55 @@ fetch_bridge_descriptors(or_options_t *options, time_t now)
}
/** If our <b>bridge</b> is configured to be a different address than
- * the bridge gives in its routerinfo <b>ri</b>, rewrite the routerinfo
+ * the bridge gives in <b>node</b>, rewrite the routerinfo
* we received to use the address we meant to use. Now we handle
* multihomed bridges better.
*/
static void
-rewrite_routerinfo_address_for_bridge(bridge_info_t *bridge, routerinfo_t *ri)
+rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
{
+ /* XXXX move this function. */
+ /* XXXX overridden addresses should really live in the node_t, so that the
+ * routerinfo_t and the microdesc_t can be immutable. But we can only
+ * do that safely if we know that no function that connects to an OR
+ * does so through an address from any source other than node_get_addr().
+ */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
- if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == ri->or_port)
- return; /* they match, so no need to do anything */
+ if (node->ri) {
+ routerinfo_t *ri = node->ri;
+ tor_addr_from_ipv4h(&addr, ri->addr);
- ri->addr = tor_addr_to_ipv4h(&bridge->addr);
- tor_free(ri->address);
- ri->address = tor_dup_ip(ri->addr);
- ri->or_port = bridge->port;
- log_info(LD_DIR, "Adjusted bridge '%s' to match configured address %s:%d.",
- ri->nickname, ri->address, ri->or_port);
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == ri->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ ri->addr = tor_addr_to_ipv4h(&bridge->addr);
+ tor_free(ri->address);
+ ri->address = tor_dup_ip(ri->addr);
+ ri->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerinfo for '%s' to match configured "
+ "address %s:%d.",
+ ri->nickname, ri->address, ri->or_port);
+ }
+ }
+ if (node->rs) {
+ routerstatus_t *rs = node->rs;
+ tor_addr_from_ipv4h(&addr, rs->addr);
+
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == rs->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ rs->addr = tor_addr_to_ipv4h(&bridge->addr);
+ rs->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerstatus for '%s' to match "
+ "configured address %s:%d.",
+ rs->nickname, fmt_addr(&bridge->addr), rs->or_port);
+ }
+ }
}
/** We just learned a descriptor for a bridge. See if that
@@ -4783,16 +4865,19 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
int first = !any_bridge_descriptors_known();
bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
time_t now = time(NULL);
- ri->is_running = 1;
+ router_set_status(ri->cache_info.identity_digest, 1);
if (bridge) { /* if we actually want to use this one */
+ node_t *node;
/* it's here; schedule its re-fetch for a long time from now. */
if (!from_cache)
download_status_reset(&bridge->fetch_status);
- rewrite_routerinfo_address_for_bridge(bridge, ri);
+ node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
+ rewrite_node_address_for_bridge(bridge, node);
+ add_an_entry_guard(node, 1);
- add_an_entry_guard(ri, 1);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
from_cache ? "cached" : "fresh");
/* set entry->made_contact so if it goes down we don't drop it from
@@ -4845,21 +4930,20 @@ any_pending_bridge_descriptor_fetches(void)
* down. Else return 0. If <b>act</b> is 1, then mark the down guards
* up; else just observe and report. */
static int
-entries_retry_helper(or_options_t *options, int act)
+entries_retry_helper(const or_options_t *options, int act)
{
- routerinfo_t *ri;
+ const node_t *node;
int any_known = 0;
int any_running = 0;
- int purpose = options->UseBridges ?
- ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
+ int need_bridges = options->UseBridges != 0;
if (!entry_guards)
entry_guards = smartlist_create();
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
- {
- ri = router_get_by_digest(e->identity);
- if (ri && ri->purpose == purpose) {
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ node = node_get_by_id(e->identity);
+ if (node && node_has_descriptor(node) &&
+ node_is_bridge(node) == need_bridges) {
any_known = 1;
- if (ri->is_running)
+ if (node->is_running)
any_running = 1; /* some entry is both known and running */
else if (act) {
/* Mark all current connections to this OR as unhealthy, since
@@ -4868,15 +4952,15 @@ entries_retry_helper(or_options_t *options, int act)
* the node down and undermine the retry attempt. We mark even
* the established conns, since if the network just came back
* we'll want to attach circuits to fresh conns. */
- connection_or_set_bad_connections(ri->cache_info.identity_digest, 1);
+ connection_or_set_bad_connections(node->identity, 1);
/* mark this entry node for retry */
- router_set_status(ri->cache_info.identity_digest, 1);
+ router_set_status(node->identity, 1);
e->can_retry = 1;
e->bad_since = 0;
}
}
- });
+ } SMARTLIST_FOREACH_END(e);
log_debug(LD_DIR, "%d: any_known %d, any_running %d",
act, any_known, any_running);
return any_known && !any_running;
@@ -4885,7 +4969,7 @@ entries_retry_helper(or_options_t *options, int act)
/** Do we know any descriptors for our bridges / entrynodes, and are
* all the ones we have descriptors for down? */
int
-entries_known_but_down(or_options_t *options)
+entries_known_but_down(const or_options_t *options)
{
tor_assert(entry_list_is_constrained(options));
return entries_retry_helper(options, 0);
@@ -4893,7 +4977,7 @@ entries_known_but_down(or_options_t *options)
/** Mark all down known bridges / entrynodes up. */
void
-entries_retry_all(or_options_t *options)
+entries_retry_all(const or_options_t *options)
{
tor_assert(entry_list_is_constrained(options));
entries_retry_helper(options, 1);
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 0e673e1c0..caa8a6738 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -44,18 +44,19 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
crypto_pk_env_t *onion_key,
const tor_addr_t *addr, uint16_t port);
-extend_info_t *extend_info_from_router(routerinfo_t *r);
+extend_info_t *extend_info_from_router(const routerinfo_t *r);
+extend_info_t *extend_info_from_node(const node_t *node);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
-routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
+const node_t *build_state_get_exit_node(cpath_build_state_t *state);
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
-void entry_guards_compute_status(or_options_t *options, time_t now);
+void entry_guards_compute_status(const or_options_t *options, time_t now);
int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);
void entry_nodes_should_be_added(void);
-int entry_list_is_constrained(or_options_t *options);
-routerinfo_t *choose_random_entry(cpath_build_state_t *state);
+int entry_list_is_constrained(const or_options_t *options);
+const node_t *choose_random_entry(cpath_build_state_t *state);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
@@ -64,18 +65,19 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
void mark_bridge_list(void);
void sweep_bridge_list(void);
-int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
+int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
+int node_is_a_configured_bridge(const node_t *node);
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest);
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *digest);
void retry_bridge_descriptor_fetch_directly(const char *digest);
-void fetch_bridge_descriptors(or_options_t *options, time_t now);
+void fetch_bridge_descriptors(const or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
int any_bridge_descriptors_known(void);
int any_pending_bridge_descriptor_fetches(void);
-int entries_known_but_down(or_options_t *options);
-void entries_retry_all(or_options_t *options);
+int entries_known_but_down(const or_options_t *options);
+void entries_retry_all(const or_options_t *options);
void entry_guards_free_all(void);
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 8ec46186d..93f5fd349 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -19,6 +19,7 @@
#include "connection_or.h"
#include "control.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "rendclient.h"
@@ -86,10 +87,7 @@ orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
/** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID
* and/or or_connection for circ has just changed from <b>old_conn, old_id</b>
* to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing
- * the old entry (if any) and adding a new one. If <b>active</b> is true,
- * remove the circuit from the list of active circuits on old_conn and add it
- * to the list of active circuits on conn.
- * XXX "active" isn't an arg anymore */
+ * the old entry (if any) and adding a new one. */
static void
circuit_set_circid_orconn_helper(circuit_t *circ, int direction,
circid_t id,
@@ -274,8 +272,10 @@ circuit_count_pending_on_or_conn(or_connection_t *or_conn)
circuit_get_all_pending_on_or_conn(sl, or_conn);
cnt = smartlist_len(sl);
smartlist_free(sl);
- log_debug(LD_CIRC,"or_conn to %s, %d pending circs",
- or_conn->nickname ? or_conn->nickname : "NULL", cnt);
+ log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
+ or_conn->nickname ? or_conn->nickname : "NULL",
+ or_conn->_base.address,
+ cnt);
return cnt;
}
@@ -773,8 +773,8 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn)
return found->circuit;
return NULL;
-
/* The rest of this checks for bugs. Disabled by default. */
+ /* We comment it out because coverity complains otherwise.
{
circuit_t *circ;
for (circ=global_circuitlist;circ;circ = circ->next) {
@@ -793,7 +793,7 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn)
}
}
return NULL;
- }
+ } */
}
/** Return a circ such that:
@@ -864,7 +864,7 @@ circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason)
}
/** Return a circ such that:
- * - circ-\>rend_data-\>query is equal to <b>rend_query</b>, and
+ * - circ-\>rend_data-\>onion_address is equal to <b>rend_query</b>, and
* - circ-\>purpose is equal to <b>purpose</b>.
*
* Return NULL if no such circuit exists.
@@ -979,7 +979,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0;
int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0;
int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* Make sure we're not trying to create a onehop circ by
* cannibalization. */
@@ -1005,15 +1005,15 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
if (info) {
/* need to make sure we don't duplicate hops */
crypt_path_t *hop = circ->cpath;
- routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
+ const node_t *ri1 = node_get_by_id(info->identity_digest);
do {
- routerinfo_t *ri2;
+ const node_t *ri2;
if (tor_memeq(hop->extend_info->identity_digest,
info->identity_digest, DIGEST_LEN))
goto next;
if (ri1 &&
- (ri2 = router_get_by_digest(hop->extend_info->identity_digest))
- && routers_in_same_family(ri1, ri2))
+ (ri2 = node_get_by_id(hop->extend_info->identity_digest))
+ && nodes_in_same_family(ri1, ri2))
goto next;
hop=hop->next;
} while (hop!=circ->cpath);
@@ -1098,7 +1098,7 @@ void
circuit_expire_all_dirty_circs(void)
{
circuit_t *circ;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
for (circ=global_circuitlist; circ; circ = circ->next) {
if (CIRCUIT_IS_ORIGIN(circ) &&
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 7289aa5c1..67677ef05 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -17,6 +17,7 @@
#include "connection.h"
#include "connection_edge.h"
#include "control.h"
+#include "nodelist.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -43,7 +44,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
int need_uptime, int need_internal,
time_t now)
{
- routerinfo_t *exitrouter;
+ const node_t *exitnode;
cpath_build_state_t *build_state;
tor_assert(circ);
tor_assert(conn);
@@ -73,7 +74,8 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
}
- if (purpose == CIRCUIT_PURPOSE_C_GENERAL)
+ if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
if (circ->timestamp_dirty &&
circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
return 0;
@@ -85,7 +87,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
* of the one we meant to finish at.
*/
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- exitrouter = build_state_get_exit_router(build_state);
+ exitnode = build_state_get_exit_node(build_state);
if (need_uptime && !build_state->need_uptime)
return 0;
@@ -93,7 +95,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
- if (!exitrouter && !build_state->onehop_tunnel) {
+ if (!exitnode && !build_state->onehop_tunnel) {
log_debug(LD_CIRC,"Not considering circuit with unknown router.");
return 0; /* this circuit is screwed and doesn't know it yet,
* or is a rendezvous circuit. */
@@ -127,7 +129,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
}
}
- if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) {
+ if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
/* can't exit from this router */
return 0;
}
@@ -288,7 +290,6 @@ circuit_expire_building(void)
struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff,
cannibalize_cutoff, close_cutoff, extremely_old_cutoff;
struct timeval now;
- struct timeval introcirc_cutoff;
cpath_build_state_t *build_state;
tor_gettimeofday(&now);
@@ -307,8 +308,6 @@ circuit_expire_building(void)
SET_CUTOFF(close_cutoff, circ_times.close_ms);
SET_CUTOFF(extremely_old_cutoff, circ_times.close_ms*2 + 1000);
- introcirc_cutoff = begindir_cutoff;
-
while (next_circ) {
struct timeval cutoff;
victim = next_circ;
@@ -325,8 +324,6 @@ circuit_expire_building(void)
cutoff = fourhop_cutoff;
else if (TO_ORIGIN_CIRCUIT(victim)->has_opened)
cutoff = cannibalize_cutoff;
- else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING)
- cutoff = introcirc_cutoff;
else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
cutoff = close_cutoff;
else
@@ -337,12 +334,6 @@ circuit_expire_building(void)
#if 0
/* some debug logs, to help track bugs */
- if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
- victim->timestamp_created <= introcirc_cutoff &&
- victim->timestamp_created > general_cutoff)
- log_info(LD_REND|LD_CIRC, "Timing out introduction circuit which we "
- "would not have done if it had been a general circuit.");
-
if (victim->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING &&
victim->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
if (!victim->timestamp_dirty)
@@ -495,7 +486,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
uint16_t port, int min)
{
circuit_t *circ;
- routerinfo_t *exitrouter;
+ const node_t *exitnode;
int num=0;
time_t now = time(NULL);
int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
@@ -511,14 +502,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
if (build_state->is_internal || build_state->onehop_tunnel)
continue;
- exitrouter = build_state_get_exit_router(build_state);
- if (exitrouter && (!need_uptime || build_state->need_uptime)) {
+ exitnode = build_state_get_exit_node(build_state);
+ if (exitnode && (!need_uptime || build_state->need_uptime)) {
int ok;
if (conn) {
- ok = connection_ap_can_use_exit(conn, exitrouter);
+ ok = connection_ap_can_use_exit(conn, exitnode);
} else {
- addr_policy_result_t r = compare_addr_to_addr_policy(
- 0, port, exitrouter->exit_policy);
+ addr_policy_result_t r;
+ r = compare_addr_to_node_policy(0, port, exitnode);
ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
}
if (ok) {
@@ -585,7 +576,7 @@ circuit_predict_and_launch_new(void)
log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another exit circ.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -597,7 +588,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d internal), need another internal "
"circ for my hidden service.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -615,7 +606,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d uptime-internal, %d internal), need"
" another hidden service circ.",
num, num_uptime_internal, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -628,7 +619,7 @@ circuit_predict_and_launch_new(void)
flags = CIRCLAUNCH_NEED_CAPACITY;
log_info(LD_CIRC,
"Have %d clean circs need another buildtime test circ.", num);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
}
@@ -645,7 +636,7 @@ void
circuit_build_needed_circs(time_t now)
{
static time_t time_to_new_circuit = 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* launch a new circ for any pending streams that need one */
connection_ap_attach_pending();
@@ -664,9 +655,9 @@ circuit_build_needed_circs(time_t now)
circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL);
if (get_options()->RunTesting &&
circ &&
- circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
+ circ->timestamp_created.tv_sec + TESTING_CIRCUIT_INTERVAL < now) {
log_fn(LOG_INFO,"Creating a new testing circuit.");
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0);
}
#endif
}
@@ -1101,17 +1092,9 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
origin_circuit_t *
-circuit_launch_by_router(uint8_t purpose,
- routerinfo_t *exit, int flags)
+circuit_launch(uint8_t purpose, int flags)
{
- origin_circuit_t *circ;
- extend_info_t *info = NULL;
- if (exit)
- info = extend_info_from_router(exit);
- circ = circuit_launch_by_extend_info(purpose, info, flags);
-
- extend_info_free(info);
- return circ;
+ return circuit_launch_by_extend_info(purpose, NULL, flags);
}
/** Launch a new circuit with purpose <b>purpose</b> and exit node
@@ -1225,7 +1208,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
int check_exit_policy;
int need_uptime, need_internal;
int want_onehop;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
tor_assert(circp);
@@ -1282,9 +1265,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
uint32_t addr = 0;
if (tor_inet_aton(conn->socks_request->address, &in))
addr = ntohl(in.s_addr);
- if (router_exit_policy_all_routers_reject(addr,
- conn->socks_request->port,
- need_uptime)) {
+ if (router_exit_policy_all_nodes_reject(addr,
+ conn->socks_request->port,
+ need_uptime)) {
log_notice(LD_APP,
"No Tor server allows exit to %s:%d. Rejecting.",
safe_str_client(conn->socks_request->address),
@@ -1294,9 +1277,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
} else {
/* XXXX023 Duplicates checks in connection_ap_handshake_attach_circuit:
* refactor into a single function? */
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (router && !connection_ap_can_use_exit(conn, router)) {
+ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' is excluded or "
"would refuse request. %s.",
@@ -1335,8 +1318,8 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
return 0;
}
- log_info(LD_REND,"Chose '%s' as intro point for '%s'.",
- extend_info->nickname,
+ log_info(LD_REND,"Chose %s as intro point for '%s'.",
+ extend_info_describe(extend_info),
safe_str_client(conn->rend_data->onion_address));
}
@@ -1345,11 +1328,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
*/
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
- routerinfo_t *r;
+ const node_t *r;
int opt = conn->chosen_exit_optional;
- r = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (r) {
- extend_info = extend_info_from_router(r);
+ r = node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (r && node_has_descriptor(r)) {
+ extend_info = extend_info_from_node(r);
} else {
log_debug(LD_DIR, "considering %d, %s",
want_onehop, conn->chosen_exit_name);
@@ -1488,7 +1471,7 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
/** Return true iff <b>address</b> is matched by one of the entries in
* TrackHostExits. */
int
-hostname_in_track_host_exits(or_options_t *options, const char *address)
+hostname_in_track_host_exits(const or_options_t *options, const char *address)
{
if (!options->TrackHostExits)
return 0;
@@ -1512,7 +1495,7 @@ hostname_in_track_host_exits(or_options_t *options, const char *address)
static void
consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *new_address = NULL;
char fp[HEX_DIGEST_LEN+1];
@@ -1615,9 +1598,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
origin_circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (!router && !want_onehop) {
+ if (!node && !want_onehop) {
/* We ran into this warning when trying to extend a circuit to a
* hidden service directory for which we didn't have a router
* descriptor. See flyspray task 767 for more details. We should
@@ -1633,7 +1616,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
}
return -1;
}
- if (router && !connection_ap_can_use_exit(conn, router)) {
+ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' is excluded or "
"would refuse request. %s.",
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index bfeaea20d..ab7f6a2fe 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -43,15 +43,15 @@ void circuit_build_failed(origin_circuit_t *circ);
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
-origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
- routerinfo_t *exit, int flags);
+origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
void circuit_reset_failure_count(int timeout);
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
-int hostname_in_track_host_exits(or_options_t *options, const char *address);
+int hostname_in_track_host_exits(const or_options_t *options,
+ const char *address);
#endif
diff --git a/src/or/command.c b/src/or/command.c
index 00d9af33f..d24373eec 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -25,6 +25,7 @@
#include "control.h"
#include "cpuworker.h"
#include "hibernate.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "router.h"
@@ -267,15 +268,18 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
}
if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
- routerinfo_t *router = router_get_by_digest(conn->identity_digest);
+ const node_t *node = node_get_by_id(conn->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).",
cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
- if (router)
+ if (node) {
+ char *p = esc_for_log(node_get_platform(node));
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Details: nickname \"%s\", platform %s.",
- router->nickname, escaped(router->platform));
+ "Details: router %s, platform %s.",
+ node_describe(node), p);
+ tor_free(p);
+ }
return;
}
@@ -620,7 +624,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
/** Warn when we get a netinfo skew with at least this value. */
#define NETINFO_NOTICE_SKEW 3600
if (labs(apparent_skew) > NETINFO_NOTICE_SKEW &&
- router_get_by_digest(conn->identity_digest)) {
+ router_get_by_id_digest(conn->identity_digest)) {
char dbuf[64];
int severity;
/*XXXX be smarter about when everybody says we are skewed. */
@@ -645,6 +649,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
/* XXX maybe act on my_apparent_addr, if the source is sufficiently
* trustworthy. */
+ (void)my_apparent_addr;
if (connection_or_set_state_open(conn)<0)
connection_mark_for_close(TO_CONN(conn));
diff --git a/src/or/config.c b/src/or/config.c
index 4bdb0384d..4aabe6b95 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -38,6 +38,8 @@
#include <shlobj.h>
#endif
+#include "procmon.h"
+
/** Enumeration of types which option values can take */
typedef enum config_type_t {
CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
@@ -46,9 +48,13 @@ typedef enum config_type_t {
CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or
* "auto". */
CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
+ CONFIG_TYPE_MSEC_INTERVAL,/**< A number of milliseconds, with optional
+ * units */
CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
CONFIG_TYPE_DOUBLE, /**< A floating-point value */
CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
+ CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false,
+ * 1 for true, and -1 for auto */
CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */
CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
* optional whitespace. */
@@ -201,6 +207,7 @@ static config_var_t _option_vars[] = {
V(ClientOnly, BOOL, "0"),
V(ConsensusParams, STRING, NULL),
V(ConnLimit, UINT, "1000"),
+ V(ConnDirectionStatistics, BOOL, "0"),
V(ConstrainedSockets, BOOL, "0"),
V(ConstrainedSockSize, MEMUNIT, "8192"),
V(ContactInfo, STRING, NULL),
@@ -209,10 +216,11 @@ static config_var_t _option_vars[] = {
V(ControlPortFileGroupReadable,BOOL, "0"),
V(ControlPortWriteToFile, FILENAME, NULL),
V(ControlSocket, LINELIST, NULL),
- V(ControlSocketsGroupWritable, BOOL, "0"),
+ V(ControlSocketsGroupWritable, BOOL, "0"),
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
V(CookieAuthFile, STRING, NULL),
+ V(CountPrivateBandwidth, BOOL, "0"),
V(DataDirectory, FILENAME, NULL),
OBSOLETE("DebugLogFile"),
V(DirAllowPrivateAddresses, BOOL, NULL),
@@ -227,9 +235,10 @@ static config_var_t _option_vars[] = {
OBSOLETE("DirRecordUsageGranularity"),
OBSOLETE("DirRecordUsageRetainIPs"),
OBSOLETE("DirRecordUsageSaveInterval"),
- V(DirReqStatistics, BOOL, "0"),
+ V(DirReqStatistics, BOOL, "1"),
VAR("DirServer", LINELIST, DirServers, NULL),
V(DisableAllSwap, BOOL, "0"),
+ V(DisableIOCP, BOOL, "1"),
V(DNSPort, PORT, "0"),
V(DNSListenAddress, LINELIST, NULL),
V(DownloadExtraInfo, BOOL, "0"),
@@ -244,7 +253,7 @@ static config_var_t _option_vars[] = {
V(ExitPolicy, LINELIST, NULL),
V(ExitPolicyRejectPrivate, BOOL, "1"),
V(ExitPortStatistics, BOOL, "0"),
- V(ExtraInfoStatistics, BOOL, "0"),
+ V(ExtraInfoStatistics, BOOL, "1"),
#if defined (WINCE)
V(FallbackNetworkstatusFile, FILENAME, "fallback-consensus"),
@@ -269,6 +278,7 @@ static config_var_t _option_vars[] = {
#endif
OBSOLETE("Group"),
V(HardwareAccel, BOOL, "0"),
+ V(HeartbeatPeriod, INTERVAL, "6 hours"),
V(AccelName, STRING, NULL),
V(AccelDir, FILENAME, NULL),
V(HashedControlPassword, LINELIST, NULL),
@@ -298,8 +308,9 @@ static config_var_t _option_vars[] = {
OBSOLETE("LinkPadding"),
OBSOLETE("LogLevel"),
OBSOLETE("LogFile"),
+ V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(LongLivedPorts, CSV,
- "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"),
+ "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
@@ -314,7 +325,7 @@ static config_var_t _option_vars[] = {
V(WarnUnsafeSocks, BOOL, "1"),
OBSOLETE("NoPublish"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
- V(NumCPUs, UINT, "1"),
+ V(NumCPUs, UINT, "0"),
V(NumEntryGuards, UINT, "3"),
V(ORListenAddress, LINELIST, NULL),
V(ORPort, PORT, "0"),
@@ -324,6 +335,8 @@ static config_var_t _option_vars[] = {
V(PerConnBWRate, MEMUNIT, "0"),
V(PidFile, STRING, NULL),
V(TestingTorNetwork, BOOL, "0"),
+ V(PortForwarding, BOOL, "0"),
+ V(PortForwardingHelper, FILENAME, "tor-fw-helper"),
V(PreferTunneledDirConns, BOOL, "1"),
V(ProtocolWarnings, BOOL, "0"),
V(PublishServerDescriptor, CSV, "1"),
@@ -335,7 +348,7 @@ static config_var_t _option_vars[] = {
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
OBSOLETE("RedirectExit"),
- V(RefuseUnknownExits, STRING, "auto"),
+ V(RefuseUnknownExits, AUTOBOOL, "auto"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
V(RelayBandwidthRate, MEMUNIT, "0"),
@@ -376,6 +389,7 @@ static config_var_t _option_vars[] = {
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
V(UseEntryGuards, BOOL, "1"),
+ V(UseMicrodescriptors, AUTOBOOL, "0"),
V(User, STRING, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
@@ -392,12 +406,14 @@ static config_var_t _option_vars[] = {
VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
V(VirtualAddrNetwork, STRING, "127.192.0.0/10"),
V(WarnPlaintextPorts, CSV, "23,109,110,143"),
+ V(_UseFilteringSSLBufferevents, BOOL, "0"),
VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
NULL),
+ VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"),
V(_UsingTestNetworkDefaults, BOOL, "0"),
@@ -406,7 +422,7 @@ static config_var_t _option_vars[] = {
/** Override default values with these if the user sets the TestingTorNetwork
* option. */
-static config_var_t testing_tor_network_defaults[] = {
+static const config_var_t testing_tor_network_defaults[] = {
V(ServerDNSAllowBrokenConfig, BOOL, "1"),
V(DirAllowPrivateAddresses, BOOL, "1"),
V(EnforceDistinctSubnets, BOOL, "0"),
@@ -415,6 +431,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(AuthDirMaxServersPerAuthAddr,UINT, "0"),
V(ClientDNSRejectInternalAddresses, BOOL,"0"),
V(ClientRejectInternalAddresses, BOOL, "0"),
+ V(CountPrivateBandwidth, BOOL, "1"),
V(ExitPolicyRejectPrivate, BOOL, "0"),
V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
@@ -426,6 +443,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
V(_UsingTestNetworkDefaults, BOOL, "1"),
+
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
};
#undef VAR
@@ -528,39 +546,43 @@ static char *get_windows_conf_root(void);
#endif
static void config_line_append(config_line_t **lst,
const char *key, const char *val);
-static void option_clear(config_format_t *fmt, or_options_t *options,
- config_var_t *var);
-static void option_reset(config_format_t *fmt, or_options_t *options,
- config_var_t *var, int use_defaults);
-static void config_free(config_format_t *fmt, void *options);
+static void option_clear(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var);
+static void option_reset(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var, int use_defaults);
+static void config_free(const config_format_t *fmt, void *options);
static int config_lines_eq(config_line_t *a, config_line_t *b);
-static int option_is_same(config_format_t *fmt,
- or_options_t *o1, or_options_t *o2,
+static int option_is_same(const config_format_t *fmt,
+ const or_options_t *o1, const or_options_t *o2,
const char *name);
-static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
-static int options_validate(or_options_t *old_options, or_options_t *options,
+static or_options_t *options_dup(const config_format_t *fmt,
+ const or_options_t *old);
+static int options_validate(or_options_t *old_options,
+ or_options_t *options,
int from_setconf, char **msg);
-static int options_act_reversible(or_options_t *old_options, char **msg);
-static int options_act(or_options_t *old_options);
-static int options_transition_allowed(or_options_t *old, or_options_t *new,
+static int options_act_reversible(const or_options_t *old_options, char **msg);
+static int options_act(const or_options_t *old_options);
+static int options_transition_allowed(const or_options_t *old,
+ const or_options_t *new,
char **msg);
-static int options_transition_affects_workers(or_options_t *old_options,
- or_options_t *new_options);
-static int options_transition_affects_descriptor(or_options_t *old_options,
- or_options_t *new_options);
+static int options_transition_affects_workers(
+ const or_options_t *old_options, const or_options_t *new_options);
+static int options_transition_affects_descriptor(
+ const or_options_t *old_options, const or_options_t *new_options);
static int check_nickname_list(const char *lst, const char *name, char **msg);
-static void config_register_addressmaps(or_options_t *options);
+static void config_register_addressmaps(const or_options_t *options);
static int parse_bridge_line(const char *line, int validate_only);
static int parse_dir_server_line(const char *line,
- authority_type_t required_type,
+ dirinfo_type_t required_type,
int validate_only);
static int validate_data_directory(or_options_t *options);
-static int write_configuration_file(const char *fname, or_options_t *options);
-static config_line_t *get_assigned_option(config_format_t *fmt,
- void *options, const char *key,
- int escape_val);
-static void config_init(config_format_t *fmt, void *options);
+static int write_configuration_file(const char *fname,
+ const or_options_t *options);
+static config_line_t *get_assigned_option(const config_format_t *fmt,
+ const void *options, const char *key,
+ int escape_val);
+static void config_init(const config_format_t *fmt, void *options);
static int or_state_validate(or_state_t *old_options, or_state_t *options,
int from_setconf, char **msg);
static int or_state_load(void);
@@ -570,8 +592,9 @@ static int is_listening_on_low_port(int port_option,
const config_line_t *listen_options);
static uint64_t config_parse_memunit(const char *s, int *ok);
+static int config_parse_msec_interval(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
-static void init_libevent(void);
+static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
/** Magic value for or_options_t. */
@@ -598,7 +621,7 @@ static config_var_t state_extra_var = {
};
/** Configuration format for or_state_t. */
-static config_format_t state_format = {
+static const config_format_t state_format = {
sizeof(or_state_t),
OR_STATE_MAGIC,
STRUCT_OFFSET(or_state_t, _magic),
@@ -632,7 +655,7 @@ get_dirportfrontpage(void)
/** Allocate an empty configuration object of a given format type. */
static void *
-config_alloc(config_format_t *fmt)
+config_alloc(const config_format_t *fmt)
{
void *opts = tor_malloc_zero(fmt->size);
*(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
@@ -642,12 +665,19 @@ config_alloc(config_format_t *fmt)
/** Return the currently configured options. */
or_options_t *
-get_options(void)
+get_options_mutable(void)
{
tor_assert(global_options);
return global_options;
}
+/** Returns the currently configured options */
+const or_options_t *
+get_options(void)
+{
+ return get_options_mutable();
+}
+
/** Change the current global options to contain <b>new_val</b> instead of
* their current value; take action based on the new value; free the old value
* as necessary. Returns 0 on success, -1 on failure.
@@ -705,6 +735,11 @@ or_options_free(or_options_t *options)
return;
routerset_free(options->_ExcludeExitNodesUnion);
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
+ rs, routerset_free(rs));
+ smartlist_free(options->NodeFamilySets);
+ }
config_free(&options_format, options);
}
@@ -787,7 +822,7 @@ escaped_safe_str(const char *address)
/** Add the default directory authorities directly into the trusted dir list,
* but only add them insofar as they share bits with <b>type</b>. */
static void
-add_default_trusted_dir_authorities(authority_type_t type)
+add_default_trusted_dir_authorities(dirinfo_type_t type)
{
int i;
const char *dirservers[] = {
@@ -861,16 +896,16 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
/* Now go through the four ways you can configure an alternate
* set of directory authorities, and make sure none are broken. */
for (cl = options->DirServers; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
return 0;
}
@@ -879,8 +914,8 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
* as appropriate.
*/
static int
-consider_adding_dir_authorities(or_options_t *options,
- or_options_t *old_options)
+consider_adding_dir_authorities(const or_options_t *options,
+ const or_options_t *old_options)
{
config_line_t *cl;
int need_to_update =
@@ -901,27 +936,28 @@ consider_adding_dir_authorities(or_options_t *options,
if (!options->DirServers) {
/* then we may want some of the defaults */
- authority_type_t type = NO_AUTHORITY;
+ dirinfo_type_t type = NO_DIRINFO;
if (!options->AlternateBridgeAuthority)
- type |= BRIDGE_AUTHORITY;
+ type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
- type |= V1_AUTHORITY | V2_AUTHORITY | V3_AUTHORITY;
+ type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
+ MICRODESC_DIRINFO;
if (!options->AlternateHSAuthority)
- type |= HIDSERV_AUTHORITY;
+ type |= HIDSERV_DIRINFO;
add_default_trusted_dir_authorities(type);
}
for (cl = options->DirServers; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
return 0;
}
@@ -933,12 +969,12 @@ consider_adding_dir_authorities(or_options_t *options,
* Return 0 if all goes well, return -1 if things went badly.
*/
static int
-options_act_reversible(or_options_t *old_options, char **msg)
+options_act_reversible(const or_options_t *old_options, char **msg)
{
smartlist_t *new_listeners = smartlist_create();
smartlist_t *replaced_listeners = smartlist_create();
static int libevent_initialized = 0;
- or_options_t *options = get_options();
+ or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
int set_conn_limit = 0;
int r = -1;
@@ -978,7 +1014,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Set up libevent. (We need to do this before we can register the
* listeners as listeners.) */
if (running_tor && !libevent_initialized) {
- init_libevent();
+ init_libevent(options);
libevent_initialized = 1;
}
@@ -1022,7 +1058,8 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Ensure data directory is private; create if possible. */
if (check_private_dir(options->DataDirectory,
- running_tor ? CPD_CREATE : CPD_CHECK)<0) {
+ running_tor ? CPD_CREATE : CPD_CHECK,
+ options->User)<0) {
tor_asprintf(msg,
"Couldn't access/create private data directory \"%s\"",
options->DataDirectory);
@@ -1030,12 +1067,13 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* No need to roll back, since you can't change the value. */
}
- if (directory_caches_v2_dir_info(options)) {
+ if (directory_caches_v2_dir_info(options)) {
size_t len = strlen(options->DataDirectory)+32;
char *fn = tor_malloc(len);
tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status",
options->DataDirectory);
- if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK) < 0) {
+ if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK,
+ options->User) < 0) {
tor_asprintf(msg,
"Couldn't access/create private data directory \"%s\"", fn);
tor_free(fn);
@@ -1105,7 +1143,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/** If we need to have a GEOIP ip-to-country map to run with our configured
* options, return 1 and set *<b>reason_out</b> to a description of why. */
int
-options_need_geoip_info(or_options_t *options, const char **reason_out)
+options_need_geoip_info(const or_options_t *options, const char **reason_out)
{
int bridge_usage =
options->BridgeRelay && options->BridgeRecordUsageByCountry;
@@ -1130,7 +1168,7 @@ options_need_geoip_info(or_options_t *options, const char **reason_out)
/** Return the bandwidthrate that we are going to report to the authorities
* based on the config options. */
uint32_t
-get_effective_bwrate(or_options_t *options)
+get_effective_bwrate(const or_options_t *options)
{
uint64_t bw = options->BandwidthRate;
if (bw > options->MaxAdvertisedBandwidth)
@@ -1144,7 +1182,7 @@ get_effective_bwrate(or_options_t *options)
/** Return the bandwidthburst that we are going to report to the authorities
* based on the config options. */
uint32_t
-get_effective_bwburst(or_options_t *options)
+get_effective_bwburst(const or_options_t *options)
{
uint64_t bw = options->BandwidthBurst;
if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
@@ -1163,12 +1201,14 @@ get_effective_bwburst(or_options_t *options)
* here yet. Some is still in do_hup() and other places.
*/
static int
-options_act(or_options_t *old_options)
+options_act(const or_options_t *old_options)
{
config_line_t *cl;
- or_options_t *options = get_options();
+ or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
char *msg;
+ const int transition_affects_workers =
+ old_options && options_transition_affects_workers(old_options, options);
if (running_tor && !have_lockfile()) {
if (try_locking(options, 1) < 0)
@@ -1220,6 +1260,17 @@ options_act(or_options_t *old_options)
finish_daemon(options->DataDirectory);
}
+ /* We want to reinit keys as needed before we do much of anything else:
+ keys are important, and other things can depend on them. */
+ if (transition_affects_workers ||
+ (options->V3AuthoritativeDir && (!old_options ||
+ !old_options->V3AuthoritativeDir))) {
+ if (init_keys() < 0) {
+ log_warn(LD_BUG,"Error initializing keys; exiting");
+ return -1;
+ }
+ }
+
/* Write our PID to the PID file. If we do not have write permissions we
* will log a warning */
if (options->PidFile)
@@ -1241,6 +1292,8 @@ options_act(or_options_t *old_options)
return -1;
}
+ monitor_owning_controller_process(options->OwningControllerProcess);
+
/* reload keys as needed for rendezvous services. */
if (rend_service_load_keys()<0) {
log_warn(LD_GENERAL,"Error loading rendezvous service keys");
@@ -1255,17 +1308,16 @@ options_act(or_options_t *old_options)
if (accounting_is_enabled(options))
configure_accounting(time(NULL));
- /* parse RefuseUnknownExits tristate */
- if (!strcmp(options->RefuseUnknownExits, "0"))
- options->RefuseUnknownExits_ = 0;
- else if (!strcmp(options->RefuseUnknownExits, "1"))
- options->RefuseUnknownExits_ = 1;
- else if (!strcmp(options->RefuseUnknownExits, "auto"))
- options->RefuseUnknownExits_ = -1;
- else {
- /* Should have caught this in options_validate */
- return -1;
- }
+#ifdef USE_BUFFEREVENTS
+ /* If we're using the bufferevents implementation and our rate limits
+ * changed, we need to tell the rate-limiting system about it. */
+ if (!old_options ||
+ old_options->BandwidthRate != options->BandwidthRate ||
+ old_options->BandwidthBurst != options->BandwidthBurst ||
+ old_options->RelayBandwidthRate != options->RelayBandwidthRate ||
+ old_options->RelayBandwidthBurst != options->RelayBandwidthBurst)
+ connection_bucket_init();
+#endif
/* Change the cell EWMA settings */
cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
@@ -1341,14 +1393,10 @@ options_act(or_options_t *old_options)
}
}
- if (options_transition_affects_workers(old_options, options)) {
+ if (transition_affects_workers) {
log_info(LD_GENERAL,
"Worker-related options changed. Rotating workers.");
- if (init_keys() < 0) {
- log_warn(LD_BUG,"Error initializing keys; exiting");
- return -1;
- }
if (server_mode(options) && !server_mode(old_options)) {
ip_address_changed(0);
if (can_complete_circuit || !any_predicted_circuits(time(NULL)))
@@ -1362,9 +1410,6 @@ options_act(or_options_t *old_options)
return -1;
}
- if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir)
- init_keys();
-
if (options->PerConnBWRate != old_options->PerConnBWRate ||
options->PerConnBWBurst != old_options->PerConnBWBurst)
connection_or_update_token_buckets(get_connection_array(), options);
@@ -1391,44 +1436,54 @@ options_act(or_options_t *old_options)
tor_free(actual_fname);
}
- if (options->DirReqStatistics && !geoip_is_loaded()) {
- /* Check if GeoIP database could be loaded. */
- log_warn(LD_CONFIG, "Configured to measure directory request "
- "statistics, but no GeoIP database found!");
- return -1;
- }
-
- if (options->EntryStatistics) {
- if (should_record_bridge_info(options)) {
- /* Don't allow measuring statistics on entry guards when configured
- * as bridge. */
- log_warn(LD_CONFIG, "Bridges cannot be configured to measure "
- "additional GeoIP statistics as entry guards.");
- return -1;
- } else if (!geoip_is_loaded()) {
- /* Check if GeoIP database could be loaded. */
- log_warn(LD_CONFIG, "Configured to measure entry node statistics, "
- "but no GeoIP database found!");
- return -1;
- }
- }
-
if (options->CellStatistics || options->DirReqStatistics ||
- options->EntryStatistics || options->ExitPortStatistics) {
+ options->EntryStatistics || options->ExitPortStatistics ||
+ options->ConnDirectionStatistics) {
time_t now = time(NULL);
+ int print_notice = 0;
if ((!old_options || !old_options->CellStatistics) &&
- options->CellStatistics)
+ options->CellStatistics) {
rep_hist_buffer_stats_init(now);
+ print_notice = 1;
+ }
if ((!old_options || !old_options->DirReqStatistics) &&
- options->DirReqStatistics)
- geoip_dirreq_stats_init(now);
+ options->DirReqStatistics) {
+ if (geoip_is_loaded()) {
+ geoip_dirreq_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->DirReqStatistics = 0;
+ /* Don't warn Tor clients, they don't use statistics */
+ if (options->ORPort)
+ log_notice(LD_CONFIG, "Configured to measure directory request "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
if ((!old_options || !old_options->EntryStatistics) &&
- options->EntryStatistics)
- geoip_entry_stats_init(now);
+ options->EntryStatistics && !should_record_bridge_info(options)) {
+ if (geoip_is_loaded()) {
+ geoip_entry_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->EntryStatistics = 0;
+ log_notice(LD_CONFIG, "Configured to measure entry node "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
if ((!old_options || !old_options->ExitPortStatistics) &&
- options->ExitPortStatistics)
+ options->ExitPortStatistics) {
rep_hist_exit_stats_init(now);
- if (!old_options)
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->ConnDirectionStatistics) &&
+ options->ConnDirectionStatistics) {
+ rep_hist_conn_stats_init(now);
+ }
+ if (print_notice)
log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
"the *-stats files that will first be written to the "
"data directory in 24 hours from now.");
@@ -1446,6 +1501,9 @@ options_act(or_options_t *old_options)
if (old_options && old_options->ExitPortStatistics &&
!options->ExitPortStatistics)
rep_hist_exit_stats_term();
+ if (old_options && old_options->ConnDirectionStatistics &&
+ !options->ConnDirectionStatistics)
+ rep_hist_conn_stats_term();
/* Check if we need to parse and add the EntryNodes config option. */
if (options->EntryNodes &&
@@ -1503,7 +1561,7 @@ options_act(or_options_t *old_options)
* apply abbreviations that work for the config file and the command line.
* If <b>warn_obsolete</b> is set, warn about deprecated names. */
static const char *
-expand_abbrev(config_format_t *fmt, const char *option, int command_line,
+expand_abbrev(const config_format_t *fmt, const char *option, int command_line,
int warn_obsolete)
{
int i;
@@ -1663,12 +1721,9 @@ config_free_lines(config_line_t *front)
}
}
-/** If <b>key</b> is a configuration option, return the corresponding
- * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
- * warn, and return the corresponding config_var_t. Otherwise return NULL.
- */
+/** As config_find_option, but return a non-const pointer. */
static config_var_t *
-config_find_option(config_format_t *fmt, const char *key)
+config_find_option_mutable(config_format_t *fmt, const char *key)
{
int i;
size_t keylen = strlen(key);
@@ -1693,9 +1748,20 @@ config_find_option(config_format_t *fmt, const char *key)
return NULL;
}
+/** If <b>key</b> is a configuration option, return the corresponding const
+ * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
+ * warn, and return the corresponding const config_var_t. Otherwise return
+ * NULL.
+ */
+static const config_var_t *
+config_find_option(const config_format_t *fmt, const char *key)
+{
+ return config_find_option_mutable((config_format_t*)fmt, key);
+}
+
/** Return the number of option entries in <b>fmt</b>. */
static int
-config_count_options(config_format_t *fmt)
+config_count_options(const config_format_t *fmt)
{
int i;
for (i=0; fmt->vars[i].name; ++i)
@@ -1713,11 +1779,11 @@ config_count_options(config_format_t *fmt)
* Called from config_assign_line() and option_reset().
*/
static int
-config_assign_value(config_format_t *fmt, or_options_t *options,
+config_assign_value(const config_format_t *fmt, or_options_t *options,
config_line_t *c, char **msg)
{
int i, ok;
- config_var_t *var;
+ const config_var_t *var;
void *lvalue;
CHECK(fmt, options);
@@ -1760,6 +1826,18 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
break;
}
+ case CONFIG_TYPE_MSEC_INTERVAL: {
+ i = config_parse_msec_interval(c->value, &ok);
+ if (!ok) {
+ tor_asprintf(msg,
+ "Msec interval '%s %s' is malformed or out of bounds.",
+ c->key, c->value);
+ return -1;
+ }
+ *(int *)lvalue = i;
+ break;
+ }
+
case CONFIG_TYPE_MEMUNIT: {
uint64_t u64 = config_parse_memunit(c->value, &ok);
if (!ok) {
@@ -1783,6 +1861,20 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
*(int *)lvalue = i;
break;
+ case CONFIG_TYPE_AUTOBOOL:
+ if (!strcmp(c->value, "auto"))
+ *(int *)lvalue = -1;
+ else if (!strcmp(c->value, "0"))
+ *(int *)lvalue = 0;
+ else if (!strcmp(c->value, "1"))
+ *(int *)lvalue = 1;
+ else {
+ tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
+ c->key, c->value);
+ return -1;
+ }
+ break;
+
case CONFIG_TYPE_STRING:
case CONFIG_TYPE_FILENAME:
tor_free(*(char **)lvalue);
@@ -1853,11 +1945,11 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
* Called from config_assign().
*/
static int
-config_assign_line(config_format_t *fmt, or_options_t *options,
+config_assign_line(const config_format_t *fmt, or_options_t *options,
config_line_t *c, int use_defaults,
int clear_first, bitarray_t *options_seen, char **msg)
{
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
@@ -1918,10 +2010,10 @@ config_assign_line(config_format_t *fmt, or_options_t *options,
/** Restore the option named <b>key</b> in options to its default value.
* Called from config_assign(). */
static void
-config_reset_line(config_format_t *fmt, or_options_t *options,
+config_reset_line(const config_format_t *fmt, or_options_t *options,
const char *key, int use_defaults)
{
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
@@ -1936,7 +2028,7 @@ config_reset_line(config_format_t *fmt, or_options_t *options,
int
option_is_recognized(const char *key)
{
- config_var_t *var = config_find_option(&options_format, key);
+ const config_var_t *var = config_find_option(&options_format, key);
return (var != NULL);
}
@@ -1945,14 +2037,14 @@ option_is_recognized(const char *key)
const char *
option_get_canonical_name(const char *key)
{
- config_var_t *var = config_find_option(&options_format, key);
+ const config_var_t *var = config_find_option(&options_format, key);
return var ? var->name : NULL;
}
/** Return a canonical list of the options assigned for key.
*/
config_line_t *
-option_get_assignment(or_options_t *options, const char *key)
+option_get_assignment(const or_options_t *options, const char *key)
{
return get_assigned_option(&options_format, options, key, 1);
}
@@ -2005,10 +2097,10 @@ config_lines_dup(const config_line_t *inp)
* value needs to be quoted before it's put in a config file, quote and
* escape that value. Return NULL if no such key exists. */
static config_line_t *
-get_assigned_option(config_format_t *fmt, void *options,
+get_assigned_option(const config_format_t *fmt, const void *options,
const char *key, int escape_val)
{
- config_var_t *var;
+ const config_var_t *var;
const void *value;
config_line_t *result;
tor_assert(options && key);
@@ -2052,7 +2144,9 @@ get_assigned_option(config_format_t *fmt, void *options,
escape_val = 0;
break;
}
+ /* fall through */
case CONFIG_TYPE_INTERVAL:
+ case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
/* This means every or_options_t uint or bool element
* needs to be an int. Not, say, a uint16_t or char. */
@@ -2068,6 +2162,14 @@ get_assigned_option(config_format_t *fmt, void *options,
tor_asprintf(&result->value, "%f", *(double*)value);
escape_val = 0; /* Can't need escape. */
break;
+
+ case CONFIG_TYPE_AUTOBOOL:
+ if (*(int*)value == -1) {
+ result->value = tor_strdup("auto");
+ escape_val = 0;
+ break;
+ }
+ /* fall through */
case CONFIG_TYPE_BOOL:
result->value = tor_strdup(*(int*)value ? "1" : "0");
escape_val = 0; /* Can't need escape. */
@@ -2180,7 +2282,7 @@ options_trial_assign() calls config_assign(1, 1)
returns.
*/
static int
-config_assign(config_format_t *fmt, void *options, config_line_t *list,
+config_assign(const config_format_t *fmt, void *options, config_line_t *list,
int use_defaults, int clear_first, char **msg)
{
config_line_t *p;
@@ -2242,7 +2344,7 @@ options_trial_assign(config_line_t *list, int use_defaults,
return r;
}
- if (options_validate(get_options(), trial_options, 1, msg) < 0) {
+ if (options_validate(get_options_mutable(), trial_options, 1, msg) < 0) {
config_free(&options_format, trial_options);
return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
}
@@ -2264,7 +2366,8 @@ options_trial_assign(config_line_t *list, int use_defaults,
/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
* Called from option_reset() and config_free(). */
static void
-option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
+option_clear(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var)
{
void *lvalue = STRUCT_VAR_P(options, var->var_offset);
(void)fmt; /* unused */
@@ -2280,11 +2383,15 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
*(time_t*)lvalue = 0;
break;
case CONFIG_TYPE_INTERVAL:
+ case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
case CONFIG_TYPE_PORT:
case CONFIG_TYPE_BOOL:
*(int*)lvalue = 0;
break;
+ case CONFIG_TYPE_AUTOBOOL:
+ *(int*)lvalue = -1;
+ break;
case CONFIG_TYPE_MEMUNIT:
*(uint64_t*)lvalue = 0;
break;
@@ -2318,8 +2425,8 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
* <b>use_defaults</b>, set it to its default value.
* Called by config_init() and option_reset_line() and option_assign_line(). */
static void
-option_reset(config_format_t *fmt, or_options_t *options,
- config_var_t *var, int use_defaults)
+option_reset(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var, int use_defaults)
{
config_line_t *c;
char *msg = NULL;
@@ -2359,7 +2466,7 @@ list_torrc_options(void)
int i;
smartlist_t *lines = smartlist_create();
for (i = 0; _option_vars[i].name; ++i) {
- config_var_t *var = &_option_vars[i];
+ const config_var_t *var = &_option_vars[i];
if (var->type == CONFIG_TYPE_OBSOLETE ||
var->type == CONFIG_TYPE_LINELIST_V)
continue;
@@ -2378,7 +2485,7 @@ static uint32_t last_resolved_addr = 0;
* public IP address.
*/
int
-resolve_my_address(int warn_severity, or_options_t *options,
+resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr_out, char **hostname_out)
{
struct in_addr in;
@@ -2387,7 +2494,7 @@ resolve_my_address(int warn_severity, or_options_t *options,
int explicit_ip=1;
int explicit_hostname=1;
int from_interface=0;
- char tmpbuf[INET_NTOA_BUF_LEN];
+ char *addr_string = NULL;
const char *address = options->Address;
int notice_severity = warn_severity <= LOG_NOTICE ?
LOG_NOTICE : warn_severity;
@@ -2429,48 +2536,43 @@ resolve_my_address(int warn_severity, or_options_t *options,
return -1;
}
from_interface = 1;
- in.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ addr = interface_ip;
log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
- "local interface. Using that.", tmpbuf);
+ "local interface. Using that.", fmt_addr32(addr));
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
} else { /* resolved hostname into addr */
- in.s_addr = htonl(addr);
-
if (!explicit_hostname &&
- is_internal_IP(ntohl(in.s_addr), 0)) {
+ is_internal_IP(addr, 0)) {
uint32_t interface_ip;
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
- "resolves to a private IP address (%s). Trying something "
- "else.", hostname, tmpbuf);
+ "resolves to a private IP address (%s). Trying something "
+ "else.", hostname, fmt_addr32(addr));
if (get_interface_address(warn_severity, &interface_ip)) {
log_fn(warn_severity, LD_CONFIG,
"Could not get local interface IP address. Too bad.");
} else if (is_internal_IP(interface_ip, 0)) {
- struct in_addr in2;
- in2.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
log_fn(notice_severity, LD_CONFIG,
"Interface IP address '%s' is a private address too. "
- "Ignoring.", tmpbuf);
+ "Ignoring.", fmt_addr32(interface_ip));
} else {
from_interface = 1;
- in.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ addr = interface_ip;
log_fn(notice_severity, LD_CONFIG,
"Learned IP address '%s' for local interface."
- " Using that.", tmpbuf);
+ " Using that.", fmt_addr32(addr));
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
}
}
}
+ } else {
+ addr = ntohl(in.s_addr); /* set addr so that addr_string is not
+ * illformed */
}
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- if (is_internal_IP(ntohl(in.s_addr), 0)) {
+ addr_string = tor_dup_ip(addr);
+ if (is_internal_IP(addr, 0)) {
/* make sure we're ok with publishing an internal IP */
if (!options->DirServers && !options->AlternateDirAuthority) {
/* if they are using the default dirservers, disallow internal IPs
@@ -2478,7 +2580,8 @@ resolve_my_address(int warn_severity, or_options_t *options,
log_fn(warn_severity, LD_CONFIG,
"Address '%s' resolves to private IP address '%s'. "
"Tor servers that use the default DirServers must have public "
- "IP addresses.", hostname, tmpbuf);
+ "IP addresses.", hostname, addr_string);
+ tor_free(addr_string);
return -1;
}
if (!explicit_ip) {
@@ -2486,19 +2589,20 @@ resolve_my_address(int warn_severity, or_options_t *options,
* they're using an internal address. */
log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
"IP address '%s'. Please set the Address config option to be "
- "the IP address you want to use.", hostname, tmpbuf);
+ "the IP address you want to use.", hostname, addr_string);
+ tor_free(addr_string);
return -1;
}
}
- log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
- *addr_out = ntohl(in.s_addr);
+ log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr));
+ *addr_out = addr;
if (last_resolved_addr && last_resolved_addr != *addr_out) {
/* Leave this as a notice, regardless of the requested severity,
* at least until dynamic IP address support becomes bulletproof. */
log_notice(LD_NET,
"Your IP address seems to have changed to %s. Updating.",
- tmpbuf);
+ addr_string);
ip_address_changed(0);
}
if (last_resolved_addr != *addr_out) {
@@ -2517,11 +2621,12 @@ resolve_my_address(int warn_severity, or_options_t *options,
}
control_event_server_status(LOG_NOTICE,
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
- tmpbuf, method, h?"HOSTNAME=":"", h);
+ addr_string, method, h?"HOSTNAME=":"", h);
}
last_resolved_addr = *addr_out;
if (hostname_out)
*hostname_out = tor_strdup(hostname);
+ tor_free(addr_string);
return 0;
}
@@ -2556,7 +2661,7 @@ is_local_addr(const tor_addr_t *addr)
/** Release storage held by <b>options</b>. */
static void
-config_free(config_format_t *fmt, void *options)
+config_free(const config_format_t *fmt, void *options)
{
int i;
@@ -2595,8 +2700,9 @@ config_lines_eq(config_line_t *a, config_line_t *b)
* and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
*/
static int
-option_is_same(config_format_t *fmt,
- or_options_t *o1, or_options_t *o2, const char *name)
+option_is_same(const config_format_t *fmt,
+ const or_options_t *o1, const or_options_t *o2,
+ const char *name)
{
config_line_t *c1, *c2;
int r = 1;
@@ -2613,7 +2719,7 @@ option_is_same(config_format_t *fmt,
/** Copy storage held by <b>old</b> into a new or_options_t and return it. */
static or_options_t *
-options_dup(config_format_t *fmt, or_options_t *old)
+options_dup(const config_format_t *fmt, const or_options_t *old)
{
or_options_t *newopts;
int i;
@@ -2689,10 +2795,10 @@ is_listening_on_low_port(int port_option,
/** Set all vars in the configuration object <b>options</b> to their default
* values. */
static void
-config_init(config_format_t *fmt, void *options)
+config_init(const config_format_t *fmt, void *options)
{
int i;
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
for (i=0; fmt->vars[i].name; ++i) {
@@ -2708,7 +2814,7 @@ config_init(config_format_t *fmt, void *options)
* Else, if comment_defaults, write default values as comments.
*/
static char *
-config_dump(config_format_t *fmt, void *options, int minimal,
+config_dump(const config_format_t *fmt, const void *options, int minimal,
int comment_defaults)
{
smartlist_t *elements;
@@ -2776,7 +2882,7 @@ config_dump(config_format_t *fmt, void *options, int minimal,
* include options that are the same as Tor's defaults.
*/
char *
-options_dump(or_options_t *options, int minimal)
+options_dump(const or_options_t *options, int minimal)
{
return config_dump(&options_format, options, minimal, 0);
}
@@ -2835,24 +2941,24 @@ static int
compute_publishserverdescriptor(or_options_t *options)
{
smartlist_t *list = options->PublishServerDescriptor;
- authority_type_t *auth = &options->_PublishServerDescriptor;
- *auth = NO_AUTHORITY;
+ dirinfo_type_t *auth = &options->_PublishServerDescriptor;
+ *auth = NO_DIRINFO;
if (!list) /* empty list, answer is none */
return 0;
SMARTLIST_FOREACH(list, const char *, string, {
if (!strcasecmp(string, "v1"))
- *auth |= V1_AUTHORITY;
+ *auth |= V1_DIRINFO;
else if (!strcmp(string, "1"))
if (options->BridgeRelay)
- *auth |= BRIDGE_AUTHORITY;
+ *auth |= BRIDGE_DIRINFO;
else
- *auth |= V2_AUTHORITY | V3_AUTHORITY;
+ *auth |= V2_DIRINFO | V3_DIRINFO;
else if (!strcasecmp(string, "v2"))
- *auth |= V2_AUTHORITY;
+ *auth |= V2_DIRINFO;
else if (!strcasecmp(string, "v3"))
- *auth |= V3_AUTHORITY;
+ *auth |= V3_DIRINFO;
else if (!strcasecmp(string, "bridge"))
- *auth |= BRIDGE_AUTHORITY;
+ *auth |= BRIDGE_DIRINFO;
else if (!strcasecmp(string, "hidserv"))
log_warn(LD_CONFIG,
"PublishServerDescriptor hidserv is invalid. See "
@@ -2880,6 +2986,10 @@ compute_publishserverdescriptor(or_options_t *options)
* will generate too many circuits and potentially overload the network. */
#define MIN_CIRCUIT_STREAM_TIMEOUT 10
+/** Lowest allowable value for HeartbeatPeriod; if this is too low, we might
+ * expose more information than we're comfortable with. */
+#define MIN_HEARTBEAT_PERIOD (30*60)
+
/** Return 0 if every setting in <b>options</b> is reasonable, and a
* permissible transition from <b>old_options</b>. Else return -1.
* Should have no side effects, except for normalizing the contents of
@@ -3009,12 +3119,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Failed to resolve/guess local address. See logs for details.");
}
- if (strcmp(options->RefuseUnknownExits, "0") &&
- strcmp(options->RefuseUnknownExits, "1") &&
- strcmp(options->RefuseUnknownExits, "auto")) {
- REJECT("RefuseUnknownExits must be 0, 1, or auto");
- }
-
#ifndef MS_WINDOWS
if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
@@ -3052,17 +3156,24 @@ options_validate(or_options_t *old_options, or_options_t *options,
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
}
+ if (options->NodeFamilies) {
+ options->NodeFamilySets = smartlist_create();
+ for (cl = options->NodeFamilies; cl; cl = cl->next) {
+ routerset_t *rs = routerset_new();
+ if (routerset_parse(rs, cl->value, cl->key) == 0) {
+ smartlist_add(options->NodeFamilySets, rs);
+ } else {
+ routerset_free(rs);
+ }
+ }
+ }
+
if (options->ExcludeNodes && options->StrictNodes) {
COMPLAIN("You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
"features to be broken in unpredictable ways.");
}
- if (options->EntryNodes && !routerset_is_list(options->EntryNodes)) {
- /* XXXX fix this; see entry_guards_prepend_from_config(). */
- REJECT("IPs or countries are not yet supported in EntryNodes.");
- }
-
if (options->AuthoritativeDir) {
if (!options->ContactInfo && !options->TestingTorNetwork)
REJECT("Authoritative directory servers must set ContactInfo");
@@ -3272,9 +3383,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if ((options->BridgeRelay
- || options->_PublishServerDescriptor & BRIDGE_AUTHORITY)
+ || options->_PublishServerDescriptor & BRIDGE_DIRINFO)
&& (options->_PublishServerDescriptor
- & (V1_AUTHORITY|V2_AUTHORITY|V3_AUTHORITY))) {
+ & (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
REJECT("Bridges are not supposed to publish router descriptors to the "
"directory authorities. Please correct your "
"PublishServerDescriptor line.");
@@ -3317,6 +3428,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT;
}
+ if (options->HeartbeatPeriod &&
+ options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD) {
+ log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; "
+ "raising to %d seconds.", MIN_HEARTBEAT_PERIOD);
+ options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD;
+ }
+
if (options->KeepalivePeriod < 1)
REJECT("KeepalivePeriod option must be positive.");
@@ -3480,6 +3598,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
+ if (options->OwningControllerProcess) {
+ const char *validate_pspec_msg = NULL;
+ if (tor_validate_process_specifier(options->OwningControllerProcess,
+ &validate_pspec_msg)) {
+ tor_asprintf(msg, "Bad OwningControllerProcess: %s",
+ validate_pspec_msg);
+ return -1;
+ }
+ }
+
if (options->ControlListenAddress) {
int all_are_local = 1;
config_line_t *ln;
@@ -3534,8 +3662,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (check_nickname_list(options->MyFamily, "MyFamily", msg))
return -1;
for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (check_nickname_list(cl->value, "NodeFamily", msg))
+ routerset_t *rs = routerset_new();
+ if (routerset_parse(rs, cl->value, cl->key)) {
+ routerset_free(rs);
return -1;
+ }
+ routerset_free(rs);
}
if (validate_addr_policies(options, msg) < 0)
@@ -3745,7 +3877,8 @@ opt_streq(const char *s1, const char *s2)
/** Check if any of the previous options have changed but aren't allowed to. */
static int
-options_transition_allowed(or_options_t *old, or_options_t *new_val,
+options_transition_allowed(const or_options_t *old,
+ const or_options_t *new_val,
char **msg)
{
if (!old)
@@ -3801,8 +3934,8 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val,
/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
* will require us to rotate the CPU and DNS workers; else return 0. */
static int
-options_transition_affects_workers(or_options_t *old_options,
- or_options_t *new_options)
+options_transition_affects_workers(const or_options_t *old_options,
+ const or_options_t *new_options)
{
if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
old_options->NumCPUs != new_options->NumCPUs ||
@@ -3825,8 +3958,8 @@ options_transition_affects_workers(or_options_t *old_options,
/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
* will require us to generate a new descriptor; else return 0. */
static int
-options_transition_affects_descriptor(or_options_t *old_options,
- or_options_t *new_options)
+options_transition_affects_descriptor(const or_options_t *old_options,
+ const or_options_t *new_options)
{
/* XXX We can be smarter here. If your DirPort isn't being
* published and you just turned it off, no need to republish. Etc. */
@@ -4031,6 +4164,8 @@ load_torrc_from_disk(int argc, char **argv)
"Unable to open configuration file \"%s\".", fname);
goto err;
}
+ } else {
+ log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname);
}
return cf;
@@ -4191,9 +4326,9 @@ options_init_from_string(const char *cf,
/* Change defaults. */
int i;
for (i = 0; testing_tor_network_defaults[i].name; ++i) {
- config_var_t *new_var = &testing_tor_network_defaults[i];
+ const config_var_t *new_var = &testing_tor_network_defaults[i];
config_var_t *old_var =
- config_find_option(&options_format, new_var->name);
+ config_find_option_mutable(&options_format, new_var->name);
tor_assert(new_var);
tor_assert(old_var);
old_var->initvalue = new_var->initvalue;
@@ -4270,7 +4405,7 @@ get_torrc_fname(void)
* configuration <b>options</b>
*/
static void
-config_register_addressmaps(or_options_t *options)
+config_register_addressmaps(const or_options_t *options)
{
smartlist_t *elts;
config_line_t *opt;
@@ -4319,6 +4454,35 @@ options_init_logs(or_options_t *options, int validate_only)
options->RunAsDaemon;
#endif
+ if (options->LogTimeGranularity <= 0) {
+ log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
+ options->LogTimeGranularity);
+ return -1;
+ } else if (1000 % options->LogTimeGranularity != 0 &&
+ options->LogTimeGranularity % 1000 != 0) {
+ int granularity = options->LogTimeGranularity;
+ if (granularity < 40) {
+ do granularity++;
+ while (1000 % granularity != 0);
+ } else if (granularity < 1000) {
+ granularity = 1000 / granularity;
+ while (1000 % granularity != 0)
+ granularity--;
+ granularity = 1000 / granularity;
+ } else {
+ granularity = 1000 * ((granularity / 1000) + 1);
+ }
+ log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a "
+ "divisor or a multiple of 1 second. Changing to "
+ "'%d'.",
+ options->LogTimeGranularity, granularity);
+ if (!validate_only)
+ set_log_time_granularity(granularity);
+ } else {
+ if (!validate_only)
+ set_log_time_granularity(options->LogTimeGranularity);
+ }
+
ok = 1;
elts = smartlist_create();
@@ -4472,7 +4636,7 @@ parse_bridge_line(const char *line, int validate_only)
* bits it's missing) as a valid authority. Return 0 on success,
* or -1 if the line isn't well-formed or if we can't add it. */
static int
-parse_dir_server_line(const char *line, authority_type_t required_type,
+parse_dir_server_line(const char *line, dirinfo_type_t required_type,
int validate_only)
{
smartlist_t *items = NULL;
@@ -4481,7 +4645,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
uint16_t dir_port = 0, or_port = 0;
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
- authority_type_t type = V2_AUTHORITY;
+ dirinfo_type_t type = V2_DIRINFO;
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
items = smartlist_create();
@@ -4502,13 +4666,13 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
if (TOR_ISDIGIT(flag[0]))
break;
if (!strcasecmp(flag, "v1")) {
- type |= (V1_AUTHORITY | HIDSERV_AUTHORITY);
+ type |= (V1_DIRINFO | HIDSERV_DIRINFO);
} else if (!strcasecmp(flag, "hs")) {
- type |= HIDSERV_AUTHORITY;
+ type |= HIDSERV_DIRINFO;
} else if (!strcasecmp(flag, "no-hs")) {
is_not_hidserv_authority = 1;
} else if (!strcasecmp(flag, "bridge")) {
- type |= BRIDGE_AUTHORITY;
+ type |= BRIDGE_DIRINFO;
} else if (!strcasecmp(flag, "no-v2")) {
is_not_v2_authority = 1;
} else if (!strcasecmpstart(flag, "orport=")) {
@@ -4525,7 +4689,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
flag);
} else {
- type |= V3_AUTHORITY;
+ type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
}
} else {
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
@@ -4535,9 +4699,9 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
smartlist_del_keeporder(items, 0);
}
if (is_not_hidserv_authority)
- type &= ~HIDSERV_AUTHORITY;
+ type &= ~HIDSERV_DIRINFO;
if (is_not_v2_authority)
- type &= ~V2_AUTHORITY;
+ type &= ~V2_DIRINFO;
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
@@ -4671,7 +4835,7 @@ validate_data_directory(or_options_t *options)
* doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
* replace it. Return 0 on success, -1 on failure. */
static int
-write_configuration_file(const char *fname, or_options_t *options)
+write_configuration_file(const char *fname, const or_options_t *options)
{
char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
int rename_old = 0, r;
@@ -4812,6 +4976,26 @@ static struct unit_table_t time_units[] = {
{ NULL, 0 },
};
+/** Table to map the names of time units to the number of milliseconds
+ * they contain. */
+static struct unit_table_t time_msec_units[] = {
+ { "", 1 },
+ { "msec", 1 },
+ { "millisecond", 1 },
+ { "milliseconds", 1 },
+ { "second", 1000 },
+ { "seconds", 1000 },
+ { "minute", 60*1000 },
+ { "minutes", 60*1000 },
+ { "hour", 60*60*1000 },
+ { "hours", 60*60*1000 },
+ { "day", 24*60*60*1000 },
+ { "days", 24*60*60*1000 },
+ { "week", 7*24*60*60*1000 },
+ { "weeks", 7*24*60*60*1000 },
+ { NULL, 0 },
+};
+
/** Parse a string <b>val</b> containing a number, zero or more
* spaces, and an optional unit string. If the unit appears in the
* table <b>u</b>, then multiply the number by the unit multiplier.
@@ -4875,6 +5059,25 @@ config_parse_memunit(const char *s, int *ok)
return u;
}
+/** Parse a string in the format "number unit", where unit is a unit of
+ * time in milliseconds. On success, set *<b>ok</b> to true and return
+ * the number of milliseconds in the provided interval. Otherwise, set
+ * *<b>ok</b> to 0 and return -1. */
+static int
+config_parse_msec_interval(const char *s, int *ok)
+{
+ uint64_t r;
+ r = config_parse_units(s, time_msec_units, ok);
+ if (!ok)
+ return -1;
+ if (r > INT_MAX) {
+ log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
+ *ok = 0;
+ return -1;
+ }
+ return (int)r;
+}
+
/** Parse a string in the format "number unit", where unit is a unit of time.
* On success, set *<b>ok</b> to true and return the number of seconds in
* the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
@@ -4894,13 +5097,29 @@ config_parse_interval(const char *s, int *ok)
return (int)r;
}
+/** Return the number of cpus configured in <b>options</b>. If we are
+ * told to auto-detect the number of cpus, return the auto-detected number. */
+int
+get_num_cpus(const or_options_t *options)
+{
+ if (options->NumCPUs == 0) {
+ int n = compute_num_cpus();
+ return (n >= 1) ? n : 1;
+ } else {
+ return options->NumCPUs;
+ }
+}
+
/**
* Initialize the libevent library.
*/
static void
-init_libevent(void)
+init_libevent(const or_options_t *options)
{
const char *badness=NULL;
+ tor_libevent_cfg cfg;
+
+ tor_assert(options);
configure_libevent_logging();
/* If the kernel complains that some method (say, epoll) doesn't
@@ -4910,7 +5129,11 @@ init_libevent(void)
tor_check_libevent_header_compatibility();
- tor_libevent_initialize();
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.disable_iocp = options->DisableIOCP;
+ cfg.num_cpus = get_num_cpus(options);
+
+ tor_libevent_initialize(&cfg);
suppress_libevent_log_msg(NULL);
@@ -4949,7 +5172,7 @@ get_or_state(void)
* Note: Consider using the get_datadir_fname* macros in or.h.
*/
char *
-options_get_datadir_fname2_suffix(or_options_t *options,
+options_get_datadir_fname2_suffix(const or_options_t *options,
const char *sub1, const char *sub2,
const char *suffix)
{
@@ -5266,7 +5489,7 @@ getinfo_helper_config(control_connection_t *conn,
smartlist_t *sl = smartlist_create();
int i;
for (i = 0; _option_vars[i].name; ++i) {
- config_var_t *var = &_option_vars[i];
+ const config_var_t *var = &_option_vars[i];
const char *type;
char *line;
switch (var->type) {
@@ -5275,9 +5498,11 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_UINT: type = "Integer"; break;
case CONFIG_TYPE_PORT: type = "Port"; break;
case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
+ case CONFIG_TYPE_MSEC_INTERVAL: type = "TimeMsecInterval"; break;
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
+ case CONFIG_TYPE_AUTOBOOL: type = "Boolean+Auto"; break;
case CONFIG_TYPE_ISOTIME: type = "Time"; break;
case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
case CONFIG_TYPE_CSV: type = "CommaList"; break;
diff --git a/src/or/config.h b/src/or/config.h
index 78a67dddf..bc7119143 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -13,7 +13,8 @@
#define _TOR_CONFIG_H
const char *get_dirportfrontpage(void);
-or_options_t *get_options(void);
+const or_options_t *get_options(void);
+or_options_t *get_options_mutable(void);
int set_options(or_options_t *new_val, char **msg);
void config_free_all(void);
const char *safe_str_client(const char *address);
@@ -26,21 +27,21 @@ int config_get_lines(const char *string, config_line_t **result);
void config_free_lines(config_line_t *front);
setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
-int resolve_my_address(int warn_severity, or_options_t *options,
+int resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr, char **hostname_out);
int is_local_addr(const tor_addr_t *addr) ATTR_PURE;
void options_init(or_options_t *options);
-char *options_dump(or_options_t *options, int minimal);
+char *options_dump(const or_options_t *options, int minimal);
int options_init_from_torrc(int argc, char **argv);
setopt_err_t options_init_from_string(const char *cf,
int command, const char *command_arg, char **msg);
int option_is_recognized(const char *key);
const char *option_get_canonical_name(const char *key);
-config_line_t *option_get_assignment(or_options_t *options,
+config_line_t *option_get_assignment(const or_options_t *options,
const char *key);
int options_save_current(void);
const char *get_torrc_fname(void);
-char *options_get_datadir_fname2_suffix(or_options_t *options,
+char *options_get_datadir_fname2_suffix(const or_options_t *options,
const char *sub1, const char *sub2,
const char *suffix);
#define get_datadir_fname2_suffix(sub1, sub2, suffix) \
@@ -57,18 +58,21 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
#define get_datadir_fname_suffix(sub1, suffix) \
get_datadir_fname2_suffix((sub1), NULL, (suffix))
+int get_num_cpus(const or_options_t *options);
+
or_state_t *get_or_state(void);
int did_last_state_file_write_fail(void);
int or_state_save(time_t now);
-int options_need_geoip_info(or_options_t *options, const char **reason_out);
+int options_need_geoip_info(const or_options_t *options,
+ const char **reason_out);
int getinfo_helper_config(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
const char *tor_get_digests(void);
-uint32_t get_effective_bwrate(or_options_t *options);
-uint32_t get_effective_bwburst(or_options_t *options);
+uint32_t get_effective_bwrate(const or_options_t *options);
+uint32_t get_effective_bwburst(const or_options_t *options);
#ifdef CONFIG_PRIVATE
/* Used only by config.c and test.c */
diff --git a/src/or/connection.c b/src/or/connection.c
index 72414589c..c84ee04d5 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -36,6 +36,10 @@
#include "router.h"
#include "routerparse.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/event.h>
+#endif
+
static connection_t *connection_create_listener(
const struct sockaddr *listensockaddr,
socklen_t listensocklen, int type,
@@ -45,8 +49,10 @@ static void connection_init(time_t now, connection_t *conn, int type,
static int connection_init_accepted_conn(connection_t *conn,
uint8_t listener_type);
static int connection_handle_listener_read(connection_t *conn, int new_type);
+#ifndef USE_BUFFEREVENTS
static int connection_bucket_should_increase(int bucket,
or_connection_t *conn);
+#endif
static int connection_finished_flushing(connection_t *conn);
static int connection_flushed_some(connection_t *conn);
static int connection_finished_connecting(connection_t *conn);
@@ -54,8 +60,8 @@ static int connection_reached_eof(connection_t *conn);
static int connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
int *socket_error);
static int connection_process_inbuf(connection_t *conn, int package_partial);
-static void client_check_address_changed(int sock);
-static void set_constrained_socket_buffers(int sock, int size);
+static void client_check_address_changed(tor_socket_t sock);
+static void set_constrained_socket_buffers(tor_socket_t sock, int size);
static const char *connection_proxy_state_to_string(int state);
static int connection_read_https_proxy_response(connection_t *conn);
@@ -183,6 +189,26 @@ conn_state_to_string(int type, int state)
return buf;
}
+#ifdef USE_BUFFEREVENTS
+/** Return true iff the connection's type is one that can use a
+ bufferevent-based implementation. */
+int
+connection_type_uses_bufferevent(connection_t *conn)
+{
+ switch (conn->type) {
+ case CONN_TYPE_AP:
+ case CONN_TYPE_EXIT:
+ case CONN_TYPE_DIR:
+ case CONN_TYPE_CONTROL:
+ case CONN_TYPE_OR:
+ case CONN_TYPE_CPUWORKER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+#endif
+
/** Allocate and return a new dir_connection_t, initialized as by
* connection_init(). */
dir_connection_t *
@@ -308,10 +334,13 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
conn->type = type;
conn->socket_family = socket_family;
- if (!connection_is_listener(conn)) { /* listeners never use their buf */
+#ifndef USE_BUFFEREVENTS
+ if (!connection_is_listener(conn)) {
+ /* listeners never use their buf */
conn->inbuf = buf_new();
conn->outbuf = buf_new();
}
+#endif
conn->timestamp_created = now;
conn->timestamp_lastread = now;
@@ -377,7 +406,8 @@ _connection_free(connection_t *conn)
"bytes on inbuf, %d on outbuf.",
conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
- (int)buf_datalen(conn->inbuf), (int)buf_datalen(conn->outbuf));
+ (int)connection_get_inbuf_len(conn),
+ (int)connection_get_outbuf_len(conn));
}
if (!connection_is_listener(conn)) {
@@ -424,6 +454,15 @@ _connection_free(connection_t *conn)
tor_free(conn->read_event); /* Probably already freed by connection_free. */
tor_free(conn->write_event); /* Probably already freed by connection_free. */
+ IF_HAS_BUFFEREVENT(conn, {
+ /* This was a workaround to handle bugs in some old versions of libevent
+ * where callbacks can occur after calling bufferevent_free(). Setting
+ * the callbacks to NULL prevented this. It shouldn't be necessary any
+ * more, but let's not tempt fate for now. */
+ bufferevent_setcb(conn->bufev, NULL, NULL, NULL, NULL);
+ bufferevent_free(conn->bufev);
+ conn->bufev = NULL;
+ });
if (conn->type == CONN_TYPE_DIR) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
@@ -439,8 +478,8 @@ _connection_free(connection_t *conn)
rend_data_free(dir_conn->rend_data);
}
- if (conn->s >= 0) {
- log_debug(LD_NET,"closing fd %d.",conn->s);
+ if (SOCKET_OK(conn->s)) {
+ log_debug(LD_NET,"closing fd %d.",(int)conn->s);
tor_close_socket(conn->s);
conn->s = -1;
}
@@ -450,6 +489,11 @@ _connection_free(connection_t *conn)
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
}
+#ifdef USE_BUFFEREVENTS
+ if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
+ ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg);
+ }
+#endif
memset(mem, 0xCC, memlen); /* poison memory */
tor_free(mem);
@@ -479,8 +523,7 @@ connection_free(connection_t *conn)
}
}
if (conn->type == CONN_TYPE_CONTROL) {
- TO_CONTROL_CONN(conn)->event_mask = 0;
- control_update_global_event_mask();
+ connection_control_closed(TO_CONTROL_CONN(conn));
}
connection_unregister_events(conn);
_connection_free(conn);
@@ -576,7 +619,7 @@ connection_about_to_close_connection(connection_t *conn)
circuit_n_conn_done(TO_OR_CONN(conn), 0);
/* now mark things down as needed */
if (connection_or_nonopen_was_started_here(or_conn)) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
rep_hist_note_connect_failed(or_conn->identity_digest, now);
entry_guard_register_connect_status(or_conn->identity_digest,0,
!options->HTTPSProxy, now);
@@ -663,22 +706,21 @@ connection_close_immediate(connection_t *conn)
}
if (conn->outbuf_flushlen) {
log_info(LD_NET,"fd %d, type %s, state %s, %d bytes on outbuf.",
- conn->s, conn_type_to_string(conn->type),
+ (int)conn->s, conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
(int)conn->outbuf_flushlen);
}
connection_unregister_events(conn);
- if (conn->s >= 0)
+ if (SOCKET_OK(conn->s))
tor_close_socket(conn->s);
conn->s = -1;
if (conn->linked)
conn->linked_conn_is_closed = 1;
- if (!connection_is_listener(conn)) {
+ if (conn->outbuf)
buf_clear(conn->outbuf);
- conn->outbuf_flushlen = 0;
- }
+ conn->outbuf_flushlen = 0;
}
/** Mark <b>conn</b> to be closed next time we loop through
@@ -740,7 +782,7 @@ connection_expire_held_open(void)
log_fn(severity, LD_NET,
"Giving up on marked_for_close conn that's been flushing "
"for 15s (fd %d, type %s, state %s).",
- conn->s, conn_type_to_string(conn->type),
+ (int)conn->s, conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state));
conn->hold_open_until_flushed = 0;
}
@@ -812,7 +854,13 @@ create_unix_sockaddr(const char *listenaddress, char **readable_address,
sockaddr = tor_malloc_zero(sizeof(struct sockaddr_un));
sockaddr->sun_family = AF_UNIX;
- strncpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path));
+ if (strlcpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path))
+ >= sizeof(sockaddr->sun_path)) {
+ log_warn(LD_CONFIG, "Unix socket path '%s' is too long to fit.",
+ escaped(listenaddress));
+ tor_free(sockaddr);
+ return NULL;
+ }
if (readable_address)
*readable_address = tor_strdup(listenaddress);
@@ -857,7 +905,7 @@ warn_too_many_conns(void)
/** Check whether we should be willing to open an AF_UNIX socket in
* <b>path</b>. Return 0 if we should go ahead and -1 if we shouldn't. */
static int
-check_location_for_unix_socket(or_options_t *options, const char *path)
+check_location_for_unix_socket(const or_options_t *options, const char *path)
{
int r = -1;
char *p = tor_strdup(path);
@@ -868,7 +916,7 @@ check_location_for_unix_socket(or_options_t *options, const char *path)
if (options->ControlSocketsGroupWritable)
flags |= CPD_GROUP_OK;
- if (check_private_dir(p, flags) < 0) {
+ if (check_private_dir(p, flags, options->User) < 0) {
char *escpath, *escdir;
escpath = esc_for_log(path);
escdir = esc_for_log(p);
@@ -893,7 +941,7 @@ check_location_for_unix_socket(or_options_t *options, const char *path)
/** Tell the TCP stack that it shouldn't wait for a long time after
* <b>sock</b> has closed before reusing its port. */
static void
-make_socket_reuseable(int sock)
+make_socket_reuseable(tor_socket_t sock)
{
#ifdef MS_WINDOWS
(void) sock;
@@ -921,7 +969,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
int type, char* address)
{
connection_t *conn;
- int s; /* the socket we're going to make */
+ tor_socket_t s; /* the socket we're going to make */
uint16_t usePort = 0, gotPort = 0;
int start_reading = 0;
@@ -944,7 +992,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
s = tor_open_socket(PF_INET,
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
- if (s < 0) {
+ if (!SOCKET_OK(s)) {
log_warn(LD_NET,"Socket creation failed.");
goto err;
}
@@ -1137,20 +1185,20 @@ check_sockaddr_family_match(sa_family_t got, connection_t *listener)
static int
connection_handle_listener_read(connection_t *conn, int new_type)
{
- int news; /* the new socket */
+ tor_socket_t news; /* the new socket */
connection_t *newconn;
/* information about the remote peer when connecting to other routers */
char addrbuf[256];
struct sockaddr *remote = (struct sockaddr*)addrbuf;
/* length of the remote address. Must be whatever accept() needs. */
socklen_t remotelen = (socklen_t)sizeof(addrbuf);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
memset(addrbuf, 0, sizeof(addrbuf));
news = tor_accept_socket(conn->s,remote,&remotelen);
- if (news < 0) { /* accept() error */
+ if (!SOCKET_OK(news)) { /* accept() error */
int e = tor_socket_errno(conn->s);
if (ERRNO_IS_ACCEPT_EAGAIN(e)) {
return 0; /* he hung up before we could accept(). that's fine. */
@@ -1166,7 +1214,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
}
log_debug(LD_NET,
"Connection accepted on socket %d (child of fd %d).",
- news,conn->s);
+ (int)news,(int)conn->s);
make_socket_reuseable(news);
set_socket_nonblocking(news);
@@ -1319,11 +1367,12 @@ int
connection_connect(connection_t *conn, const char *address,
const tor_addr_t *addr, uint16_t port, int *socket_error)
{
- int s, inprogress = 0;
+ tor_socket_t s;
+ int inprogress = 0;
char addrbuf[256];
struct sockaddr *dest_addr;
- socklen_t dest_addr_len;
- or_options_t *options = get_options();
+ int dest_addr_len;
+ const or_options_t *options = get_options();
int protocol_family;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
@@ -1380,7 +1429,7 @@ connection_connect(connection_t *conn, const char *address,
make_socket_reuseable(s);
- if (connect(s, dest_addr, dest_addr_len) < 0) {
+ if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
/* yuck. kill it. */
@@ -1405,7 +1454,7 @@ connection_connect(connection_t *conn, const char *address,
escaped_safe_str_client(address),
port, inprogress?"in progress":"established", s);
conn->s = s;
- if (connection_add(conn) < 0) /* no space, forget it */
+ if (connection_add_connecting(conn) < 0) /* no space, forget it */
return -1;
return inprogress ? 0 : 1;
}
@@ -1446,7 +1495,7 @@ connection_proxy_state_to_string(int state)
int
connection_proxy_connect(connection_t *conn, int type)
{
- or_options_t *options;
+ const or_options_t *options;
tor_assert(conn);
@@ -1638,6 +1687,19 @@ connection_send_socks5_connect(connection_t *conn)
conn->proxy_state = PROXY_SOCKS5_WANT_CONNECT_OK;
}
+/** DOCDOC */
+static int
+connection_fetch_from_buf_socks_client(connection_t *conn,
+ int state, char **reason)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_from_evbuffer_socks_client(input, state, reason);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_socks_client(conn->inbuf, state, reason);
+ }
+}
+
/** Call this from connection_*_process_inbuf() to advance the proxy
* handshake.
*
@@ -1665,17 +1727,17 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS4_WANT_CONNECT_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
if (ret == 1)
conn->proxy_state = PROXY_CONNECTED;
break;
case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* no auth needed, do connect */
if (ret == 1) {
connection_send_socks5_connect(conn);
@@ -1684,9 +1746,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* send auth if needed, otherwise do connect */
if (ret == 1) {
@@ -1721,9 +1783,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* send the connect request */
if (ret == 1) {
connection_send_socks5_connect(conn);
@@ -1732,9 +1794,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_CONNECT_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
if (ret == 1)
conn->proxy_state = PROXY_CONNECTED;
break;
@@ -1949,38 +2011,41 @@ int
retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ int retval = 0;
+ const uint16_t old_or_port = router_get_advertised_or_port(options);
+ const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
options->ORPort, "0.0.0.0",
replaced_conns, new_conns, options->ClientOnly,
AF_INET)<0)
- return -1;
+ retval = -1;
if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
options->DirPort, "0.0.0.0",
replaced_conns, new_conns, options->ClientOnly,
AF_INET)<0)
- return -1;
+ retval = -1;
if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
options->SocksPort, "127.0.0.1",
replaced_conns, new_conns, 0,
AF_INET)<0)
- return -1;
+ retval = -1;
if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
options->TransPort, "127.0.0.1",
replaced_conns, new_conns, 0,
AF_INET)<0)
- return -1;
+ retval = -1;
if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NATDListenAddress,
options->NATDPort, "127.0.0.1",
replaced_conns, new_conns, 0,
AF_INET)<0)
- return -1;
+ retval = -1;
if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress,
options->DNSPort, "127.0.0.1",
replaced_conns, new_conns, 0,
AF_INET)<0)
- return -1;
+ retval = -1;
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
options->ControlListenAddress,
options->ControlPort, "127.0.0.1",
@@ -1994,7 +2059,16 @@ retry_all_listeners(smartlist_t *replaced_conns,
AF_UNIX)<0)
return -1;
- return 0;
+ if (old_or_port != router_get_advertised_or_port(options) ||
+ old_dir_port != router_get_advertised_dir_port(options, 0)) {
+ /* Our chosen ORPort or DirPort is not what it used to be: the
+ * descriptor we had (if any) should be regenerated. (We won't
+ * automatically notice this because of changes in the option,
+ * since the value could be "auto".) */
+ mark_my_descriptor_dirty("Chosen Or/DirPort changed");
+ }
+
+ return retval;
}
/** Return 1 if we should apply rate limiting to <b>conn</b>,
@@ -2003,14 +2077,20 @@ retry_all_listeners(smartlist_t *replaced_conns,
static int
connection_is_rate_limited(connection_t *conn)
{
- if (conn->linked || /* internal connection */
- tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
- tor_addr_is_internal(&conn->addr, 0)) /* internal address */
- return 0;
+ const or_options_t *options = get_options();
+ if (conn->linked)
+ return 0; /* Internal connection */
+ else if (! options->CountPrivateBandwidth &&
+ (tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
+ tor_addr_is_internal(&conn->addr, 0)))
+ return 0; /* Internal address */
else
return 1;
}
+#ifdef USE_BUFFEREVENTS
+static struct bufferevent_rate_limit_group *global_rate_limit = NULL;
+#else
extern int global_read_bucket, global_write_bucket;
extern int global_relayed_read_bucket, global_relayed_write_bucket;
@@ -2018,11 +2098,13 @@ extern int global_relayed_read_bucket, global_relayed_write_bucket;
* we are likely to run dry again this second, so be stingy with the
* tokens we just put in. */
static int write_buckets_empty_last_second = 0;
+#endif
/** How many seconds of no active local circuits will make the
* connection revert to the "relayed" bandwidth class? */
#define CLIENT_IDLE_TIME_FOR_PRIORITY 30
+#ifndef USE_BUFFEREVENTS
/** Return 1 if <b>conn</b> should use tokens from the "relayed"
* bandwidth rates, else 0. Currently, only OR conns with bandwidth
* class 1, and directory conns that are serving data out, count.
@@ -2133,6 +2215,20 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
return connection_bucket_round_robin(base, priority,
global_bucket, conn_bucket);
}
+#else
+static ssize_t
+connection_bucket_read_limit(connection_t *conn, time_t now)
+{
+ (void) now;
+ return bufferevent_get_max_to_read(conn->bufev);
+}
+ssize_t
+connection_bucket_write_limit(connection_t *conn, time_t now)
+{
+ (void) now;
+ return bufferevent_get_max_to_write(conn->bufev);
+}
+#endif
/** Return 1 if the global write buckets are low enough that we
* shouldn't send <b>attempt</b> bytes of low-priority directory stuff
@@ -2157,8 +2253,12 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
int
global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
{
+#ifdef USE_BUFFEREVENTS
+ ssize_t smaller_bucket = bufferevent_get_max_to_write(conn->bufev);
+#else
int smaller_bucket = global_write_bucket < global_relayed_write_bucket ?
global_write_bucket : global_relayed_write_bucket;
+#endif
if (authdir_mode(get_options()) && priority>1)
return 0; /* there's always room to answer v2 if we're an auth dir */
@@ -2168,12 +2268,14 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
if (smaller_bucket < (int)attempt)
return 1; /* not enough space no matter the priority */
+#ifndef USE_BUFFEREVENTS
if (write_buckets_empty_last_second)
return 1; /* we're already hitting our limits, no more please */
+#endif
if (priority == 1) { /* old-style v1 query */
/* Could we handle *two* of these requests within the next two seconds? */
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int64_t can_write = (int64_t)smaller_bucket
+ 2*(options->RelayBandwidthRate ? options->RelayBandwidthRate :
options->BandwidthRate);
@@ -2185,6 +2287,7 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
return 0;
}
+#ifndef USE_BUFFEREVENTS
/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes
* onto <b>conn</b>. Decrement buckets appropriately. */
static void
@@ -2212,6 +2315,11 @@ connection_buckets_decrement(connection_t *conn, time_t now,
if (!connection_is_rate_limited(conn))
return; /* local IPs are free */
+
+ if (conn->type == CONN_TYPE_OR)
+ rep_hist_note_or_conn_bytes(conn->global_identifier, num_read,
+ num_written, now);
+
if (num_read > 0) {
rep_hist_note_bytes_read(num_read, now);
}
@@ -2285,7 +2393,7 @@ connection_consider_empty_write_buckets(connection_t *conn)
void
connection_bucket_init(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* start it at max traffic */
global_read_bucket = (int)options->BandwidthBurst;
global_write_bucket = (int)options->BandwidthBurst;
@@ -2330,7 +2438,7 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst,
void
connection_bucket_refill(int seconds_elapsed, time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *conns = get_connection_array();
int relayrate, relayburst;
@@ -2393,7 +2501,7 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
TO_OR_CONN(conn)->read_bucket > 0)) {
/* and either a non-cell conn or a cell conn with non-empty bucket */
LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,
- "waking up conn (fd %d) for read", conn->s));
+ "waking up conn (fd %d) for read", (int)conn->s));
conn->read_blocked_on_bw = 0;
connection_start_reading(conn);
}
@@ -2406,7 +2514,7 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
conn->state != OR_CONN_STATE_OPEN ||
TO_OR_CONN(conn)->write_bucket > 0)) {
LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,
- "waking up conn (fd %d) for write", conn->s));
+ "waking up conn (fd %d) for write", (int)conn->s));
conn->write_blocked_on_bw = 0;
connection_start_writing(conn);
}
@@ -2428,6 +2536,88 @@ connection_bucket_should_increase(int bucket, or_connection_t *conn)
return 1;
}
+#else
+
+static void
+connection_buckets_decrement(connection_t *conn, time_t now,
+ size_t num_read, size_t num_written)
+{
+ (void) conn;
+ (void) now;
+ (void) num_read;
+ (void) num_written;
+ /* Libevent does this for us. */
+}
+void
+connection_bucket_refill(int seconds_elapsed, time_t now)
+{
+ (void) seconds_elapsed;
+ (void) now;
+ /* Libevent does this for us. */
+}
+void
+connection_bucket_init(void)
+{
+ const or_options_t *options = get_options();
+ const struct timeval *tick = tor_libevent_get_one_tick_timeout();
+ struct ev_token_bucket_cfg *bucket_cfg;
+
+ uint64_t rate, burst;
+ if (options->RelayBandwidthRate) {
+ rate = options->RelayBandwidthRate;
+ burst = options->RelayBandwidthBurst;
+ } else {
+ rate = options->BandwidthRate;
+ burst = options->BandwidthBurst;
+ }
+
+ rate /= TOR_LIBEVENT_TICKS_PER_SECOND;
+ bucket_cfg = ev_token_bucket_cfg_new((uint32_t)rate, (uint32_t)burst,
+ (uint32_t)rate, (uint32_t)burst,
+ tick);
+
+ if (!global_rate_limit) {
+ global_rate_limit =
+ bufferevent_rate_limit_group_new(tor_libevent_get_base(), bucket_cfg);
+ } else {
+ bufferevent_rate_limit_group_set_cfg(global_rate_limit, bucket_cfg);
+ }
+ ev_token_bucket_cfg_free(bucket_cfg);
+}
+
+void
+connection_get_rate_limit_totals(uint64_t *read_out, uint64_t *written_out)
+{
+ if (global_rate_limit == NULL) {
+ *read_out = *written_out = 0;
+ } else {
+ bufferevent_rate_limit_group_get_totals(
+ global_rate_limit, read_out, written_out);
+ }
+}
+
+/** DOCDOC */
+void
+connection_enable_rate_limiting(connection_t *conn)
+{
+ if (conn->bufev) {
+ if (!global_rate_limit)
+ connection_bucket_init();
+ bufferevent_add_to_rate_limit_group(conn->bufev, global_rate_limit);
+ }
+}
+
+static void
+connection_consider_empty_write_buckets(connection_t *conn)
+{
+ (void) conn;
+}
+static void
+connection_consider_empty_read_buckets(connection_t *conn)
+{
+ (void) conn;
+}
+#endif
/** Read bytes from conn-\>s and process them.
*
@@ -2598,7 +2788,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
log_debug(LD_NET,
"%d: starting, inbuf_datalen %ld (%d pending in tls object)."
" at_most %ld.",
- conn->s,(long)buf_datalen(conn->inbuf),
+ (int)conn->s,(long)buf_datalen(conn->inbuf),
tor_tls_get_pending_bytes(or_conn->tls), (long)at_most);
initial_size = buf_datalen(conn->inbuf);
@@ -2682,7 +2872,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
}
if (n_read > 0) {
- /* change *max_to_read */
+ /* change *max_to_read */
*max_to_read = at_most - n_read;
/* Update edge_conn->n_read */
@@ -2714,11 +2904,205 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
return 0;
}
+#ifdef USE_BUFFEREVENTS
+/* XXXX These generic versions could be simplified by making them
+ type-specific */
+
+/** Callback: Invoked whenever bytes are added to or drained from an input
+ * evbuffer. Used to track the number of bytes read. */
+static void
+evbuffer_inbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *info, void *arg)
+{
+ connection_t *conn = arg;
+ (void) buf;
+ /* XXXX These need to get real counts on the non-nested TLS case. - NM */
+ if (info->n_added) {
+ time_t now = approx_time();
+ conn->timestamp_lastread = now;
+ connection_buckets_decrement(conn, now, info->n_added, 0);
+ connection_consider_empty_read_buckets(conn);
+ if (conn->type == CONN_TYPE_AP) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ /*XXXX022 check for overflow*/
+ edge_conn->n_read += (int)info->n_added;
+ }
+ }
+}
+
+/** Callback: Invoked whenever bytes are added to or drained from an output
+ * evbuffer. Used to track the number of bytes written. */
+static void
+evbuffer_outbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *info, void *arg)
+{
+ connection_t *conn = arg;
+ (void)buf;
+ if (info->n_deleted) {
+ time_t now = approx_time();
+ conn->timestamp_lastwritten = now;
+ connection_buckets_decrement(conn, now, 0, info->n_deleted);
+ connection_consider_empty_write_buckets(conn);
+ if (conn->type == CONN_TYPE_AP) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ /*XXXX022 check for overflow*/
+ edge_conn->n_written += (int)info->n_deleted;
+ }
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has read data. */
+void
+connection_handle_read_cb(struct bufferevent *bufev, void *arg)
+{
+ connection_t *conn = arg;
+ (void) bufev;
+ if (!conn->marked_for_close) {
+ if (connection_process_inbuf(conn, 1)<0) /* XXXX Always 1? */
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has written data. */
+void
+connection_handle_write_cb(struct bufferevent *bufev, void *arg)
+{
+ connection_t *conn = arg;
+ struct evbuffer *output;
+ if (connection_flushed_some(conn)<0) {
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ return;
+ }
+
+ output = bufferevent_get_output(bufev);
+ if (!evbuffer_get_length(output)) {
+ connection_finished_flushing(conn);
+ if (conn->marked_for_close && conn->hold_open_until_flushed) {
+ conn->hold_open_until_flushed = 0;
+ if (conn->linked) {
+ /* send eof */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has had an event (like a
+ * connection, or an eof, or an error) occur. */
+void
+connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg)
+{
+ connection_t *conn = arg;
+ (void) bufev;
+ if (event & BEV_EVENT_CONNECTED) {
+ tor_assert(connection_state_is_connecting(conn));
+ if (connection_finished_connecting(conn)<0)
+ return;
+ }
+ if (event & BEV_EVENT_EOF) {
+ if (!conn->marked_for_close) {
+ conn->inbuf_reached_eof = 1;
+ if (connection_reached_eof(conn)<0)
+ return;
+ }
+ }
+ if (event & BEV_EVENT_ERROR) {
+ int socket_error = evutil_socket_geterror(conn->s);
+ if (conn->type == CONN_TYPE_OR &&
+ conn->state == OR_CONN_STATE_CONNECTING) {
+ connection_or_connect_failed(TO_OR_CONN(conn),
+ errno_to_orconn_end_reason(socket_error),
+ tor_socket_strerror(socket_error));
+ } else if (CONN_IS_EDGE(conn)) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ if (!edge_conn->edge_has_sent_end)
+ connection_edge_end_errno(edge_conn);
+ if (edge_conn->socks_request) /* broken, don't send a socks reply back */
+ edge_conn->socks_request->has_finished = 1;
+ }
+ connection_close_immediate(conn); /* Connection is dead. */
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ }
+}
+
+/** Set up the generic callbacks for the bufferevent on <b>conn</b>. */
+void
+connection_configure_bufferevent_callbacks(connection_t *conn)
+{
+ struct bufferevent *bufev;
+ struct evbuffer *input, *output;
+ tor_assert(conn->bufev);
+ bufev = conn->bufev;
+ bufferevent_setcb(bufev,
+ connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_handle_event_cb,
+ conn);
+
+ input = bufferevent_get_input(bufev);
+ output = bufferevent_get_output(bufev);
+ evbuffer_add_cb(input, evbuffer_inbuf_callback, conn);
+ evbuffer_add_cb(output, evbuffer_outbuf_callback, conn);
+}
+#endif
+
/** A pass-through to fetch_from_buf. */
int
connection_fetch_from_buf(char *string, size_t len, connection_t *conn)
{
- return fetch_from_buf(string, len, conn->inbuf);
+ IF_HAS_BUFFEREVENT(conn, {
+ /* XXX overflow -seb */
+ return (int)bufferevent_read(conn->bufev, string, len);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf(string, len, conn->inbuf);
+ }
+}
+
+/** As fetch_from_buf_line(), but read from a connection's input buffer. */
+int
+connection_fetch_from_buf_line(connection_t *conn, char *data,
+ size_t *data_len)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ int r;
+ size_t eol_len=0;
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ struct evbuffer_ptr ptr =
+ evbuffer_search_eol(input, NULL, &eol_len, EVBUFFER_EOL_LF);
+ if (ptr.pos == -1)
+ return 0; /* No EOL found. */
+ if ((size_t)ptr.pos+eol_len >= *data_len) {
+ return -1; /* Too long */
+ }
+ *data_len = ptr.pos+eol_len;
+ r = evbuffer_remove(input, data, ptr.pos+eol_len);
+ tor_assert(r >= 0);
+ data[ptr.pos+eol_len] = '\0';
+ return 1;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_line(conn->inbuf, data, data_len);
+ }
+}
+
+/** As fetch_from_buf_http, but fetches from a conncetion's input buffer_t or
+ * its bufferevent as appropriate. */
+int
+connection_fetch_from_buf_http(connection_t *conn,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used,
+ size_t max_bodylen, int force_complete)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_from_evbuffer_http(input, headers_out, max_headerlen,
+ body_out, body_used, max_bodylen, force_complete);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_http(conn->inbuf, headers_out, max_headerlen,
+ body_out, body_used, max_bodylen, force_complete);
+ }
}
/** Return conn-\>outbuf_flushlen: how many bytes conn wants to flush
@@ -2739,15 +3123,15 @@ connection_outbuf_too_full(connection_t *conn)
return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE);
}
-/** Try to flush more bytes onto conn-\>s.
+/** Try to flush more bytes onto <b>conn</b>-\>s.
*
* This function gets called either from conn_write() in main.c
* when poll() has declared that conn wants to write, or below
* from connection_write_to_buf() when an entire TLS record is ready.
*
- * Update conn-\>timestamp_lastwritten to now, and call flush_buf
+ * Update <b>conn</b>-\>timestamp_lastwritten to now, and call flush_buf
* or flush_buf_tls appropriately. If it succeeds and there are no more
- * more bytes on conn->outbuf, then call connection_finished_flushing
+ * more bytes on <b>conn</b>-\>outbuf, then call connection_finished_flushing
* on it too.
*
* If <b>force</b>, then write as many bytes as possible, ignoring bandwidth
@@ -2769,7 +3153,7 @@ connection_handle_write_impl(connection_t *conn, int force)
tor_assert(!connection_is_listener(conn));
- if (conn->marked_for_close || conn->s < 0)
+ if (conn->marked_for_close || !SOCKET_OK(conn->s))
return 0; /* do nothing */
if (conn->in_flushed_some) {
@@ -2839,6 +3223,7 @@ connection_handle_write_impl(connection_t *conn, int force)
/* If we just flushed the last bytes, check if this tunneled dir
* request is done. */
+ /* XXXX move this to flushed_some or finished_flushing -NM */
if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id)
geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
DIRREQ_OR_CONN_BUFFER_FLUSHED);
@@ -2894,6 +3279,7 @@ connection_handle_write_impl(connection_t *conn, int force)
if (n_written && conn->type == CONN_TYPE_AP) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+
/* Check for overflow: */
if (PREDICT_LIKELY(UINT32_MAX - edge_conn->n_written > n_written))
edge_conn->n_written += (int)n_written;
@@ -2937,6 +3323,25 @@ connection_handle_write(connection_t *conn, int force)
return res;
}
+/**
+ * Try to flush data that's waiting for a write on <b>conn</b>. Return
+ * -1 on failure, 0 on success.
+ *
+ * Don't use this function for regular writing; the buffers/bufferevents
+ * system should be good enough at scheduling writes there. Instead, this
+ * function is for cases when we're about to exit or something and we want
+ * to report it right away.
+ */
+int
+connection_flush(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ int r = bufferevent_flush(conn->bufev, EV_WRITE, BEV_FLUSH);
+ return (r < 0) ? -1 : 0;
+ });
+ return connection_handle_write(conn, 1);
+}
+
/** OpenSSL TLS record size is 16383; this is close. The goal here is to
* push data out as soon as we know there's enough for a TLS record, so
* during periods of high load we won't read entire megabytes from
@@ -2970,6 +3375,22 @@ _connection_write_to_buf_impl(const char *string, size_t len,
if (conn->marked_for_close && !conn->hold_open_until_flushed)
return;
+ IF_HAS_BUFFEREVENT(conn, {
+ if (zlib) {
+ int done = zlib < 0;
+ r = write_to_evbuffer_zlib(bufferevent_get_output(conn->bufev),
+ TO_DIR_CONN(conn)->zlib_state,
+ string, len, done);
+ } else {
+ r = bufferevent_write(conn->bufev, string, len);
+ }
+ if (r < 0) {
+ /* XXXX mark for close? */
+ log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen.");
+ }
+ return;
+ });
+
old_datalen = buf_datalen(conn->outbuf);
if (zlib) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
@@ -2985,18 +3406,25 @@ _connection_write_to_buf_impl(const char *string, size_t len,
/* if it failed, it means we have our package/delivery windows set
wrong compared to our max outbuf size. close the whole circuit. */
log_warn(LD_NET,
- "write_to_buf failed. Closing circuit (fd %d).", conn->s);
+ "write_to_buf failed. Closing circuit (fd %d).", (int)conn->s);
circuit_mark_for_close(circuit_get_by_edge_conn(TO_EDGE_CONN(conn)),
END_CIRC_REASON_INTERNAL);
} else {
log_warn(LD_NET,
- "write_to_buf failed. Closing connection (fd %d).", conn->s);
+ "write_to_buf failed. Closing connection (fd %d).",
+ (int)conn->s);
connection_mark_for_close(conn);
}
return;
}
- connection_start_writing(conn);
+ /* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
+ * state, we don't want to try to write it right away, since
+ * conn->write_event won't be set yet. Otherwise, write data from
+ * this conn as the socket is available. */
+ if (conn->write_event) {
+ connection_start_writing(conn);
+ }
if (zlib) {
conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
} else {
@@ -3030,7 +3458,7 @@ _connection_write_to_buf_impl(const char *string, size_t len,
/* this connection is broken. remove it. */
log_warn(LD_BUG, "unhandled error on write for "
"conn (type %d, fd %d); removing",
- conn->type, conn->s);
+ conn->type, (int)conn->s);
tor_fragile_assert();
/* do a close-immediate here, so we don't try to flush */
connection_close_immediate(conn);
@@ -3142,6 +3570,32 @@ connection_get_by_type_state_rendquery(int type, int state,
return NULL;
}
+/** Return a directory connection (if any one exists) that is fetching
+ * the item described by <b>state</b>/<b>resource</b> */
+dir_connection_t *
+connection_dir_get_by_purpose_and_resource(int purpose,
+ const char *resource)
+{
+ smartlist_t *conns = get_connection_array();
+
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ dir_connection_t *dirconn;
+ if (conn->type != CONN_TYPE_DIR || conn->marked_for_close ||
+ conn->purpose != purpose)
+ continue;
+ dirconn = TO_DIR_CONN(conn);
+ if (dirconn->requested_resource == NULL) {
+ if (resource == NULL)
+ return dirconn;
+ } else if (resource) {
+ if (0 == strcmp(resource, dirconn->requested_resource))
+ return dirconn;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ return NULL;
+}
+
/** Return an open, non-marked connection of a given type and purpose, or NULL
* if no such connection exists. */
connection_t *
@@ -3253,7 +3707,7 @@ alloc_http_authenticator(const char *authenticator)
* call init_keys().
*/
static void
-client_check_address_changed(int sock)
+client_check_address_changed(tor_socket_t sock)
{
uint32_t iface_ip, ip_out; /* host order */
struct sockaddr_in out_addr;
@@ -3309,7 +3763,7 @@ client_check_address_changed(int sock)
* to the desired size to stay below system TCP buffer limits.
*/
static void
-set_constrained_socket_buffers(int sock, int size)
+set_constrained_socket_buffers(tor_socket_t sock, int size)
{
void *sz = (void*)&size;
socklen_t sz_sz = (socklen_t) sizeof(size);
@@ -3392,6 +3846,9 @@ connection_finished_flushing(connection_t *conn)
// log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s);
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_stop_writing(conn);
+
switch (conn->type) {
case CONN_TYPE_OR:
return connection_or_finished_flushing(TO_OR_CONN(conn));
@@ -3517,6 +3974,16 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn);
tor_assert(conn->type >= _CONN_TYPE_MIN);
tor_assert(conn->type <= _CONN_TYPE_MAX);
+
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ tor_assert(conn->read_event == NULL);
+ tor_assert(conn->write_event == NULL);
+ tor_assert(conn->inbuf == NULL);
+ tor_assert(conn->outbuf == NULL);
+ }
+#endif
+
switch (conn->type) {
case CONN_TYPE_OR:
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
@@ -3541,11 +4008,18 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn->linked);
}
if (conn->linked)
- tor_assert(conn->s < 0);
+ tor_assert(!SOCKET_OK(conn->s));
if (conn->outbuf_flushlen > 0) {
- tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw ||
- (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->edge_blocked_on_circ));
+ /* With optimistic data, we may have queued data in
+ * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
+ * */
+ tor_assert((conn->type == CONN_TYPE_EXIT &&
+ conn->state == EXIT_CONN_STATE_RESOLVING) ||
+ connection_is_writing(conn) ||
+ conn->write_blocked_on_bw ||
+ (CONN_IS_EDGE(conn) &&
+ TO_EDGE_CONN(conn)->edge_blocked_on_circ));
}
if (conn->hold_open_until_flushed)
@@ -3555,10 +4029,10 @@ assert_connection_ok(connection_t *conn, time_t now)
* marked_for_close. */
/* buffers */
- if (!connection_is_listener(conn)) {
+ if (conn->inbuf)
assert_buf_ok(conn->inbuf);
+ if (conn->outbuf)
assert_buf_ok(conn->outbuf);
- }
if (conn->type == CONN_TYPE_OR) {
or_connection_t *or_conn = TO_OR_CONN(conn);
diff --git a/src/or/connection.h b/src/or/connection.h
index 576d3a63e..8dc011209 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -12,6 +12,9 @@
#ifndef _TOR_CONNECTION_H
#define _TOR_CONNECTION_H
+/* XXXX For buf_datalen in inline function */
+#include "buffers.h"
+
const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state);
@@ -31,6 +34,21 @@ void _connection_mark_for_close(connection_t *conn,int line, const char *file);
#define connection_mark_for_close(c) \
_connection_mark_for_close((c), __LINE__, _SHORT_FILE_)
+/**
+ * Mark 'c' for close, but try to hold it open until all the data is written.
+ */
+#define _connection_mark_and_flush(c,line,file) \
+ do { \
+ connection_t *tmp_conn_ = (c); \
+ _connection_mark_for_close(tmp_conn_, (line), (file)); \
+ tmp_conn_->hold_open_until_flushed = 1; \
+ IF_HAS_BUFFEREVENT(tmp_conn_, \
+ connection_start_writing(tmp_conn_)); \
+ } while (0)
+
+#define connection_mark_and_flush(c) \
+ _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_)
+
void connection_expire_held_open(void);
int connection_connect(connection_t *conn, const char *address,
@@ -51,10 +69,18 @@ void connection_bucket_refill(int seconds_elapsed, time_t now);
int connection_handle_read(connection_t *conn);
int connection_fetch_from_buf(char *string, size_t len, connection_t *conn);
+int connection_fetch_from_buf_line(connection_t *conn, char *data,
+ size_t *data_len);
+int connection_fetch_from_buf_http(connection_t *conn,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used,
+ size_t max_bodylen, int force_complete);
int connection_wants_to_flush(connection_t *conn);
int connection_outbuf_too_full(connection_t *conn);
int connection_handle_write(connection_t *conn, int force);
+int connection_flush(connection_t *conn);
+
void _connection_write_to_buf_impl(const char *string, size_t len,
connection_t *conn, int zlib);
static void connection_write_to_buf(const char *string, size_t len,
@@ -73,6 +99,29 @@ connection_write_to_buf_zlib(const char *string, size_t len,
_connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1);
}
+static size_t connection_get_inbuf_len(connection_t *conn);
+static size_t connection_get_outbuf_len(connection_t *conn);
+
+static INLINE size_t
+connection_get_inbuf_len(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ return evbuffer_get_length(bufferevent_get_input(conn->bufev));
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return conn->inbuf ? buf_datalen(conn->inbuf) : 0;
+ }
+}
+
+static INLINE size_t
+connection_get_outbuf_len(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ return evbuffer_get_length(bufferevent_get_output(conn->bufev));
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return conn->outbuf ? buf_datalen(conn->outbuf) : 0;
+ }
+}
+
connection_t *connection_get_by_global_id(uint64_t id);
connection_t *connection_get_by_type(int type);
@@ -83,6 +132,8 @@ connection_t *connection_get_by_type_addr_port_purpose(int type,
connection_t *connection_get_by_type_state(int type, int state);
connection_t *connection_get_by_type_state_rendquery(int type, int state,
const char *rendquery);
+dir_connection_t *connection_dir_get_by_purpose_and_resource(
+ int state, const char *resource);
#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
int connection_is_listener(connection_t *conn);
@@ -96,5 +147,19 @@ int connection_or_nonopen_was_started_here(or_connection_t *conn);
void connection_dump_buffer_mem_stats(int severity);
void remove_file_if_very_old(const char *fname, time_t now);
+#ifdef USE_BUFFEREVENTS
+int connection_type_uses_bufferevent(connection_t *conn);
+void connection_configure_bufferevent_callbacks(connection_t *conn);
+void connection_handle_read_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_write_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg);
+void connection_get_rate_limit_totals(uint64_t *read_out,
+ uint64_t *written_out);
+void connection_enable_rate_limiting(connection_t *conn);
+#else
+#define connection_type_uses_bufferevent(c) (0)
+#endif
+
#endif
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 7828f1638..c49014848 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -23,6 +23,7 @@
#include "dirserv.h"
#include "hibernate.h"
#include "main.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -90,8 +91,8 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
conn->socks_request->has_finished = 1;
}
- _connection_mark_for_close(TO_CONN(conn), line, file);
- conn->_base.hold_open_until_flushed = 1;
+ _connection_mark_and_flush(TO_CONN(conn), line, file);
+
conn->end_reason = endreason;
}
@@ -100,7 +101,7 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
int
connection_edge_reached_eof(edge_connection_t *conn)
{
- if (buf_datalen(conn->_base.inbuf) &&
+ if (connection_get_inbuf_len(TO_CONN(conn)) &&
connection_state_is_open(TO_CONN(conn))) {
/* it still has stuff to process. don't let it die yet. */
return 0;
@@ -191,8 +192,7 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn)
conn->edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
}
conn->cpath_layer = NULL;
@@ -336,7 +336,6 @@ connection_edge_finished_flushing(edge_connection_t *conn)
switch (conn->_base.state) {
case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN:
- connection_stop_writing(TO_CONN(conn));
connection_edge_consider_sending_sendme(conn);
return 0;
case AP_CONN_STATE_SOCKS_WAIT:
@@ -345,7 +344,7 @@ connection_edge_finished_flushing(edge_connection_t *conn)
case AP_CONN_STATE_CIRCUIT_WAIT:
case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT:
- connection_stop_writing(TO_CONN(conn));
+ case AP_CONN_STATE_RESOLVE_WAIT:
return 0;
default:
log_warn(LD_BUG, "Called in unexpected state %d.",conn->_base.state);
@@ -375,8 +374,9 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
rep_hist_note_exit_stream_opened(conn->port);
conn->state = EXIT_CONN_STATE_OPEN;
- connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
- if (connection_wants_to_flush(conn)) /* in case there are any queued relay
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
+ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay
* cells */
connection_start_writing(conn);
/* deliver a 'connected' relay cell back through the circuit. */
@@ -439,7 +439,7 @@ connection_ap_expire_beginning(void)
edge_connection_t *conn;
circuit_t *circ;
time_t now = time(NULL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int severity;
int cutoff;
int seconds_idle, seconds_since_born;
@@ -503,12 +503,12 @@ connection_ap_expire_beginning(void)
}
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL);
log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP,
- "We tried for %d seconds to connect to '%s' using exit '%s'."
+ "We tried for %d seconds to connect to '%s' using exit %s."
" Retrying on a new circuit.",
seconds_idle,
safe_str_client(conn->socks_request->address),
conn->cpath_layer ?
- conn->cpath_layer->extend_info->nickname : "*unnamed*");
+ extend_info_describe(conn->cpath_layer->extend_info): "*unnamed*");
/* send an end down the circuit */
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
/* un-mark it as ending, since we're going to reuse it */
@@ -605,7 +605,7 @@ void
circuit_discard_optional_exit_enclaves(extend_info_t *info)
{
edge_connection_t *edge_conn;
- routerinfo_t *r1, *r2;
+ const node_t *r1, *r2;
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -617,8 +617,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
if (!edge_conn->chosen_exit_optional &&
!edge_conn->chosen_exit_retries)
continue;
- r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
- r2 = router_get_by_digest(info->identity_digest);
+ r1 = node_get_by_nickname(edge_conn->chosen_exit_name, 0);
+ r2 = node_get_by_id(info->identity_digest);
if (!r1 || !r2 || r1 != r2)
continue;
tor_assert(edge_conn->socks_request);
@@ -813,7 +813,7 @@ clear_trackexithost_mappings(const char *exitname)
* host is unknown or no longer allowed, or for which the source address
* is no longer in trackexithosts. */
void
-addressmap_clear_excluded_trackexithosts(or_options_t *options)
+addressmap_clear_excluded_trackexithosts(const or_options_t *options)
{
const routerset_t *allow_nodes = options->ExitNodes;
const routerset_t *exclude_nodes = options->_ExcludeExitNodesUnion;
@@ -829,7 +829,7 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
size_t len;
const char *target = ent->new_address, *dot;
char *nodename;
- routerinfo_t *ri; /* XXX023 Use node_t. */
+ const node_t *node;
if (strcmpend(target, ".exit")) {
/* Not a .exit mapping */
@@ -848,11 +848,11 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
} else {
nodename = tor_strndup(dot+1, strlen(dot+1)-5);
}
- ri = router_get_by_nickname(nodename, 0);
+ node = node_get_by_nickname(nodename, 0);
tor_free(nodename);
- if (!ri ||
- (allow_nodes && !routerset_contains_router(allow_nodes, ri)) ||
- routerset_contains_router(exclude_nodes, ri) ||
+ if (!node ||
+ (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||
+ routerset_contains_node(exclude_nodes, node) ||
!hostname_in_track_host_exits(options, address)) {
/* We don't know this one, or we want to be rid of it. */
addressmap_ent_remove(address, ent);
@@ -866,7 +866,7 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
* no longer allowed by AutomapHostsOnResolve, or for which the
* target address is no longer in the virtual network. */
void
-addressmap_clear_invalid_automaps(or_options_t *options)
+addressmap_clear_invalid_automaps(const or_options_t *options)
{
int clear_all = !options->AutomapHostsOnResolve;
const smartlist_t *suffixes = options->AutomapHostsSuffixes;
@@ -1313,7 +1313,6 @@ static char *
addressmap_get_virtual_address(int type)
{
char buf[64];
- struct in_addr in;
tor_assert(addressmap);
if (type == RESOLVED_TYPE_HOSTNAME) {
@@ -1327,6 +1326,7 @@ addressmap_get_virtual_address(int type)
} else if (type == RESOLVED_TYPE_IPV4) {
// This is an imperfect estimate of how many addresses are available, but
// that's ok.
+ struct in_addr in;
uint32_t available = 1u << (32-virtual_addr_netmask_bits);
while (available) {
/* Don't hand out any .0 or .255 address. */
@@ -1520,7 +1520,7 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
static int
consider_plaintext_ports(edge_connection_t *conn, uint16_t port)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int reject = smartlist_string_num_isin(options->RejectPlaintextPorts, port);
if (smartlist_string_num_isin(options->WarnPlaintextPorts, port)) {
@@ -1557,7 +1557,7 @@ connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->LeaveStreamsUnattached) {
conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
@@ -1588,7 +1588,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
{
socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
struct in_addr addr_tmp;
/* We set this to true if this is an address we should automatically
* remap to a local address in VirtualAddrNetwork */
@@ -1711,15 +1711,14 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* If StrictNodes is not set, then .exit overrides ExcludeNodes. */
routerset_t *excludeset = options->StrictNodes ?
options->_ExcludeExitNodesUnion : options->ExcludeExitNodes;
- /*XXX023 make this a node_t. */
- routerinfo_t *router;
+ const node_t *node;
tor_assert(!automap);
if (s) {
/* The address was of the form "(stuff).(name).exit */
if (s[1] != '\0') {
conn->chosen_exit_name = tor_strdup(s+1);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ node = node_get_by_nickname(conn->chosen_exit_name, 1);
if (remapped_to_exit) /* 5 tries before it expires the addressmap */
conn->chosen_exit_retries = TRACKHOSTEXITS_RETRIES;
*s = 0;
@@ -1734,15 +1733,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
}
} else {
/* It looks like they just asked for "foo.exit". */
+
conn->chosen_exit_name = tor_strdup(socks->address);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (router) {
+ node = node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (node) {
*socks->address = 0;
- strlcpy(socks->address, router->address, sizeof(socks->address));
+ node_get_address_string(node, socks->address, sizeof(socks->address));
}
}
/* Now make sure that the chosen exit exists... */
- if (!router) {
+ if (!node) {
log_warn(LD_APP,
"Unrecognized relay in exit address '%s.exit'. Refusing.",
safe_str_client(socks->address));
@@ -1750,7 +1750,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
/* ...and make sure that it isn't excluded. */
- if (routerset_contains_router(excludeset, router)) {
+ if (routerset_contains_node(excludeset, node)) {
log_warn(LD_APP,
"Excluded relay in exit address '%s.exit'. Refusing.",
safe_str_client(socks->address));
@@ -1825,16 +1825,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */
- routerinfo_t *r =
+ const node_t *r =
router_find_exact_exit_enclave(socks->address, socks->port);
if (r) {
log_info(LD_APP,
"Redirecting address %s to exit at enclave router %s",
- safe_str_client(socks->address), r->nickname);
+ safe_str_client(socks->address), node_describe(r));
/* use the hex digest, not nickname, in case there are two
routers with this nickname */
conn->chosen_exit_name =
- tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
+ tor_strdup(hex_str(r->identity, DIGEST_LEN));
conn->chosen_exit_optional = 1;
}
}
@@ -1949,10 +1949,10 @@ get_pf_socket(void)
#ifdef OPENBSD
/* only works on OpenBSD */
- pf = open("/dev/pf", O_RDONLY);
+ pf = tor_open_cloexec("/dev/pf", O_RDONLY, 0);
#else
/* works on NetBSD and FreeBSD */
- pf = open("/dev/pf", O_RDWR);
+ pf = tor_open_cloexec("/dev/pf", O_RDWR, 0);
#endif
if (pf < 0) {
@@ -2079,7 +2079,7 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
{
socks_request_t *socks;
int sockshere;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
tor_assert(conn->_base.type == CONN_TYPE_AP);
@@ -2089,8 +2089,14 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
log_debug(LD_APP,"entered.");
- sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks,
- options->TestSocks, options->SafeSocks);
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ struct evbuffer *input = bufferevent_get_input(conn->_base.bufev);
+ sockshere = fetch_from_evbuffer_socks(input, socks,
+ options->TestSocks, options->SafeSocks);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks,
+ options->TestSocks, options->SafeSocks);
+ };
if (sockshere == 0) {
if (socks->replylen) {
connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn));
@@ -2191,7 +2197,7 @@ connection_ap_process_natd(edge_connection_t *conn)
/* look for LF-terminated "[DEST ip_addr port]"
* where ip_addr is a dotted-quad and port is in string form */
- err = fetch_from_buf_line(conn->_base.inbuf, tmp_buf, &tlen);
+ err = connection_fetch_from_buf_line(TO_CONN(conn), tmp_buf, &tlen);
if (err == 0)
return 0;
if (err < 0) {
@@ -2304,8 +2310,10 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
ap_conn->socks_request->port);
payload_len = (int)strlen(payload)+1;
- log_debug(LD_APP,
- "Sending relay cell to begin stream %d.", ap_conn->stream_id);
+ log_info(LD_APP,
+ "Sending relay cell %d to begin stream %d.",
+ (int)ap_conn->use_begindir,
+ ap_conn->stream_id);
begin_type = ap_conn->use_begindir ?
RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN;
@@ -2418,9 +2426,11 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
* and call connection_ap_handshake_attach_circuit(conn) on it.
*
* Return the other end of the linked connection pair, or -1 if error.
+ * DOCDOC partner.
*/
edge_connection_t *
-connection_ap_make_link(char *address, uint16_t port,
+connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
const char *digest, int use_begindir, int want_onehop)
{
edge_connection_t *conn;
@@ -2455,6 +2465,8 @@ connection_ap_make_link(char *address, uint16_t port,
tor_addr_make_unspec(&conn->_base.addr);
conn->_base.port = 0;
+ connection_link_connections(partner, TO_CONN(conn));
+
if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */
connection_free(TO_CONN(conn));
return NULL;
@@ -2491,13 +2503,11 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
answer_type == RESOLVED_TYPE_HOSTNAME)) {
return; /* we already told the controller. */
} else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
- struct in_addr in;
- char buf[INET_NTOA_BUF_LEN];
- in.s_addr = get_uint32(answer);
- tor_inet_ntoa(&in, buf, sizeof(buf));
+ char *cp = tor_dup_ip(get_uint32(answer));
control_event_address_mapped(conn->socks_request->address,
- buf, expires, NULL);
- } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len <256) {
+ cp, expires, NULL);
+ tor_free(cp);
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
char *cp = tor_strndup(answer, answer_len);
control_event_address_mapped(conn->socks_request->address,
cp, expires, NULL);
@@ -2610,7 +2620,8 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
}
connection_ap_handshake_socks_reply(conn, buf, replylen,
(answer_type == RESOLVED_TYPE_IPV4 ||
- answer_type == RESOLVED_TYPE_IPV6) ?
+ answer_type == RESOLVED_TYPE_IPV6 ||
+ answer_type == RESOLVED_TYPE_HOSTNAME) ?
0 : END_STREAM_REASON_RESOLVEFAILED);
}
@@ -2693,7 +2704,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
char *address=NULL;
uint16_t port;
or_circuit_t *or_circ = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
assert_circuit_ok(circ);
if (!CIRCUIT_IS_ORIGIN(circ))
@@ -2976,12 +2987,13 @@ connection_exit_connect(edge_connection_t *edge_conn)
}
conn->state = EXIT_CONN_STATE_OPEN;
- if (connection_wants_to_flush(conn)) {
+ if (connection_get_outbuf_len(conn)) {
/* in case there are any queued data cells */
log_warn(LD_BUG,"newly connected conn had data waiting!");
// connection_start_writing(conn);
}
- connection_watch_events(conn, READ_EVENT);
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_watch_events(conn, READ_EVENT);
/* also, deliver a 'connected' cell back through the circuit. */
if (connection_edge_is_rendezvous_stream(edge_conn)) {
@@ -3091,9 +3103,9 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
* resolved.)
*/
int
-connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
+connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
tor_assert(conn->_base.type == CONN_TYPE_AP);
@@ -3104,10 +3116,10 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
* make sure the exit node of the existing circuit matches exactly.
*/
if (conn->chosen_exit_name) {
- routerinfo_t *chosen_exit =
- router_get_by_nickname(conn->chosen_exit_name, 1);
- if (!chosen_exit || tor_memneq(chosen_exit->cache_info.identity_digest,
- exit->cache_info.identity_digest, DIGEST_LEN)) {
+ const node_t *chosen_exit =
+ node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (!chosen_exit || tor_memneq(chosen_exit->identity,
+ exit->identity, DIGEST_LEN)) {
/* doesn't match */
// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
// conn->chosen_exit_name, exit->nickname);
@@ -3122,8 +3134,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
addr_policy_result_t r;
if (tor_inet_aton(conn->socks_request->address, &in))
addr = ntohl(in.s_addr);
- r = compare_addr_to_addr_policy(addr, conn->socks_request->port,
- exit->exit_policy);
+ r = compare_addr_to_node_policy(addr, conn->socks_request->port, exit);
if (r == ADDR_POLICY_REJECTED)
return 0; /* We know the address, and the exit policy rejects it. */
if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
@@ -3131,17 +3142,12 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
* addresses with this port. Since the user didn't ask for
* this node, err on the side of caution. */
} else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
- /* Can't support reverse lookups without eventdns. */
- if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR &&
- exit->has_old_dnsworkers)
- return 0;
-
/* Don't send DNS requests to non-exit servers by default. */
- if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy))
+ if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit))
return 0;
}
if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) {
+ routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) {
/* Not a suitable exit. Refuse it. */
return 0;
}
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 8ba2fafd0..a7fc12e23 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -30,7 +30,8 @@ int connection_edge_finished_connecting(edge_connection_t *conn);
int connection_ap_handshake_send_begin(edge_connection_t *ap_conn);
int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn);
-edge_connection_t *connection_ap_make_link(char *address, uint16_t port,
+edge_connection_t *connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
const char *digest,
int use_begindir, int want_onehop);
void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
@@ -47,7 +48,8 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
void connection_exit_connect(edge_connection_t *conn);
int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
-int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit);
+int connection_ap_can_use_exit(edge_connection_t *conn,
+ const node_t *exit);
void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
void connection_ap_fail_onehop(const char *failed_digest,
@@ -61,8 +63,8 @@ int connection_ap_process_transparent(edge_connection_t *conn);
int address_is_invalid_destination(const char *address, int client);
void addressmap_init(void);
-void addressmap_clear_excluded_trackexithosts(or_options_t *options);
-void addressmap_clear_invalid_automaps(or_options_t *options);
+void addressmap_clear_excluded_trackexithosts(const or_options_t *options);
+void addressmap_clear_invalid_automaps(const or_options_t *options);
void addressmap_clean(time_t now);
void addressmap_clear_configured(void);
void addressmap_clear_transient(void);
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index ed174c922..679500dee 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -22,12 +22,17 @@
#include "geoip.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "reasons.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#endif
+
static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
static int connection_or_send_versions(or_connection_t *conn);
@@ -37,6 +42,14 @@ static int connection_or_check_valid_tls_handshake(or_connection_t *conn,
int started_here,
char *digest_rcvd_out);
+static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn);
+
+#ifdef USE_BUFFEREVENTS
+static void connection_or_handle_event_cb(struct bufferevent *bufev,
+ short event, void *arg);
+#include <event2/buffer.h>/*XXXX REMOVE */
+#endif
+
/**************************************************************/
/** Map from identity digest of connected OR or desired OR to a connection_t
@@ -178,7 +191,8 @@ var_cell_pack_header(const var_cell_t *cell, char *hdr_out)
var_cell_t *
var_cell_new(uint16_t payload_len)
{
- var_cell_t *cell = tor_malloc(sizeof(var_cell_t)+payload_len-1);
+ size_t size = STRUCT_OFFSET(var_cell_t, payload) + payload_len;
+ var_cell_t *cell = tor_malloc(size);
cell->payload_len = payload_len;
cell->command = 0;
cell->circ_id = 0;
@@ -227,6 +241,14 @@ connection_or_process_inbuf(or_connection_t *conn)
}
return ret;
+#ifdef USE_BUFFEREVENTS
+ case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
+ if (tor_tls_server_got_renegotiate(conn->tls))
+ connection_or_tls_renegotiated_cb(conn->tls, conn);
+ if (conn->_base.marked_for_close)
+ return 0;
+ /* fall through. */
+#endif
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING:
return connection_or_process_cells_from_inbuf(conn);
@@ -248,7 +270,7 @@ connection_or_process_inbuf(or_connection_t *conn)
int
connection_or_flushed_some(or_connection_t *conn)
{
- size_t datalen = buf_datalen(conn->_base.outbuf);
+ size_t datalen = connection_get_outbuf_len(TO_CONN(conn));
/* If we're under the low water mark, add cells until we're just over the
* high water mark. */
if (datalen < OR_CONN_LOWWATER) {
@@ -281,7 +303,6 @@ connection_or_finished_flushing(or_connection_t *conn)
case OR_CONN_STATE_PROXY_HANDSHAKING:
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING:
- connection_stop_writing(TO_CONN(conn));
break;
default:
log_err(LD_BUG,"Called in unexpected state %d.", conn->_base.state);
@@ -342,7 +363,7 @@ connection_or_digest_is_known_relay(const char *id_digest)
{
if (router_get_consensus_status_by_id(id_digest))
return 1; /* It's in the consensus: "yes" */
- if (router_get_by_digest(id_digest))
+ if (router_get_by_id_digest(id_digest))
return 1; /* Not in the consensus, but we have a descriptor for
* it. Probably it was in a recent consensus. "Yes". */
return 0;
@@ -359,7 +380,7 @@ connection_or_digest_is_known_relay(const char *id_digest)
*/
static void
connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
- or_options_t *options)
+ const or_options_t *options)
{
int rate, burst; /* per-connection rate limiting params */
if (connection_or_digest_is_known_relay(conn->identity_digest)) {
@@ -382,6 +403,22 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
conn->bandwidthrate = rate;
conn->bandwidthburst = burst;
+#ifdef USE_BUFFEREVENTS
+ {
+ const struct timeval *tick = tor_libevent_get_one_tick_timeout();
+ struct ev_token_bucket_cfg *cfg, *old_cfg;
+ int rate_per_tick = rate / TOR_LIBEVENT_TICKS_PER_SECOND;
+ cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick,
+ burst, tick);
+ old_cfg = conn->bucket_cfg;
+ if (conn->_base.bufev)
+ bufferevent_set_rate_limit(conn->_base.bufev, cfg);
+ if (old_cfg)
+ ev_token_bucket_cfg_free(old_cfg);
+ conn->bucket_cfg = cfg;
+ (void) reset; /* No way to do this with libevent yet. */
+ }
+#else
if (reset) { /* set up the token buckets to be full */
conn->read_bucket = conn->write_bucket = burst;
return;
@@ -392,13 +429,15 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
conn->read_bucket = burst;
if (conn->write_bucket > burst)
conn->write_bucket = burst;
+#endif
}
/** Either our set of relays or our per-conn rate limits have changed.
* Go through all the OR connections and update their token buckets to make
* sure they don't exceed their maximum values. */
void
-connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options)
+connection_or_update_token_buckets(smartlist_t *conns,
+ const or_options_t *options)
{
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
@@ -416,7 +455,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
const char *id_digest,
int started_here)
{
- routerinfo_t *r = router_get_by_digest(id_digest);
+ const node_t *r = node_get_by_id(id_digest);
connection_or_set_identity_digest(conn, id_digest);
connection_or_update_token_buckets_helper(conn, 1, get_options());
@@ -424,8 +463,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
tor_addr_copy(&conn->_base.addr, addr);
tor_addr_copy(&conn->real_addr, addr);
if (r) {
+ tor_addr_t node_addr;
+ node_get_addr(r, &node_addr);
/* XXXX proposal 118 will make this more complex. */
- if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr))
+ if (tor_addr_eq(&conn->_base.addr, &node_addr))
conn->is_canonical = 1;
if (!started_here) {
/* Override the addr/port, so our log messages will make sense.
@@ -438,12 +479,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
* right IP address and port 56244, that wouldn't be as helpful. now we
* log the "right" port too, so we know if it's moria1 or moria2.
*/
- tor_addr_from_ipv4h(&conn->_base.addr, r->addr);
- conn->_base.port = r->or_port;
+ tor_addr_copy(&conn->_base.addr, &node_addr);
+ conn->_base.port = node_get_orport(r);
}
- conn->nickname = tor_strdup(r->nickname);
+ conn->nickname = tor_strdup(node_get_nickname(r));
tor_free(conn->_base.address);
- conn->_base.address = tor_strdup(r->address);
+ conn->_base.address = tor_dup_addr(&node_addr);
} else {
const char *n;
/* If we're an authoritative directory server, we may know a
@@ -787,7 +828,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
const char *id_digest)
{
or_connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int socket_error = 0;
int using_proxy = 0;
tor_addr_t addr;
@@ -863,6 +904,7 @@ int
connection_tls_start_handshake(or_connection_t *conn, int receiving)
{
conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING;
+ tor_assert(!conn->tls);
conn->tls = tor_tls_new(conn->_base.s, receiving);
tor_tls_set_logged_address(conn->tls, // XXX client and relay?
escaped_safe_str(conn->_base.address));
@@ -870,12 +912,38 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(TO_CONN(conn))) {
+ const int filtering = get_options()->_UseFilteringSSLBufferevents;
+ struct bufferevent *b =
+ tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s,
+ receiving, filtering);
+ if (!b) {
+ log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing.");
+ return -1;
+ }
+ conn->_base.bufev = b;
+ if (conn->bucket_cfg)
+ bufferevent_set_rate_limit(conn->_base.bufev, conn->bucket_cfg);
+ connection_enable_rate_limiting(TO_CONN(conn));
+
+ connection_configure_bufferevent_callbacks(TO_CONN(conn));
+ bufferevent_setcb(b,
+ connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_or_handle_event_cb,/* overriding this one*/
+ TO_CONN(conn));
+ }
+#endif
connection_start_reading(TO_CONN(conn));
log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s);
note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C);
- if (connection_tls_continue_handshake(conn) < 0) {
- return -1;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ /* ???? */;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ if (connection_tls_continue_handshake(conn) < 0)
+ return -1;
}
return 0;
}
@@ -929,13 +997,16 @@ connection_tls_continue_handshake(or_connection_t *conn)
if (! tor_tls_used_v1_handshake(conn->tls)) {
if (!tor_tls_is_server(conn->tls)) {
if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
- // log_notice(LD_OR,"Done. state was TLS_HANDSHAKING.");
+ log_debug(LD_OR, "Done with initial SSL handshake (client-side). "
+ "Requesting renegotiation.");
conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
goto again;
}
// log_notice(LD_OR,"Done. state was %d.", conn->_base.state);
} else {
/* improved handshake, but not a client. */
+ log_debug(LD_OR, "Done with initial SSL handshake (server-side). "
+ "Expecting renegotiation.");
tor_tls_set_renegotiate_callback(conn->tls,
connection_or_tls_renegotiated_cb,
conn);
@@ -960,6 +1031,78 @@ connection_tls_continue_handshake(or_connection_t *conn)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+static void
+connection_or_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg)
+{
+ struct or_connection_t *conn = TO_OR_CONN(arg);
+
+ /* XXXX cut-and-paste code; should become a function. */
+ if (event & BEV_EVENT_CONNECTED) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ if (tor_tls_finish_handshake(conn->tls) < 0) {
+ log_warn(LD_OR, "Problem finishing handshake");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+
+ if (! tor_tls_used_v1_handshake(conn->tls)) {
+ if (!tor_tls_is_server(conn->tls)) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
+ tor_tls_unblock_renegotiation(conn->tls);
+ if (bufferevent_ssl_renegotiate(conn->_base.bufev)<0) {
+ log_warn(LD_OR, "Start_renegotiating went badly.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ tor_tls_unblock_renegotiation(conn->tls);
+ return; /* ???? */
+ }
+ } else if (tor_tls_get_num_server_handshakes(conn->tls) == 1) {
+ /* improved handshake, as a server. Only got one handshake, so
+ * wait for the next one. */
+ tor_tls_set_renegotiate_callback(conn->tls,
+ connection_or_tls_renegotiated_cb,
+ conn);
+ conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
+ /* return 0; */
+ return; /* ???? */
+ } else {
+ const int handshakes = tor_tls_get_num_server_handshakes(conn->tls);
+ tor_assert(handshakes >= 2);
+ if (handshakes == 2) {
+ /* improved handshake, as a server. Two handshakes happened already,
+ * so we treat renegotiation as done.
+ */
+ connection_or_tls_renegotiated_cb(conn->tls, conn);
+ } else {
+ log_warn(LD_OR, "More than two handshakes done on connection. "
+ "Closing.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ return;
+ }
+ }
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ if (connection_tls_finish_handshake(conn) < 0)
+ connection_mark_for_close(TO_CONN(conn)); /* ???? */
+ return;
+ }
+
+ if (event & BEV_EVENT_ERROR) {
+ unsigned long err;
+ while ((err = bufferevent_get_openssl_error(bufev))) {
+ tor_tls_log_one_error(conn->tls, err, LOG_WARN, LD_OR,
+ "handshaking (with bufferevent)");
+ }
+ }
+
+ connection_handle_event_cb(bufev, event, arg);
+}
+#endif
+
/** Return 1 if we initiated this connection, or 0 if it started
* out as an incoming connection.
*/
@@ -1005,7 +1148,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
char *digest_rcvd_out)
{
crypto_pk_env_t *identity_rcvd=NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
const char *safe_address =
started_here ? conn->_base.address :
@@ -1128,7 +1271,9 @@ connection_tls_finish_handshake(or_connection_t *conn)
char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn);
- log_debug(LD_HANDSHAKE,"tls handshake with %s done. verifying.",
+ log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done. verifying.",
+ started_here?"outgoing":"incoming",
+ conn,
safe_str_client(conn->_base.address));
directory_set_dirty();
@@ -1209,7 +1354,7 @@ connection_or_set_state_open(or_connection_t *conn)
router_set_status(conn->identity_digest, 1);
} else {
/* only report it to the geoip module if it's not a known router */
- if (!router_get_by_digest(conn->identity_digest)) {
+ if (!router_get_by_id_digest(conn->identity_digest)) {
if (tor_addr_family(&TO_CONN(conn)->addr) == AF_INET) {
/*XXXX IP6 support ipv6 geoip.*/
uint32_t a = tor_addr_to_ipv4h(&TO_CONN(conn)->addr);
@@ -1220,8 +1365,12 @@ connection_or_set_state_open(or_connection_t *conn)
or_handshake_state_free(conn->handshake_state);
conn->handshake_state = NULL;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ connection_start_reading(TO_CONN(conn));
+ }
- connection_start_reading(TO_CONN(conn));
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
return 0;
@@ -1266,12 +1415,18 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell,
conn->timestamp_last_added_nonpadding = approx_time();
}
-/** See whether there's a variable-length cell waiting on <b>conn</b>'s
+/** See whether there's a variable-length cell waiting on <b>or_conn</b>'s
* inbuf. Return values as for fetch_var_cell_from_buf(). */
static int
-connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out)
+connection_fetch_var_cell_from_buf(or_connection_t *or_conn, var_cell_t **out)
{
- return fetch_var_cell_from_buf(conn->_base.inbuf, out, conn->link_proto);
+ connection_t *conn = TO_CONN(or_conn);
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_var_cell_from_evbuffer(input, out, or_conn->link_proto);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_var_cell_from_buf(conn->inbuf, out, or_conn->link_proto);
+ }
}
/** Process cells from <b>conn</b>'s inbuf.
@@ -1289,7 +1444,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
while (1) {
log_debug(LD_OR,
"%d: starting, inbuf_datalen %d (%d pending in tls object).",
- conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
+ conn->_base.s,(int)connection_get_inbuf_len(TO_CONN(conn)),
tor_tls_get_pending_bytes(conn->tls));
if (connection_fetch_var_cell_from_buf(conn, &var_cell)) {
if (!var_cell)
@@ -1300,8 +1455,8 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
} else {
char buf[CELL_NETWORK_SIZE];
cell_t cell;
- if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response
- available? */
+ if (connection_get_inbuf_len(TO_CONN(conn))
+ < CELL_NETWORK_SIZE) /* whole response available? */
return 0; /* not yet */
circuit_build_times_network_is_live(&circ_times);
@@ -1388,7 +1543,7 @@ connection_or_send_netinfo(or_connection_t *conn)
{
cell_t cell;
time_t now = time(NULL);
- routerinfo_t *me;
+ const routerinfo_t *me;
int len;
uint8_t *out;
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 70ef96a33..4a374cac0 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -27,7 +27,7 @@ int connection_or_finished_flushing(or_connection_t *conn);
int connection_or_finished_connecting(or_connection_t *conn);
int connection_or_digest_is_known_relay(const char *id_digest);
void connection_or_update_token_buckets(smartlist_t *conns,
- or_options_t *options);
+ const or_options_t *options);
void connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg);
diff --git a/src/or/control.c b/src/or/control.c
index 384e579f9..6ea9dbe47 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -26,12 +26,20 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#ifndef MS_WINDOWS
+#include <pwd.h>
+#include <sys/resource.h>
+#endif
+
+#include "procmon.h"
+
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
* finished authentication and is accepting commands. */
#define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN)
@@ -64,7 +72,8 @@
#define EVENT_CLIENTS_SEEN 0x0015
#define EVENT_NEWCONSENSUS 0x0016
#define EVENT_BUILDTIMEOUT_SET 0x0017
-#define _EVENT_MAX 0x0017
+#define EVENT_SIGNAL 0x0018
+#define _EVENT_MAX 0x0018
/* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */
/** Bitfield: The bit 1&lt;&lt;e is set if <b>any</b> open control
@@ -96,7 +105,7 @@ static int disable_log_messages = 0;
static int authentication_cookie_is_set = 0;
/** If authentication_cookie_is_set, a secret cookie that we've stored to disk
* and which we're using to authenticate controllers. (If the controller can
- * read it off disk, it has permission to connect. */
+ * read it off disk, it has permission to connect.) */
static char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
/** A sufficiently large size to record the last bootstrap phase string. */
@@ -479,33 +488,26 @@ decode_escaped_string(const char *start, size_t in_len_max,
}
/** Acts like sprintf, but writes its formatted string to the end of
- * <b>conn</b>-\>outbuf. The message may be truncated if it is too long,
- * but it will always end with a CRLF sequence.
- *
- * Currently the length of the message is limited to 1024 (including the
- * ending CR LF NUL ("\\r\\n\\0"). */
+ * <b>conn</b>-\>outbuf. */
static void
connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
{
-#define CONNECTION_PRINTF_TO_BUF_BUFFERSIZE 1024
va_list ap;
- char buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE];
- int r;
- size_t len;
+ char *buf = NULL;
+ int len;
+
va_start(ap,format);
- r = tor_vsnprintf(buf, sizeof(buf), format, ap);
+ len = tor_vasprintf(&buf, format, ap);
va_end(ap);
- if (r<0) {
+
+ if (len < 0) {
log_warn(LD_BUG, "Unable to format string for controller.");
return;
}
- len = strlen(buf);
- if (fast_memcmp("\r\n\0", buf+len-2, 3)) {
- buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-1] = '\0';
- buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n';
- buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r';
- }
- connection_write_to_buf(buf, len, TO_CONN(conn));
+
+ connection_write_to_buf(buf, (size_t)len, TO_CONN(conn));
+
+ tor_free(buf);
}
/** Write all of the open control ports to ControlPortWriteToFile */
@@ -514,7 +516,7 @@ control_ports_write_to_file(void)
{
smartlist_t *lines;
char *joined = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!options->ControlPortWriteToFile)
return;
@@ -598,52 +600,37 @@ send_control_event_string(uint16_t event, event_format_t which,
else if (event == EVENT_STATUS_SERVER)
is_err = !strcmpstart(msg, "STATUS_SERVER ERR ");
if (is_err)
- connection_handle_write(TO_CONN(control_conn), 1);
+ connection_flush(TO_CONN(control_conn));
}
}
} SMARTLIST_FOREACH_END(conn);
}
-/** Helper for send_control1_event and send_control1_event_extended:
+/** Helper for send_control_event and control_event_status:
* Send an event to all v1 controllers that are listening for code
* <b>event</b>. The event's body is created by the printf-style format in
- * <b>format</b>, and other arguments as provided.
- *
- * Currently the length of the message is limited to 1024 (including the
- * ending \\r\\n\\0). */
+ * <b>format</b>, and other arguments as provided. */
static void
send_control_event_impl(uint16_t event, event_format_t which,
const char *format, va_list ap)
{
- /* This is just a little longer than the longest allowed log message */
-#define SEND_CONTROL1_EVENT_BUFFERSIZE 10064
- int r;
- char buf[SEND_CONTROL1_EVENT_BUFFERSIZE];
- size_t len;
+ char *buf = NULL;
+ int len;
- r = tor_vsnprintf(buf, sizeof(buf), format, ap);
- if (r<0) {
+ len = tor_vasprintf(&buf, format, ap);
+ if (len < 0) {
log_warn(LD_BUG, "Unable to format event for controller.");
return;
}
- len = strlen(buf);
- if (fast_memcmp("\r\n\0", buf+len-2, 3)) {
- /* if it is not properly terminated, do it now */
- buf[SEND_CONTROL1_EVENT_BUFFERSIZE-1] = '\0';
- buf[SEND_CONTROL1_EVENT_BUFFERSIZE-2] = '\n';
- buf[SEND_CONTROL1_EVENT_BUFFERSIZE-3] = '\r';
- }
-
send_control_event_string(event, which|ALL_FORMATS, buf);
+
+ tor_free(buf);
}
/** Send an event to all v1 controllers that are listening for code
* <b>event</b>. The event's body is created by the printf-style format in
- * <b>format</b>, and other arguments as provided.
- *
- * Currently the length of the message is limited to 1024 (including the
- * ending \\n\\r\\0. */
+ * <b>format</b>, and other arguments as provided. */
static void
send_control_event(uint16_t event, event_format_t which,
const char *format, ...)
@@ -818,7 +805,7 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
smartlist_t *unrecognized = smartlist_create();
char *msg = NULL;
size_t msg_len;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int i, len;
(void) body_len; /* body is NUL-terminated; so we can ignore len. */
@@ -930,13 +917,44 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len,
return 0;
}
+struct control_event_t {
+ uint16_t event_code;
+ const char *event_name;
+};
+static const struct control_event_t control_event_table[] = {
+ { EVENT_CIRCUIT_STATUS, "CIRC" },
+ { EVENT_STREAM_STATUS, "STREAM" },
+ { EVENT_OR_CONN_STATUS, "ORCONN" },
+ { EVENT_BANDWIDTH_USED, "BW" },
+ { EVENT_DEBUG_MSG, "DEBUG" },
+ { EVENT_INFO_MSG, "INFO" },
+ { EVENT_NOTICE_MSG, "NOTICE" },
+ { EVENT_WARN_MSG, "WARN" },
+ { EVENT_ERR_MSG, "ERR" },
+ { EVENT_NEW_DESC, "NEWDESC" },
+ { EVENT_ADDRMAP, "ADDRMAP" },
+ { EVENT_AUTHDIR_NEWDESCS, "AUTHDIR_NEWDESCS" },
+ { EVENT_DESCCHANGED, "DESCCHANGED" },
+ { EVENT_NS, "NS" },
+ { EVENT_STATUS_GENERAL, "STATUS_GENERAL" },
+ { EVENT_STATUS_CLIENT, "STATUS_CLIENT" },
+ { EVENT_STATUS_SERVER, "STATUS_SERVER" },
+ { EVENT_GUARD, "GUARD" },
+ { EVENT_STREAM_BANDWIDTH_USED, "STREAM_BW" },
+ { EVENT_CLIENTS_SEEN, "CLIENTS_SEEN" },
+ { EVENT_NEWCONSENSUS, "NEWCONSENSUS" },
+ { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" },
+ { EVENT_SIGNAL, "SIGNAL" },
+ { 0, NULL },
+};
+
/** Called when we get a SETEVENTS message: update conn->event_mask,
* and reply with DONE or ERROR. */
static int
handle_control_setevents(control_connection_t *conn, uint32_t len,
const char *body)
{
- uint16_t event_code;
+ int event_code = -1;
uint32_t event_mask = 0;
smartlist_t *events = smartlist_create();
@@ -948,56 +966,22 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
{
if (!strcasecmp(ev, "EXTENDED")) {
continue;
- } else if (!strcasecmp(ev, "CIRC"))
- event_code = EVENT_CIRCUIT_STATUS;
- else if (!strcasecmp(ev, "STREAM"))
- event_code = EVENT_STREAM_STATUS;
- else if (!strcasecmp(ev, "ORCONN"))
- event_code = EVENT_OR_CONN_STATUS;
- else if (!strcasecmp(ev, "BW"))
- event_code = EVENT_BANDWIDTH_USED;
- else if (!strcasecmp(ev, "DEBUG"))
- event_code = EVENT_DEBUG_MSG;
- else if (!strcasecmp(ev, "INFO"))
- event_code = EVENT_INFO_MSG;
- else if (!strcasecmp(ev, "NOTICE"))
- event_code = EVENT_NOTICE_MSG;
- else if (!strcasecmp(ev, "WARN"))
- event_code = EVENT_WARN_MSG;
- else if (!strcasecmp(ev, "ERR"))
- event_code = EVENT_ERR_MSG;
- else if (!strcasecmp(ev, "NEWDESC"))
- event_code = EVENT_NEW_DESC;
- else if (!strcasecmp(ev, "ADDRMAP"))
- event_code = EVENT_ADDRMAP;
- else if (!strcasecmp(ev, "AUTHDIR_NEWDESCS"))
- event_code = EVENT_AUTHDIR_NEWDESCS;
- else if (!strcasecmp(ev, "DESCCHANGED"))
- event_code = EVENT_DESCCHANGED;
- else if (!strcasecmp(ev, "NS"))
- event_code = EVENT_NS;
- else if (!strcasecmp(ev, "STATUS_GENERAL"))
- event_code = EVENT_STATUS_GENERAL;
- else if (!strcasecmp(ev, "STATUS_CLIENT"))
- event_code = EVENT_STATUS_CLIENT;
- else if (!strcasecmp(ev, "STATUS_SERVER"))
- event_code = EVENT_STATUS_SERVER;
- else if (!strcasecmp(ev, "GUARD"))
- event_code = EVENT_GUARD;
- else if (!strcasecmp(ev, "STREAM_BW"))
- event_code = EVENT_STREAM_BANDWIDTH_USED;
- else if (!strcasecmp(ev, "CLIENTS_SEEN"))
- event_code = EVENT_CLIENTS_SEEN;
- else if (!strcasecmp(ev, "NEWCONSENSUS"))
- event_code = EVENT_NEWCONSENSUS;
- else if (!strcasecmp(ev, "BUILDTIMEOUT_SET"))
- event_code = EVENT_BUILDTIMEOUT_SET;
- else {
- connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
- ev);
- SMARTLIST_FOREACH(events, char *, e, tor_free(e));
- smartlist_free(events);
- return 0;
+ } else {
+ int i;
+ for (i = 0; control_event_table[i].event_name != NULL; ++i) {
+ if (!strcasecmp(ev, control_event_table[i].event_name)) {
+ event_code = control_event_table[i].event_code;
+ break;
+ }
+ }
+
+ if (event_code == -1) {
+ connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
+ ev);
+ SMARTLIST_FOREACH(events, char *, e, tor_free(e));
+ smartlist_free(events);
+ return 0;
+ }
}
event_mask |= (1 << event_code);
}
@@ -1059,7 +1043,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
const char *body)
{
int used_quoted_string = 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const char *errstr = NULL;
char *password;
size_t password_len;
@@ -1268,13 +1252,33 @@ handle_control_signal(control_connection_t *conn, uint32_t len,
send_control_done(conn);
/* Flush the "done" first if the signal might make us shut down. */
if (sig == SIGTERM || sig == SIGINT)
- connection_handle_write(TO_CONN(conn), 1);
+ connection_flush(TO_CONN(conn));
process_signal(sig);
return 0;
}
+/** Called when we get a TAKEOWNERSHIP command. Mark this connection
+ * as an owning connection, so that we will exit if the connection
+ * closes. */
+static int
+handle_control_takeownership(control_connection_t *conn, uint32_t len,
+ const char *body)
+{
+ (void)len;
+ (void)body;
+
+ conn->is_owning_control_connection = 1;
+
+ log_info(LD_CONTROL, "Control connection %d has taken ownership of this "
+ "Tor instance.",
+ (int)(conn->_base.s));
+
+ send_control_done(conn);
+ return 0;
+}
+
/** Called when we get a MAPADDRESS command; try to bind all listed addresses,
* and report success or failure. */
static int
@@ -1377,10 +1381,16 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
} else if (!strcmp(question, "info/names")) {
*answer = list_getinfo_options();
} else if (!strcmp(question, "events/names")) {
- *answer = tor_strdup("CIRC STREAM ORCONN BW DEBUG INFO NOTICE WARN ERR "
- "NEWDESC ADDRMAP AUTHDIR_NEWDESCS DESCCHANGED "
- "NS STATUS_GENERAL STATUS_CLIENT STATUS_SERVER "
- "GUARD STREAM_BW CLIENTS_SEEN NEWCONSENSUS");
+ int i;
+ smartlist_t *event_names = smartlist_create();
+
+ for (i = 0; control_event_table[i].event_name != NULL; ++i) {
+ smartlist_add(event_names, (char *)control_event_table[i].event_name);
+ }
+
+ *answer = smartlist_join_strings(event_names, " ", 0, NULL);
+
+ smartlist_free(event_names);
} else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
} else if (!strcmp(question, "address")) {
@@ -1390,10 +1400,65 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
return -1;
}
*answer = tor_dup_ip(addr);
+ } else if (!strcmp(question, "traffic/read")) {
+ tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_read()));
+ } else if (!strcmp(question, "traffic/written")) {
+ tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_written()));
+ } else if (!strcmp(question, "process/pid")) {
+ int myPid = -1;
+
+ #ifdef MS_WINDOWS
+ myPid = _getpid();
+ #else
+ myPid = getpid();
+ #endif
+
+ tor_asprintf(answer, "%d", myPid);
+ } else if (!strcmp(question, "process/uid")) {
+ #ifdef MS_WINDOWS
+ *answer = tor_strdup("-1");
+ #else
+ int myUid = geteuid();
+ tor_asprintf(answer, "%d", myUid);
+ #endif
+ } else if (!strcmp(question, "process/user")) {
+ #ifdef MS_WINDOWS
+ *answer = tor_strdup("");
+ #else
+ int myUid = geteuid();
+ struct passwd *myPwEntry = getpwuid(myUid);
+
+ if (myPwEntry) {
+ *answer = tor_strdup(myPwEntry->pw_name);
+ } else {
+ *answer = tor_strdup("");
+ }
+ #endif
+ } else if (!strcmp(question, "process/descriptor-limit")) {
+ /** platform specifc limits are from the set_max_file_descriptors function
+ * of src/common/compat.c */
+ /* XXXX023 This is duplicated code from compat.c; it should turn into a
+ * function. */
+ #ifdef HAVE_GETRLIMIT
+ struct rlimit descriptorLimit;
+
+ if (getrlimit(RLIMIT_NOFILE, &descriptorLimit) == 0) {
+ tor_asprintf(answer, U64_FORMAT,
+ U64_PRINTF_ARG(descriptorLimit.rlim_max));
+ } else {
+ *answer = tor_strdup("-1");
+ }
+ #elif defined(CYGWIN) || defined(__CYGWIN__)
+ *answer = tor_strdup("3200");
+ #elif defined(MS_WINDOWS)
+ *answer = tor_strdup("15000");
+ #else
+ *answer = tor_strdup("15000");
+ #endif
} else if (!strcmp(question, "dir-usage")) {
*answer = directory_dump_request_log();
} else if (!strcmp(question, "fingerprint")) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me) {
*errmsg = "No routerdesc known; am I really a server?";
return -1;
@@ -1415,8 +1480,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
* NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
* not be NUL-terminated. */
static char *
-munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri,
- signed_descriptor_t *ei)
+munge_extrainfo_into_routerinfo(const char *ri_body,
+ const signed_descriptor_t *ri,
+ const signed_descriptor_t *ei)
{
char *out = NULL, *outp;
int i;
@@ -1490,7 +1556,7 @@ getinfo_helper_listeners(control_connection_t *control_conn,
struct sockaddr_storage ss;
socklen_t ss_len = sizeof(ss);
- if (conn->type != type || conn->marked_for_close || conn->s < 0)
+ if (conn->type != type || conn->marked_for_close || !SOCKET_OK(conn->s))
continue;
if (getsockname(conn->s, (struct sockaddr *)&ss, &ss_len) < 0) {
@@ -1518,16 +1584,17 @@ getinfo_helper_dir(control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg)
{
+ const routerinfo_t *ri;
(void) control_conn;
if (!strcmpstart(question, "desc/id/")) {
- routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
+ ri = router_get_by_hexdigest(question+strlen("desc/id/"));
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
*answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
}
} else if (!strcmpstart(question, "desc/name/")) {
- routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
+ ri = router_get_by_nickname(question+strlen("desc/name/"),1);
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
@@ -1537,7 +1604,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_create();
if (routerlist && routerlist->routers) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
+ SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
@@ -1553,7 +1620,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_create();
if (routerlist && routerlist->routers) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
+ SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
signed_descriptor_t *ei = extrainfo_get_by_descriptor_digest(
@@ -1571,8 +1638,8 @@ getinfo_helper_dir(control_connection_t *control_conn,
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
} else if (!strcmpstart(question, "desc-annotations/id/")) {
- routerinfo_t *ri = router_get_by_hexdigest(question+
- strlen("desc-annotations/id/"));
+ ri = router_get_by_hexdigest(question+
+ strlen("desc-annotations/id/"));
if (ri) {
const char *annotations =
signed_descriptor_get_annotations(&ri->cache_info);
@@ -1885,7 +1952,7 @@ getinfo_helper_events(control_connection_t *control_conn,
} else if (!strcmp(question, "status/version/num-versioning") ||
!strcmp(question, "status/version/num-concurring")) {
char s[33];
- tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
+ tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_DIRINFO));
*answer = tor_strdup(s);
log_warn(LD_GENERAL, "%s is deprecated; it no longer gives useful "
"information", question);
@@ -2003,6 +2070,14 @@ static const getinfo_item_t getinfo_items[] = {
"Number of versioning authorities agreeing on the status of the "
"current version"),
ITEM("address", misc, "IP address of this Tor host, if we can guess it."),
+ ITEM("traffic/read", misc,"Bytes read since the process was started."),
+ ITEM("traffic/written", misc,
+ "Bytes written since the process was started."),
+ ITEM("process/pid", misc, "Process id belonging to the main tor process."),
+ ITEM("process/uid", misc, "User id running the tor process."),
+ ITEM("process/user", misc,
+ "Username under which the tor process is running."),
+ ITEM("process/descriptor-limit", misc, "File descriptor limit."),
ITEM("dir-usage", misc, "Breakdown of bytes transferred over DirPort."),
PREFIX("desc-annotations/id/", dir, "Router annotations by hexdigest."),
PREFIX("dir/server/", dir,"Router descriptors as retrieved from a DirPort."),
@@ -2010,8 +2085,8 @@ static const getinfo_item_t getinfo_items[] = {
"v2 networkstatus docs as retrieved from a DirPort."),
ITEM("dir/status-vote/current/consensus", dir,
"v3 Networkstatus consensus as retrieved from a DirPort."),
- PREFIX("exit-policy/default", policies,
- "The default value appended to the configured exit policy."),
+ ITEM("exit-policy/default", policies,
+ "The default value appended to the configured exit policy."),
PREFIX("ip-to-country/", geoip, "Perform a GEOIP lookup"),
{ NULL, NULL, NULL, 0 }
};
@@ -2212,7 +2287,7 @@ static int
handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
const char *body)
{
- smartlist_t *router_nicknames=NULL, *routers=NULL;
+ smartlist_t *router_nicknames=NULL, *nodes=NULL;
origin_circuit_t *circ = NULL;
int zero_circ;
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
@@ -2243,8 +2318,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if ((smartlist_len(args) == 1) ||
(smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
// "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
- circ = circuit_launch_by_router(intended_purpose, NULL,
- CIRCLAUNCH_NEED_CAPACITY);
+ circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
if (!circ) {
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
} else {
@@ -2272,17 +2346,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
- routers = smartlist_create();
+ nodes = smartlist_create();
SMARTLIST_FOREACH(router_nicknames, const char *, n,
{
- routerinfo_t *r = router_get_by_nickname(n, 1);
- if (!r) {
+ const node_t *node = node_get_by_nickname(n, 1);
+ if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
}
- smartlist_add(routers, r);
+ if (!node_has_descriptor(node)) {
+ connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n);
+ goto done;
+ }
+ smartlist_add(nodes, (void*)node);
});
- if (!smartlist_len(routers)) {
+ if (!smartlist_len(nodes)) {
connection_write_str_to_buf("512 No router names provided\r\n", conn);
goto done;
}
@@ -2293,9 +2371,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
}
/* now circ refers to something that is ready to be extended */
- SMARTLIST_FOREACH(routers, routerinfo_t *, r,
+ SMARTLIST_FOREACH(nodes, const node_t *, node,
{
- extend_info_t *info = extend_info_from_router(r);
+ extend_info_t *info = extend_info_from_node(node);
+ tor_assert(info); /* True, since node_has_descriptor(node) == true */
circuit_append_new_exit(circ, info);
extend_info_free(info);
});
@@ -2329,7 +2408,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
done:
SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
smartlist_free(router_nicknames);
- smartlist_free(routers);
+ smartlist_free(nodes);
return 0;
}
@@ -2445,16 +2524,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Is this a single hop circuit? */
if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
- routerinfo_t *r = NULL;
- char* exit_digest;
+ const node_t *node = NULL;
+ char *exit_digest;
if (circ->build_state &&
circ->build_state->chosen_exit &&
!tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
exit_digest = circ->build_state->chosen_exit->identity_digest;
- r = router_get_by_digest(exit_digest);
+ node = node_get_by_id(exit_digest);
}
/* Do both the client and relay allow one-hop exit circuits? */
- if (!r || !r->allow_single_hop_exits ||
+ if (!node ||
+ !node_allows_single_hop_exits(node) ||
!get_options()->AllowSingleHopCircuits) {
connection_write_str_to_buf(
"551 Can't attach stream to this one-hop circuit.\r\n", conn);
@@ -2748,7 +2828,7 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
connection_mark_for_close(TO_CONN(conn));
goto done;
} else {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int cookies = options->CookieAuthentication;
char *cfile = get_cookie_file();
char *esc_cfile = esc_for_log(cfile);
@@ -2826,8 +2906,6 @@ int
connection_control_finished_flushing(control_connection_t *conn)
{
tor_assert(conn);
-
- connection_stop_writing(TO_CONN(conn));
return 0;
}
@@ -2842,6 +2920,43 @@ connection_control_reached_eof(control_connection_t *conn)
return 0;
}
+/** Shut down this Tor instance in the same way that SIGINT would, but
+ * with a log message appropriate for the loss of an owning controller. */
+static void
+lost_owning_controller(const char *owner_type, const char *loss_manner)
+{
+ int shutdown_slowly = server_mode(get_options());
+
+ log_notice(LD_CONTROL, "Owning controller %s has %s -- %s.",
+ owner_type, loss_manner,
+ shutdown_slowly ? "shutting down" : "exiting now");
+
+ /* XXXX Perhaps this chunk of code should be a separate function,
+ * called here and by process_signal(SIGINT). */
+
+ if (!shutdown_slowly) {
+ tor_cleanup();
+ exit(0);
+ }
+ /* XXXX This will close all listening sockets except control-port
+ * listeners. Perhaps we should close those too. */
+ hibernate_begin_shutdown();
+}
+
+/** Called when <b>conn</b> is being freed. */
+void
+connection_control_closed(control_connection_t *conn)
+{
+ tor_assert(conn);
+
+ conn->event_mask = 0;
+ control_update_global_event_mask();
+
+ if (conn->is_owning_control_connection) {
+ lost_owning_controller("connection", "closed");
+ }
+}
+
/** Return true iff <b>cmd</b> is allowable (or at least forgivable) at this
* stage of the protocol. */
static int
@@ -2862,6 +2977,17 @@ is_valid_initial_command(control_connection_t *conn, const char *cmd)
* interfaces is broken. */
#define MAX_COMMAND_LINE_LENGTH (1024*1024)
+static int
+peek_connection_has_control0_command(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return peek_evbuffer_has_control0_command(input);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return peek_buf_has_control0_command(conn->inbuf);
+ }
+}
+
/** Called when data has arrived on a v1 control connection: Try to fetch
* commands from conn->inbuf, and execute them.
*/
@@ -2884,7 +3010,7 @@ connection_control_process_inbuf(control_connection_t *conn)
}
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH &&
- peek_buf_has_control0_command(conn->_base.inbuf)) {
+ peek_connection_has_control0_command(TO_CONN(conn))) {
/* Detect v0 commands and send a "no more v0" message. */
size_t body_len;
char buf[128];
@@ -2896,8 +3022,8 @@ connection_control_process_inbuf(control_connection_t *conn)
body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
set_uint16(buf+0, htons(body_len));
connection_write_to_buf(buf, 4+body_len, TO_CONN(conn));
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+
+ connection_mark_and_flush(TO_CONN(conn));
return 0;
}
@@ -2908,7 +3034,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* First, fetch a line. */
do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
- r = fetch_from_buf_line(conn->_base.inbuf,
+ r = connection_fetch_from_buf_line(TO_CONN(conn),
conn->incoming_cmd+conn->incoming_cmd_cur_len,
&data_len);
if (r == 0)
@@ -2918,8 +3044,7 @@ connection_control_process_inbuf(control_connection_t *conn)
if (data_len + conn->incoming_cmd_cur_len > MAX_COMMAND_LINE_LENGTH) {
connection_write_str_to_buf("500 Line too long.\r\n", conn);
connection_stop_reading(TO_CONN(conn));
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
conn->incoming_cmd_len *= 2;
@@ -2979,8 +3104,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* Otherwise, Quit is always valid. */
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
connection_write_str_to_buf("250 closing connection\r\n", conn);
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
return 0;
}
@@ -2997,6 +3121,9 @@ connection_control_process_inbuf(control_connection_t *conn)
return 0;
}
+ /* XXXX Why is this not implemented as a table like the GETINFO
+ * items are? Even handling the plus signs at the beginnings of
+ * commands wouldn't be very hard with proper macros. */
cmd_data_len = (uint32_t)data_len;
if (!strcasecmp(conn->incoming_cmd, "SETCONF")) {
if (handle_control_setconf(conn, cmd_data_len, args))
@@ -3022,6 +3149,9 @@ connection_control_process_inbuf(control_connection_t *conn)
} else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) {
if (handle_control_signal(conn, cmd_data_len, args))
return -1;
+ } else if (!strcasecmp(conn->incoming_cmd, "TAKEOWNERSHIP")) {
+ if (handle_control_takeownership(conn, cmd_data_len, args))
+ return -1;
} else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) {
if (handle_control_mapaddress(conn, cmd_data_len, args))
return -1;
@@ -3077,7 +3207,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
{
const char *status;
char extended_buf[96];
- int providing_reason=0;
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
return 0;
tor_assert(circ);
@@ -3101,7 +3230,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
const char *reason_str = circuit_end_reason_to_control_string(reason_code);
char *reason = NULL;
size_t n=strlen(extended_buf);
- providing_reason=1;
if (!reason_str) {
reason = tor_malloc(16);
tor_snprintf(reason, 16, "UNKNOWN_%d", reason_code);
@@ -3274,10 +3402,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
static void
orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
{
- routerinfo_t *ri = router_get_by_digest(conn->identity_digest);
- if (ri) {
+ const node_t *node = node_get_by_id(conn->identity_digest);
+ if (node) {
tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
- router_get_verbose_nickname(name, ri);
+ node_get_verbose_nickname(node, name);
} else if (! tor_digest_is_zero(conn->identity_digest)) {
name[0] = '$';
base16_encode(name+1, len-1, conn->identity_digest,
@@ -3594,7 +3722,7 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses,
smartlist_add(strs, tor_strdup("650+"));
smartlist_add(strs, tor_strdup(event_string));
smartlist_add(strs, tor_strdup("\r\n"));
- SMARTLIST_FOREACH(statuses, routerstatus_t *, rs,
+ SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
{
s = networkstatus_getinfo_helper_single(rs);
if (!s) continue;
@@ -3682,10 +3810,46 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
return 0;
}
+/** Called when a signal has been processed from signal_callback */
+int
+control_event_signal(uintptr_t signal)
+{
+ const char *signal_string = NULL;
+
+ if (!control_event_is_interesting(EVENT_SIGNAL))
+ return 0;
+
+ switch (signal) {
+ case SIGHUP:
+ signal_string = "RELOAD";
+ break;
+ case SIGUSR1:
+ signal_string = "DUMP";
+ break;
+ case SIGUSR2:
+ signal_string = "DEBUG";
+ break;
+ case SIGNEWNYM:
+ signal_string = "NEWNYM";
+ break;
+ case SIGCLEARDNSCACHE:
+ signal_string = "CLEARDNSCACHE";
+ break;
+ default:
+ log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
+ (unsigned long)signal);
+ return -1;
+ }
+
+ send_control_event(EVENT_SIGNAL, ALL_FORMATS, "650 SIGNAL %s\r\n",
+ signal_string);
+ return 0;
+}
+
/** Called when a single local_routerstatus_t has changed: Sends an NS event
* to any controller that cares. */
int
-control_event_networkstatus_changed_single(routerstatus_t *rs)
+control_event_networkstatus_changed_single(const routerstatus_t *rs)
{
smartlist_t *statuses;
int r;
@@ -3694,7 +3858,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs)
return 0;
statuses = smartlist_create();
- smartlist_add(statuses, rs);
+ smartlist_add(statuses, (void*)rs);
r = control_event_networkstatus_changed(statuses);
smartlist_free(statuses);
return r;
@@ -3819,9 +3983,9 @@ control_event_guard(const char *nickname, const char *digest,
{
char buf[MAX_VERBOSE_NICKNAME_LEN+1];
- routerinfo_t *ri = router_get_by_digest(digest);
- if (ri) {
- router_get_verbose_nickname(buf, ri);
+ const node_t *node = node_get_by_id(digest);
+ if (node) {
+ node_get_verbose_nickname(node, buf);
} else {
tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
}
@@ -3836,7 +4000,7 @@ control_event_guard(const char *nickname, const char *digest,
static char *
get_cookie_file(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->CookieAuthFile && strlen(options->CookieAuthFile)) {
return tor_strdup(options->CookieAuthFile);
} else {
@@ -3884,6 +4048,75 @@ init_cookie_authentication(int enabled)
return 0;
}
+/** A copy of the process specifier of Tor's owning controller, or
+ * NULL if this Tor instance is not currently owned by a process. */
+static char *owning_controller_process_spec = NULL;
+
+/** A process-termination monitor for Tor's owning controller, or NULL
+ * if this Tor instance is not currently owned by a process. */
+static tor_process_monitor_t *owning_controller_process_monitor = NULL;
+
+/** Process-termination monitor callback for Tor's owning controller
+ * process. */
+static void
+owning_controller_procmon_cb(void *unused)
+{
+ (void)unused;
+
+ lost_owning_controller("process", "vanished");
+}
+
+/** Set <b>process_spec</b> as Tor's owning controller process.
+ * Exit on failure. */
+void
+monitor_owning_controller_process(const char *process_spec)
+{
+ const char *msg;
+
+ tor_assert((owning_controller_process_spec == NULL) ==
+ (owning_controller_process_monitor == NULL));
+
+ if (owning_controller_process_spec != NULL) {
+ if ((process_spec != NULL) && !strcmp(process_spec,
+ owning_controller_process_spec)) {
+ /* Same process -- return now, instead of disposing of and
+ * recreating the process-termination monitor. */
+ return;
+ }
+
+ /* We are currently owned by a process, and we should no longer be
+ * owned by it. Free the process-termination monitor. */
+ tor_process_monitor_free(owning_controller_process_monitor);
+ owning_controller_process_monitor = NULL;
+
+ tor_free(owning_controller_process_spec);
+ owning_controller_process_spec = NULL;
+ }
+
+ tor_assert((owning_controller_process_spec == NULL) &&
+ (owning_controller_process_monitor == NULL));
+
+ if (process_spec == NULL)
+ return;
+
+ owning_controller_process_spec = tor_strdup(process_spec);
+ owning_controller_process_monitor =
+ tor_process_monitor_new(tor_libevent_get_base(),
+ owning_controller_process_spec,
+ LD_CONTROL,
+ owning_controller_procmon_cb, NULL,
+ &msg);
+
+ if (owning_controller_process_monitor == NULL) {
+ log_err(LD_BUG, "Couldn't create process-termination monitor for "
+ "owning controller: %s. Exiting.",
+ msg);
+ owning_controller_process_spec = NULL;
+ tor_cleanup();
+ exit(0);
+ }
+}
+
/** Convert the name of a bootstrapping phase <b>s</b> into strings
* <b>tag</b> and <b>summary</b> suitable for display by the controller. */
static int
diff --git a/src/or/control.h b/src/or/control.h
index a73ed5d3c..147a5af0b 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -27,6 +27,8 @@ void control_ports_write_to_file(void);
int connection_control_finished_flushing(control_connection_t *conn);
int connection_control_reached_eof(control_connection_t *conn);
+void connection_control_closed(control_connection_t *conn);
+
int connection_control_process_inbuf(control_connection_t *conn);
#define EVENT_AUTHDIR_NEWDESCS 0x000D
@@ -55,7 +57,7 @@ int control_event_my_descriptor_changed(void);
int control_event_networkstatus_changed(smartlist_t *statuses);
int control_event_newconsensus(const networkstatus_t *consensus);
-int control_event_networkstatus_changed_single(routerstatus_t *rs);
+int control_event_networkstatus_changed_single(const routerstatus_t *rs);
int control_event_general_status(int severity, const char *format, ...)
CHECK_PRINTF(2,3);
int control_event_client_status(int severity, const char *format, ...)
@@ -66,12 +68,15 @@ int control_event_guard(const char *nickname, const char *digest,
const char *status);
int control_event_buildtimeout_set(const circuit_build_times_t *cbt,
buildtimeout_set_event_t type);
+int control_event_signal(uintptr_t signal);
int init_cookie_authentication(int enabled);
smartlist_t *decode_hashed_passwords(config_line_t *passwords);
void disable_control_logging(void);
void enable_control_logging(void);
+void monitor_owning_controller_process(const char *process_spec);
+
void control_event_bootstrap(bootstrap_status_t status, int progress);
void control_event_bootstrap_problem(const char *warn, int reason);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 7cbc19133..bf8964c29 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -62,7 +62,6 @@ connection_cpu_finished_flushing(connection_t *conn)
{
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CPUWORKER);
- connection_stop_writing(conn);
return 0;
}
@@ -141,13 +140,13 @@ connection_cpu_process_inbuf(connection_t *conn)
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CPUWORKER);
- if (!buf_datalen(conn->inbuf))
+ if (!connection_get_inbuf_len(conn))
return 0;
if (conn->state == CPUWORKER_STATE_BUSY_ONION) {
- if (buf_datalen(conn->inbuf) < LEN_ONION_RESPONSE) /* answer available? */
+ if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE)
return 0; /* not yet */
- tor_assert(buf_datalen(conn->inbuf) == LEN_ONION_RESPONSE);
+ tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE);
connection_fetch_from_buf(&success,1,conn);
connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);
@@ -226,8 +225,8 @@ cpuworker_main(void *data)
{
char question[ONIONSKIN_CHALLENGE_LEN];
uint8_t question_type;
- int *fdarray = data;
- int fd;
+ tor_socket_t *fdarray = data;
+ tor_socket_t fd;
/* variables for onion processing */
char keys[CPATH_KEY_MATERIAL_LEN];
@@ -317,12 +316,12 @@ cpuworker_main(void *data)
static int
spawn_cpuworker(void)
{
- int *fdarray;
- int fd;
+ tor_socket_t *fdarray;
+ tor_socket_t fd;
connection_t *conn;
int err;
- fdarray = tor_malloc(sizeof(int)*2);
+ fdarray = tor_malloc(sizeof(tor_socket_t)*2);
if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fdarray)) < 0) {
log_warn(LD_NET, "Couldn't construct socketpair for cpuworker: %s",
tor_socket_strerror(-err));
@@ -367,7 +366,7 @@ spawn_cpuworker(void)
static void
spawn_enough_cpuworkers(void)
{
- int num_cpuworkers_needed = get_options()->NumCPUs;
+ int num_cpuworkers_needed = get_num_cpus(get_options());
if (num_cpuworkers_needed < MIN_CPUWORKERS)
num_cpuworkers_needed = MIN_CPUWORKERS;
diff --git a/src/or/directory.c b/src/or/directory.c
index eb99e9d08..9e1373d46 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -15,7 +15,9 @@
#include "dirvote.h"
#include "geoip.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -78,6 +80,8 @@ static void dir_routerdesc_download_failed(smartlist_t *failed,
int router_purpose,
int was_extrainfo,
int was_descriptor_digests);
+static void dir_microdesc_download_failed(smartlist_t *failed,
+ int status_code);
static void note_client_request(int purpose, int compressed, size_t bytes);
static int client_likes_consensus(networkstatus_t *v, const char *want_url);
@@ -137,26 +141,28 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
+ dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ dir_purpose == DIR_PURPOSE_FETCH_MICRODESC)
return 0;
return 1;
}
-/** Return a newly allocated string describing <b>auth</b>. */
-char *
-authority_type_to_string(authority_type_t auth)
+/** Return a newly allocated string describing <b>auth</b>. Only describes
+ * authority features. */
+static char *
+authdir_type_to_string(dirinfo_type_t auth)
{
char *result;
smartlist_t *lst = smartlist_create();
- if (auth & V1_AUTHORITY)
+ if (auth & V1_DIRINFO)
smartlist_add(lst, (void*)"V1");
- if (auth & V2_AUTHORITY)
+ if (auth & V2_DIRINFO)
smartlist_add(lst, (void*)"V2");
- if (auth & V3_AUTHORITY)
+ if (auth & V3_DIRINFO)
smartlist_add(lst, (void*)"V3");
- if (auth & BRIDGE_AUTHORITY)
+ if (auth & BRIDGE_DIRINFO)
smartlist_add(lst, (void*)"Bridge");
- if (auth & HIDSERV_AUTHORITY)
+ if (auth & HIDSERV_DIRINFO)
smartlist_add(lst, (void*)"Hidden service");
if (smartlist_len(lst)) {
result = smartlist_join_strings(lst, ", ", 0, NULL);
@@ -201,6 +207,8 @@ dir_conn_purpose_to_string(int purpose)
return "hidden-service v2 descriptor fetch";
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
return "hidden-service v2 descriptor upload";
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ return "microdescriptor fetch";
}
log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
@@ -213,17 +221,19 @@ dir_conn_purpose_to_string(int purpose)
int
router_supports_extrainfo(const char *identity_digest, int is_authority)
{
- routerinfo_t *ri = router_get_by_digest(identity_digest);
+ const node_t *node = node_get_by_id(identity_digest);
- if (ri) {
- if (ri->caches_extra_info)
+ if (node && node->ri) {
+ if (node->ri->caches_extra_info)
return 1;
- if (is_authority && ri->platform &&
- tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
+ if (is_authority && node->ri->platform &&
+ tor_version_as_new_as(node->ri->platform,
+ "Tor 0.2.0.0-alpha-dev (r10070)"))
return 1;
}
if (is_authority) {
- routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
+ const routerstatus_t *rs =
+ router_get_consensus_status_by_id(identity_digest);
if (rs && rs->version_supports_extrainfo_upload)
return 1;
}
@@ -242,7 +252,7 @@ int
directories_have_accepted_server_descriptor(void)
{
smartlist_t *servers = router_get_trusted_dir_servers();
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
if ((d->type & options->_PublishServerDescriptor) &&
d->has_accepted_serverdesc) {
@@ -271,11 +281,11 @@ directories_have_accepted_server_descriptor(void)
*/
void
directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
- authority_type_t type,
+ dirinfo_type_t type,
const char *payload,
size_t payload_len, size_t extrainfo_len)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int post_via_tor;
smartlist_t *dirservers = router_get_trusted_dir_servers();
int found = 0;
@@ -297,7 +307,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
continue;
if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, rs)) {
+ routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
"it's in our ExcludedNodes list and StrictNodes is set. "
"Skipping.",
@@ -324,7 +334,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
NULL, payload, upload_len, 0);
} SMARTLIST_FOREACH_END(ds);
if (!found) {
- char *s = authority_type_to_string(type);
+ char *s = authdir_type_to_string(type);
log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
"of type '%s', but no authorities of that type listed!", s);
tor_free(s);
@@ -341,39 +351,42 @@ void
directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource, int pds_flags)
{
- routerstatus_t *rs = NULL;
- or_options_t *options = get_options();
+ const routerstatus_t *rs = NULL;
+ const or_options_t *options = get_options();
int prefer_authority = directory_fetches_from_authorities(options);
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
- authority_type_t type;
+ dirinfo_type_t type;
time_t if_modified_since = 0;
/* FFFF we could break this switch into its own function, and call
* it elsewhere in directory.c. -RD */
switch (dir_purpose) {
case DIR_PURPOSE_FETCH_EXTRAINFO:
- type = EXTRAINFO_CACHE |
- (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
- V3_AUTHORITY);
+ type = EXTRAINFO_DIRINFO |
+ (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
+ V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
- type = V2_AUTHORITY;
+ type = V2_DIRINFO;
prefer_authority = 1; /* Only v2 authorities have these anyway. */
break;
case DIR_PURPOSE_FETCH_SERVERDESC:
- type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
- V3_AUTHORITY);
+ type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
+ V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_RENDDESC:
- type = HIDSERV_AUTHORITY;
+ type = HIDSERV_DIRINFO;
break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
- type = V3_AUTHORITY;
+ type = V3_DIRINFO;
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
case DIR_PURPOSE_FETCH_CERTIFICATE:
- type = V3_AUTHORITY;
+ type = V3_DIRINFO;
+ break;
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ type = MICRODESC_DIRINFO;
break;
default:
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
@@ -381,25 +394,42 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
- networkstatus_t *v = networkstatus_get_latest_consensus();
- if (v)
- if_modified_since = v->valid_after + 180;
+ int flav = FLAV_NS;
+ networkstatus_t *v;
+ if (resource)
+ flav = networkstatus_parse_flavor_name(resource);
+
+ if (flav != -1) {
+ /* IF we have a parsed consensus of this type, we can do an
+ * if-modified-time based on it. */
+ v = networkstatus_get_latest_consensus_by_flavor(flav);
+ if (v)
+ if_modified_since = v->valid_after + 180;
+ } else {
+ /* Otherwise it might be a consensus we don't parse, but which we
+ * do cache. Look at the cached copy, perhaps. */
+ cached_dir_t *cd = dirserv_get_consensus(resource ? resource : "ns");
+ if (cd)
+ if_modified_since = cd->published + 180;
+ }
}
- if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
+ if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
return;
if (!get_via_tor) {
- if (options->UseBridges && type != BRIDGE_AUTHORITY) {
+ if (options->UseBridges && type != BRIDGE_DIRINFO) {
/* want to ask a running bridge for which we have a descriptor. */
/* XXX023 we assume that all of our bridges can answer any
* possible directory question. This won't be true forever. -RD */
/* It certainly is not true with conditional consensus downloading,
* so, for now, never assume the server supports that. */
- routerinfo_t *ri = choose_random_entry(NULL);
- if (ri) {
+ const node_t *node = choose_random_entry(NULL);
+ if (node && node->ri) {
+ /* every bridge has a routerinfo. */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
+ routerinfo_t *ri = node->ri;
+ node_get_addr(node, &addr);
directory_initiate_command(ri->address, &addr,
ri->or_port, 0,
0, /* don't use conditional consensus url */
@@ -412,10 +442,11 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
"nodes are available yet.");
return;
} else {
- if (prefer_authority || type == BRIDGE_AUTHORITY) {
+ if (prefer_authority || type == BRIDGE_DIRINFO) {
/* only ask authdirservers, and don't ask myself */
rs = router_pick_trusteddirserver(type, pds_flags);
- if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) {
+ if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH))) {
/* We don't want to fetch from any authorities that we're currently
* fetching server descriptors from, and we got no match. Did we
* get no match because all the authorities have connections
@@ -423,7 +454,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
* return,) or because all the authorities are down or on fire or
* unreachable or something (in which case we should go on with
* our fallback code)? */
- pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH;
+ pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH);
rs = router_pick_trusteddirserver(type, pds_flags);
if (rs) {
log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
@@ -432,7 +464,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
}
- if (!rs && type != BRIDGE_AUTHORITY) {
+ if (!rs && type != BRIDGE_DIRINFO) {
/* anybody with a non-zero dirport will do */
rs = router_pick_directory_server(type, pds_flags);
if (!rs) {
@@ -449,7 +481,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
/* only ask hidserv authorities, any of them will do */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
- rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
+ rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
} else {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
@@ -495,7 +527,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
routerstatus_t *rs;
if (router_digest_is_me(ds->digest))
continue;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
rs = &ds->fake_status;
directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
@@ -506,7 +538,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
/** Same as directory_initiate_command_routerstatus(), but accepts
* rendezvous data to fetch a hidden service descriptor. */
void
-directory_initiate_command_routerstatus_rend(routerstatus_t *status,
+directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -516,20 +548,22 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
time_t if_modified_since,
const rend_data_t *rend_query)
{
- or_options_t *options = get_options();
- routerinfo_t *router;
+ const or_options_t *options = get_options();
+ const node_t *node;
char address_buf[INET_NTOA_BUF_LEN+1];
struct in_addr in;
const char *address;
tor_addr_t addr;
- router = router_get_by_digest(status->identity_digest);
+ node = node_get_by_id(status->identity_digest);
- if (!router && anonymized_connection) {
+ if (!node && anonymized_connection) {
log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
- "don't have its router descriptor.", status->nickname);
+ "don't have its router descriptor.",
+ routerstatus_describe(status));
return;
- } else if (router) {
- address = router->address;
+ } else if (node) {
+ node_get_address_string(node, address_buf, sizeof(address_buf));
+ address = address_buf;
} else {
in.s_addr = htonl(status->addr);
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
@@ -538,11 +572,11 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
tor_addr_from_ipv4h(&addr, status->addr);
if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
- log_warn(LD_DIR, "Wanted to contact directory mirror '%s' for %s, but "
+ routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
+ log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
"it's in our ExcludedNodes list and StrictNodes is set. "
"Skipping. This choice might make your Tor not work.",
- status->nickname,
+ routerstatus_describe(status),
dir_conn_purpose_to_string(dir_purpose));
return;
}
@@ -573,7 +607,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
* want to fetch.
*/
void
-directory_initiate_command_routerstatus(routerstatus_t *status,
+directory_initiate_command_routerstatus(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -597,7 +631,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
{
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"authority")) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me &&
router_digest_is_me(conn->identity_digest) &&
tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
@@ -625,15 +659,18 @@ connection_dir_request_failed(dir_connection_t *conn)
connection_dir_download_v2_networkstatus_failed(conn, -1);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
- log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
+ log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
+ "directory server at '%s'; retrying",
conn->_base.address);
if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
connection_dir_bridge_routerdesc_failed(conn);
connection_dir_download_routerdesc_failed(conn);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
- networkstatus_consensus_download_failed(0);
+ if (conn->requested_resource)
+ networkstatus_consensus_download_failed(0, conn->requested_resource);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
- log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
+ log_info(LD_DIR, "Giving up on certificate fetch from directory server "
+ "at '%s'; retrying",
conn->_base.address);
connection_dir_download_cert_failed(conn, 0);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
@@ -642,6 +679,10 @@ connection_dir_request_failed(dir_connection_t *conn)
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
log_info(LD_DIR, "Giving up downloading votes from '%s'",
conn->_base.address);
+ } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ log_info(LD_DIR, "Giving up on downloading microdescriptors from "
+ " directory server at '%s'; will retry", conn->_base.address);
+ connection_dir_download_routerdesc_failed(conn);
}
}
@@ -712,7 +753,8 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
/* No need to relaunch descriptor downloads here: we already do it
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
+ conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
(void) conn;
}
@@ -775,7 +817,7 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status)
* 3) Else yes.
*/
static int
-directory_command_should_use_begindir(or_options_t *options,
+directory_command_should_use_begindir(const or_options_t *options,
const tor_addr_t *addr,
int or_port, uint8_t router_purpose,
int anonymized_connection)
@@ -816,6 +858,20 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
if_modified_since, NULL);
}
+/** Return non-zero iff a directory connection with purpose
+ * <b>dir_purpose</b> reveals sensitive information about a Tor
+ * instance's client activities. (Such connections must be performed
+ * through normal three-hop Tor circuits.) */
+static int
+is_sensitive_dir_purpose(uint8_t dir_purpose)
+{
+ return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
+ (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
+}
+
/** Same as directory_initiate_command(), but accepts rendezvous data to
* fetch a hidden service descriptor. */
static void
@@ -831,7 +887,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
const rend_data_t *rend_query)
{
dir_connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int socket_error = 0;
int use_begindir = supports_begindir &&
directory_command_should_use_begindir(options, _addr,
@@ -850,6 +906,9 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
+ tor_assert(!(is_sensitive_dir_purpose(dir_purpose) &&
+ !anonymized_connection));
+
/* ensure that we don't make direct connections when a SOCKS server is
* configured. */
if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
@@ -925,14 +984,14 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
* hook up both sides
*/
linked_conn =
- connection_ap_make_link(conn->_base.address, conn->_base.port,
+ connection_ap_make_link(TO_CONN(conn),
+ conn->_base.address, conn->_base.port,
digest, use_begindir, conn->dirconn_direct);
if (!linked_conn) {
log_warn(LD_NET,"Making tunnel to dirserver failed.");
connection_mark_for_close(TO_CONN(conn));
return;
}
- connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
if (connection_add(TO_CONN(conn)) < 0) {
log_warn(LD_NET,"Unable to add connection for link to dirserver.");
@@ -945,8 +1004,12 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
payload, payload_len,
supports_conditional_consensus,
if_modified_since);
+
connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
- connection_start_reading(TO_CONN(linked_conn));
+ IF_HAS_BUFFEREVENT(TO_CONN(linked_conn), {
+ connection_watch_events(TO_CONN(linked_conn), READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT
+ connection_start_reading(TO_CONN(linked_conn));
}
}
@@ -984,12 +1047,22 @@ _compare_strs(const void **a, const void **b)
* This url depends on whether or not the server we go to
* is sufficiently new to support conditional consensus downloading,
* i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
+ *
+ * If 'resource' is provided, it is the name of a consensus flavor to request.
*/
static char *
-directory_get_consensus_url(int supports_conditional_consensus)
+directory_get_consensus_url(int supports_conditional_consensus,
+ const char *resource)
{
- char *url;
- size_t len;
+ char *url = NULL;
+ const char *hyphen, *flavor;
+ if (resource==NULL || strcmp(resource, "ns")==0) {
+ flavor = ""; /* Request ns consensuses as "", so older servers will work*/
+ hyphen = "";
+ } else {
+ flavor = resource;
+ hyphen = "-";
+ }
if (supports_conditional_consensus) {
char *authority_id_list;
@@ -999,7 +1072,7 @@ directory_get_consensus_url(int supports_conditional_consensus)
trusted_dir_server_t *, ds,
{
char *hex;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
@@ -1011,16 +1084,15 @@ directory_get_consensus_url(int supports_conditional_consensus)
authority_id_list = smartlist_join_strings(authority_digests,
"+", 0, NULL);
- len = strlen(authority_id_list)+64;
- url = tor_malloc(len);
- tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
- authority_id_list);
+ tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
+ hyphen, flavor, authority_id_list);
SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
smartlist_free(authority_digests);
tor_free(authority_id_list);
} else {
- url = tor_strdup("/tor/status-vote/current/consensus.z");
+ tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s.z",
+ hyphen, flavor);
}
return url;
}
@@ -1101,10 +1173,11 @@ directory_send_command(dir_connection_t *conn,
tor_snprintf(url, len, "/tor/status/%s", resource);
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
- tor_assert(!resource);
+ /* resource is optional. If present, it's a flavor name */
tor_assert(!payload);
httpcommand = "GET";
- url = directory_get_consensus_url(supports_conditional_consensus);
+ url = directory_get_consensus_url(supports_conditional_consensus,
+ resource);
log_info(LD_DIR, "Downloading consensus from %s using %s",
hoststring, url);
break;
@@ -1144,6 +1217,11 @@ directory_send_command(dir_connection_t *conn,
url = tor_malloc(len);
tor_snprintf(url, len, "/tor/extra/%s", resource);
break;
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ tor_assert(resource);
+ httpcommand = "GET";
+ tor_asprintf(&url, "/tor/micro/%s", resource);
+ break;
case DIR_PURPOSE_UPLOAD_DIR:
tor_assert(!resource);
tor_assert(payload);
@@ -1419,6 +1497,9 @@ body_is_plausible(const char *body, size_t len, int purpose)
return 1; /* empty bodies don't need decompression */
if (len < 32)
return 0;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ return (!strcmpstart(body,"onion-key"));
+ }
if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
if (!strcmpstart(body,"router") ||
!strcmpstart(body,"signed-directory") ||
@@ -1495,11 +1576,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
int plausible;
int skewed=0;
int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
+ conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
int was_compressed=0;
time_t now = time(NULL);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_DL_SIZE,
allow_partial)) {
@@ -1574,13 +1656,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (status_code == 503) {
routerstatus_t *rs;
trusted_dir_server_t *ds;
+ const char *id_digest = conn->identity_digest;
log_info(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
- if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
+ if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
rs->last_dir_503_at = now;
- if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
+ if ((ds = router_get_trusteddirserver_by_digest(id_digest)))
ds->fake_status.last_dir_503_at = now;
tor_free(body); tor_free(headers); tor_free(reason);
@@ -1719,6 +1802,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
int r;
+ const char *flavname = conn->requested_resource;
if (status_code != 200) {
int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
log(severity, LD_DIR,
@@ -1727,22 +1811,24 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
- networkstatus_consensus_download_failed(status_code);
+ networkstatus_consensus_download_failed(status_code, flavname);
return -1;
}
log_info(LD_DIR,"Received consensus directory (size %d) from server "
"'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
- if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) {
+ if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) {
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
- "Unable to load consensus directory downloaded from "
+ "Unable to load %s consensus directory downloaded from "
"server '%s:%d'. I'll try again soon.",
- conn->_base.address, conn->_base.port);
+ flavname, conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
- networkstatus_consensus_download_failed(0);
+ networkstatus_consensus_download_failed(0, flavname);
return -1;
}
/* launches router downloads as needed */
routers_update_all_from_networkstatus(now, 3);
+ update_microdescs_from_networkstatus(now);
+ update_microdesc_downloads(now);
directory_info_has_arrived(now, 0);
log_info(LD_DIR, "Successfully loaded consensus.");
}
@@ -1892,6 +1978,43 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (directory_conn_is_self_reachability_test(conn))
router_dirport_found_reachable();
}
+ if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ smartlist_t *which = NULL;
+ log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
+ "size %d) from server '%s:%d'",
+ status_code, (int)body_len, conn->_base.address,
+ conn->_base.port);
+ tor_assert(conn->requested_resource &&
+ !strcmpstart(conn->requested_resource, "d/"));
+ which = smartlist_create();
+ dir_split_resource_into_fingerprints(conn->requested_resource+2,
+ which, NULL,
+ DSR_DIGEST256|DSR_BASE64);
+ if (status_code != 200) {
+ log_info(LD_DIR, "Received status code %d (%s) from server "
+ "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
+ "soon.",
+ status_code, escaped(reason), conn->_base.address,
+ (int)conn->_base.port, conn->requested_resource);
+ dir_microdesc_download_failed(which, status_code);
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ smartlist_free(which);
+ tor_free(body); tor_free(headers); tor_free(reason);
+ return 0;
+ } else {
+ smartlist_t *mds;
+ mds = microdescs_add_to_cache(get_microdesc_cache(),
+ body, body+body_len, SAVED_NOWHERE, 0,
+ now, which);
+ if (smartlist_len(which)) {
+ /* Mark remaining ones as failed. */
+ dir_microdesc_download_failed(which, status_code);
+ }
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ smartlist_free(which);
+ smartlist_free(mds);
+ }
+ }
if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
switch (status_code) {
@@ -1900,7 +2023,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
router_get_trusteddirserver_by_digest(conn->identity_digest);
char *rejected_hdr = http_get_header(headers,
"X-Descriptor-Not-New: ");
- int rejected = 0;
if (rejected_hdr) {
if (!strcmp(rejected_hdr, "Yes")) {
log_info(LD_GENERAL,
@@ -1913,7 +2035,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
* last descriptor, not on the published time of the last
* descriptor. If those are different, that's a bad thing to
* do. -NM */
- rejected = 1;
}
tor_free(rejected_hdr);
}
@@ -2168,7 +2289,7 @@ connection_dir_process_inbuf(dir_connection_t *conn)
return 0;
}
- if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
+ if (connection_get_inbuf_len(TO_CONN(conn)) > MAX_DIRECTORY_OBJECT_SIZE) {
log_warn(LD_HTTP, "Too much data received from directory connection: "
"denial of service attempt, or you need to upgrade?");
connection_mark_for_close(TO_CONN(conn));
@@ -2471,18 +2592,18 @@ client_likes_consensus(networkstatus_t *v, const char *want_url)
* Always return 0. */
static int
directory_handle_command_get(dir_connection_t *conn, const char *headers,
- const char *body, size_t body_len)
+ const char *req_body, size_t req_body_len)
{
size_t dlen;
char *url, *url_mem, *header;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
time_t if_modified_since = 0;
int compressed;
size_t url_len;
/* We ignore the body of a GET request. */
- (void)body;
- (void)body_len;
+ (void)req_body;
+ (void)req_body_len;
log_debug(LD_DIRSERV,"Received GET command.");
@@ -3191,7 +3312,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
const char *body, size_t body_len)
{
char *url = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
log_debug(LD_DIRSERV,"Received POST command.");
@@ -3335,7 +3456,7 @@ directory_handle_command(dir_connection_t *conn)
tor_assert(conn);
tor_assert(conn->_base.type == CONN_TYPE_DIR);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_UL_SIZE, 0)) {
case -1: /* overflow */
@@ -3388,10 +3509,10 @@ connection_dir_finished_flushing(dir_connection_t *conn)
DIRREQ_DIRECT,
DIRREQ_FLUSHING_DIR_CONN_FINISHED);
switch (conn->_base.state) {
+ case DIR_CONN_STATE_CONNECTING:
case DIR_CONN_STATE_CLIENT_SENDING:
log_debug(LD_DIR,"client finished sending command.");
conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
- connection_stop_writing(TO_CONN(conn));
return 0;
case DIR_CONN_STATE_SERVER_WRITING:
log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
@@ -3621,6 +3742,36 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
}
+/* DOCDOC NM */
+static void
+dir_microdesc_download_failed(smartlist_t *failed,
+ int status_code)
+{
+ networkstatus_t *consensus
+ = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ routerstatus_t *rs;
+ download_status_t *dls;
+ time_t now = time(NULL);
+ int server = directory_fetches_from_authorities(get_options());
+
+ if (! consensus)
+ return;
+ SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
+ rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
+ if (!rs)
+ continue;
+ dls = &rs->dl_status;
+ if (dls->n_download_failures >= MAX_MICRODESC_DOWNLOAD_FAILURES)
+ continue;
+ {
+ char buf[BASE64_DIGEST256_LEN+1];
+ digest256_to_base64(buf, d);
+ download_status_increment_failure(dls, status_code, buf,
+ server, now);
+ }
+ } SMARTLIST_FOREACH_END(d);
+}
+
/** Helper. Compare two fp_pair_t objects, and return negative, 0, or
* positive as appropriate. */
static int
diff --git a/src/or/directory.h b/src/or/directory.h
index 94dfb1764..caff938e5 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -13,9 +13,8 @@
#define _TOR_DIRECTORY_H
int directories_have_accepted_server_descriptor(void);
-char *authority_type_to_string(authority_type_t auth);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
- authority_type_t type, const char *payload,
+ dirinfo_type_t type, const char *payload,
size_t payload_len, size_t extrainfo_len);
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource,
@@ -23,7 +22,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
void directory_get_from_all_authorities(uint8_t dir_purpose,
uint8_t router_purpose,
const char *resource);
-void directory_initiate_command_routerstatus(routerstatus_t *status,
+void directory_initiate_command_routerstatus(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -31,7 +30,7 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
const char *payload,
size_t payload_len,
time_t if_modified_since);
-void directory_initiate_command_routerstatus_rend(routerstatus_t *status,
+void directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 79b68cdac..0ea1ef648 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -16,6 +16,7 @@
#include "hibernate.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rephist.h"
#include "router.h"
@@ -67,8 +68,6 @@ static char *format_versions_list(config_line_t *ln);
struct authdir_config_t;
static int add_fingerprint_to_dir(const char *nickname, const char *fp,
struct authdir_config_t *list);
-static uint32_t dirserv_router_get_status(const routerinfo_t *router,
- const char **msg);
static uint32_t
dirserv_get_status_impl(const char *fp, const char *nickname,
const char *address,
@@ -76,7 +75,8 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
const char *platform, const char *contact,
const char **msg, int should_log);
static void clear_cached_dir(cached_dir_t *d);
-static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp,
+static const signed_descriptor_t *get_signed_descriptor_by_fp(
+ const char *fp,
int extrainfo,
time_t publish_cutoff);
static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
@@ -212,7 +212,7 @@ dirserv_load_fingerprint_file(void)
authdir_config_t *fingerprint_list_new;
int result;
config_line_t *front=NULL, *list;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
fname = get_datadir_fname("approved-routers");
log_info(LD_GENERAL,
@@ -305,7 +305,7 @@ dirserv_load_fingerprint_file(void)
*
* If the status is 'FP_REJECT' and <b>msg</b> is provided, set
* *<b>msg</b> to an explanation of why. */
-static uint32_t
+uint32_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg)
{
char d[DIGEST_LEN];
@@ -327,7 +327,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
/** Return true if there is no point in downloading the router described by
* <b>rs</b> because this directory would reject it. */
int
-dirserv_would_reject_router(routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs)
{
uint32_t res;
@@ -362,7 +362,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
return 0;
}
-/** Helper: As dirserv_get_router_status, but takes the router fingerprint
+/** Helper: As dirserv_router_get_status, but takes the router fingerprint
* (hex, no spaces), nickname, address (used for logging only), IP address, OR
* port, platform (logging only) and contact info (logging only) as arguments.
*
@@ -377,7 +377,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
const char **msg, int should_log)
{
int reject_unlisted = get_options()->AuthDirRejectUnlisted;
- uint32_t result = 0;
+ uint32_t result;
router_status_t *status_by_digest;
if (!fingerprint_list)
@@ -518,14 +518,15 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
if (get_options()->DirAllowPrivateAddresses)
return 0; /* whatever it is, we're fine with it */
if (!tor_inet_aton(ri->address, &iaddr)) {
- log_info(LD_DIRSERV,"Router '%s' published non-IP address '%s'. Refusing.",
- ri->nickname, ri->address);
+ log_info(LD_DIRSERV,"Router %s published non-IP address '%s'. Refusing.",
+ router_describe(ri),
+ ri->address);
return -1;
}
if (is_internal_IP(ntohl(iaddr.s_addr), 0)) {
log_info(LD_DIRSERV,
- "Router '%s' published internal IP address '%s'. Refusing.",
- ri->nickname, ri->address);
+ "Router %s published internal IP address '%s'. Refusing.",
+ router_describe(ri), ri->address);
return -1; /* it's a private IP, we should reject it */
}
return 0;
@@ -541,7 +542,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
*/
int
authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain)
+ int complain, int *valid_out)
{
/* Okay. Now check whether the fingerprint is recognized. */
uint32_t status = dirserv_router_get_status(ri, msg);
@@ -554,10 +555,11 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
/* Is there too much clock skew? */
now = time(NULL);
if (ri->cache_info.published_on > now+ROUTER_ALLOW_SKEW) {
- log_fn(severity, LD_DIRSERV, "Publication time for nickname '%s' is too "
+ log_fn(severity, LD_DIRSERV, "Publication time for %s is too "
"far (%d minutes) in the future; possible clock skew. Not adding "
"(%s)",
- ri->nickname, (int)((ri->cache_info.published_on-now)/60),
+ router_describe(ri),
+ (int)((ri->cache_info.published_on-now)/60),
esc_router_info(ri));
*msg = "Rejected: Your clock is set too far in the future, or your "
"timezone is not correct.";
@@ -565,9 +567,10 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
}
if (ri->cache_info.published_on < now-ROUTER_MAX_AGE_TO_PUBLISH) {
log_fn(severity, LD_DIRSERV,
- "Publication time for router with nickname '%s' is too far "
+ "Publication time for %s is too far "
"(%d minutes) in the past. Not adding (%s)",
- ri->nickname, (int)((now-ri->cache_info.published_on)/60),
+ router_describe(ri),
+ (int)((now-ri->cache_info.published_on)/60),
esc_router_info(ri));
*msg = "Rejected: Server is expired, or your clock is too far in the past,"
" or your timezone is not correct.";
@@ -575,22 +578,32 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
}
if (dirserv_router_has_valid_address(ri) < 0) {
log_fn(severity, LD_DIRSERV,
- "Router with nickname '%s' has invalid address '%s'. "
+ "Router %s has invalid address '%s'. "
"Not adding (%s).",
- ri->nickname, ri->address,
+ router_describe(ri),
+ ri->address,
esc_router_info(ri));
*msg = "Rejected: Address is not an IP, or IP is a private address.";
return -1;
}
- /* Okay, looks like we're willing to accept this one. */
- ri->is_named = (status & FP_NAMED) ? 1 : 0;
- ri->is_valid = (status & FP_INVALID) ? 0 : 1;
- ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
- ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
+
+ *valid_out = ! (status & FP_INVALID);
return 0;
}
+/** Update the relevant flags of <b>node</b> based on our opinion as a
+ * directory authority in <b>authstatus</b>, as returned by
+ * dirserv_router_get_status or equivalent. */
+void
+dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus)
+{
+ node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
+ node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
+ node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+}
+
/** True iff <b>a</b> is more severe than <b>b</b>. */
static int
WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
@@ -715,14 +728,14 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
* from this server. (We do this here and not in router_add_to_routerlist
* because we want to be able to accept the newest router descriptor that
* another authority has, so we all converge on the same one.) */
- ri_old = router_get_by_digest(ri->cache_info.identity_digest);
+ ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
&& router_differences_are_cosmetic(ri_old, ri)
&& !router_is_me(ri)) {
log_info(LD_DIRSERV,
- "Not replacing descriptor from '%s' (source: %s); "
+ "Not replacing descriptor from %s (source: %s); "
"differences are cosmetic.",
- ri->nickname, source);
+ router_describe(ri), source);
*msg = "Not replacing router descriptor; no information has changed since "
"the last one with this identity.";
control_event_or_authdir_new_descriptor("DROPPED",
@@ -759,8 +772,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
routerlist_descriptors_added(changed, 0);
smartlist_free(changed);
if (!*msg) {
- *msg = ri->is_valid ? "Descriptor for valid server accepted" :
- "Descriptor for invalid server accepted";
+ *msg = "Descriptor accepted";
}
log_info(LD_DIRSERV,
"Added descriptor from '%s' (source: %s): %s.",
@@ -775,12 +787,12 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
static was_router_added_t
dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
{
- routerinfo_t *ri;
+ const routerinfo_t *ri;
int r;
tor_assert(msg);
*msg = NULL;
- ri = router_get_by_digest(ei->cache_info.identity_digest);
+ ri = router_get_by_id_digest(ei->cache_info.identity_digest);
if (!ri) {
*msg = "No corresponding router descriptor for extra-info descriptor";
extrainfo_free(ei);
@@ -815,54 +827,67 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
static void
directory_remove_invalid(void)
{
- int i;
int changed = 0;
routerlist_t *rl = router_get_routerlist();
+ smartlist_t *nodes = smartlist_create();
+ smartlist_add_all(nodes, nodelist_get_list());
- routerlist_assert_ok(rl);
-
- for (i = 0; i < smartlist_len(rl->routers); ++i) {
+ SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
const char *msg;
- routerinfo_t *ent = smartlist_get(rl->routers, i);
- uint32_t r = dirserv_router_get_status(ent, &msg);
+ routerinfo_t *ent = node->ri;
+ char description[NODE_DESC_BUF_LEN];
+ uint32_t r;
+ if (!ent)
+ continue;
+ r = dirserv_router_get_status(ent, &msg);
+ router_get_description(description, ent);
if (r & FP_REJECT) {
- log_info(LD_DIRSERV, "Router '%s' is now rejected: %s",
- ent->nickname, msg?msg:"");
+ log_info(LD_DIRSERV, "Router %s is now rejected: %s",
+ description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
- i--;
changed = 1;
continue;
}
- if (bool_neq((r & FP_NAMED), ent->is_named)) {
+#if 0
+ if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
log_info(LD_DIRSERV,
- "Router '%s' is now %snamed.", ent->nickname,
+ "Router %s is now %snamed.", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NAMED)?1:0;
changed = 1;
}
- if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
- log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname,
+ if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
+ log_info(LD_DIRSERV,
+ "Router '%s' is now %snamed. (FP_UNNAMED)", description,
+ (r&FP_NAMED)?"":"un");
+ ent->is_named = (r&FP_NUNAMED)?0:1;
+ changed = 1;
+ }
+#endif
+ if (bool_neq((r & FP_INVALID), !node->is_valid)) {
+ log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
(r&FP_INVALID) ? "in" : "");
- ent->is_valid = (r&FP_INVALID)?0:1;
+ node->is_valid = (r&FP_INVALID)?0:1;
changed = 1;
}
- if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
- log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname,
+ if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
+ log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description,
(r & FP_BADDIR) ? "bad" : "good");
- ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
+ node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
changed = 1;
}
- if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
- log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname,
+ if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
+ log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
(r & FP_BADEXIT) ? "bad" : "good");
- ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+ node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
changed = 1;
}
- }
+ } SMARTLIST_FOREACH_END(node);
if (changed)
directory_set_dirty();
routerlist_assert_ok(rl);
+ smartlist_free(nodes);
}
/** Mark the directory as <b>dirty</b> -- when we're next asked for a
@@ -901,10 +926,11 @@ directory_set_dirty(void)
* as running iff <b>is_live</b> is true.
*/
static char *
-list_single_server_status(routerinfo_t *desc, int is_live)
+list_single_server_status(const routerinfo_t *desc, int is_live)
{
char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
char *cp;
+ const node_t *node;
tor_assert(desc);
@@ -912,7 +938,8 @@ list_single_server_status(routerinfo_t *desc, int is_live)
if (!is_live) {
*cp++ = '!';
}
- if (desc->is_valid) {
+ node = node_get_by_id(desc->cache_info.identity_digest);
+ if (node && node->is_valid) {
strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
cp += strlen(cp);
*cp++ = '=';
@@ -951,6 +978,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
unreachable.
*/
int answer;
+ node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
+ tor_assert(node);
if (router_is_me(router)) {
/* We always know if we are down ourselves. */
@@ -985,7 +1014,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
rep_hist_note_router_unreachable(router->cache_info.identity_digest, when);
}
- router->is_running = answer;
+ node->is_running = answer;
}
/** Based on the routerinfo_ts in <b>routers</b>, allocate the
@@ -1003,7 +1032,7 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
smartlist_t *rs_entries;
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* We include v2 dir auths here too, because they need to answer
* controllers. Eventually we'll deprecate this whole function;
* see also networkstatus_getinfo_by_purpose(). */
@@ -1013,6 +1042,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
rs_entries = smartlist_create();
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
if (authdir) {
/* Update router status in routerinfo_t. */
dirserv_set_router_is_running(ri, now);
@@ -1020,12 +1051,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
if (for_controller) {
char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
char *cp = name_buf;
- if (!ri->is_running)
+ if (!node->is_running)
*cp++ = '!';
router_get_verbose_nickname(cp, ri);
smartlist_add(rs_entries, tor_strdup(name_buf));
} else if (ri->cache_info.published_on >= cutoff) {
- smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
+ smartlist_add(rs_entries, list_single_server_status(ri,
+ node->is_running));
}
} SMARTLIST_FOREACH_END(ri);
@@ -1063,12 +1095,12 @@ format_versions_list(config_line_t *ln)
* not hibernating, and not too old. Else return 0.
*/
static int
-router_is_active(routerinfo_t *ri, time_t now)
+router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
{
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
if (ri->cache_info.published_on < cutoff)
return 0;
- if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
+ if (!node->is_running || !node->is_valid || ri->is_hibernating)
return 0;
return 1;
}
@@ -1167,9 +1199,9 @@ dirserv_dump_directory_to_string(char **dir_out,
/** Return 1 if we fetch our directory material directly from the
* authorities, rather than from a mirror. */
int
-directory_fetches_from_authorities(or_options_t *options)
+directory_fetches_from_authorities(const or_options_t *options)
{
- routerinfo_t *me;
+ const routerinfo_t *me;
uint32_t addr;
int refuseunknown;
if (options->FetchDirInfoEarly)
@@ -1194,7 +1226,7 @@ directory_fetches_from_authorities(or_options_t *options)
* on the "mirror" schedule rather than the "client" schedule.
*/
int
-directory_fetches_dir_info_early(or_options_t *options)
+directory_fetches_dir_info_early(const or_options_t *options)
{
return directory_fetches_from_authorities(options);
}
@@ -1206,7 +1238,7 @@ directory_fetches_dir_info_early(or_options_t *options)
* client as a directory guard.
*/
int
-directory_fetches_dir_info_later(or_options_t *options)
+directory_fetches_dir_info_later(const or_options_t *options)
{
return options->UseBridges != 0;
}
@@ -1214,7 +1246,7 @@ directory_fetches_dir_info_later(or_options_t *options)
/** Return 1 if we want to cache v2 dir info (each status file).
*/
int
-directory_caches_v2_dir_info(or_options_t *options)
+directory_caches_v2_dir_info(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1223,7 +1255,7 @@ directory_caches_v2_dir_info(or_options_t *options)
* and we're willing to serve them to others. Else return 0.
*/
int
-directory_caches_dir_info(or_options_t *options)
+directory_caches_dir_info(const or_options_t *options)
{
if (options->BridgeRelay || options->DirPort)
return 1;
@@ -1239,7 +1271,7 @@ directory_caches_dir_info(or_options_t *options)
* requests via the "begin_dir" interface, which doesn't require
* having any separate port open. */
int
-directory_permits_begindir_requests(or_options_t *options)
+directory_permits_begindir_requests(const or_options_t *options)
{
return options->BridgeRelay != 0 || options->DirPort != 0;
}
@@ -1248,7 +1280,7 @@ directory_permits_begindir_requests(or_options_t *options)
* requests via the controller interface, which doesn't require
* having any separate port open. */
int
-directory_permits_controller_requests(or_options_t *options)
+directory_permits_controller_requests(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1258,7 +1290,8 @@ directory_permits_controller_requests(or_options_t *options)
* lately.
*/
int
-directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now)
+directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now)
{
return !directory_caches_dir_info(options) &&
!options->FetchUselessDescriptors &&
@@ -1281,7 +1314,8 @@ static cached_dir_t cached_runningrouters;
* cached_dir_t. */
static digestmap_t *cached_v2_networkstatus = NULL;
-/** Map from flavor name to the v3 consensuses that we're currently serving. */
+/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
+ * currently serving. */
static strmap_t *cached_consensuses = NULL;
/** Possibly replace the contents of <b>d</b> with the value of
@@ -1525,11 +1559,11 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
cached_dir_t *auth_src,
time_t dirty, cached_dir_t *(*regenerate)(void),
const char *name,
- authority_type_t auth_type)
+ dirinfo_type_t auth_type)
{
- or_options_t *options = get_options();
- int authority = (auth_type == V1_AUTHORITY && authdir_mode_v1(options)) ||
- (auth_type == V2_AUTHORITY && authdir_mode_v2(options));
+ const or_options_t *options = get_options();
+ int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
+ (auth_type == V2_DIRINFO && authdir_mode_v2(options));
if (!authority || authdir_mode_bridge(options)) {
return cache_src;
@@ -1558,7 +1592,7 @@ dirserv_get_directory(void)
return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
the_directory_is_dirty,
dirserv_regenerate_directory,
- "v1 server directory", V1_AUTHORITY);
+ "v1 server directory", V1_DIRINFO);
}
/** Only called by v1 auth dirservers.
@@ -1651,7 +1685,7 @@ dirserv_get_runningrouters(void)
&cached_runningrouters, &the_runningrouters,
runningrouters_is_dirty,
generate_runningrouters,
- "v1 network status list", V1_AUTHORITY);
+ "v1 network status list", V1_DIRINFO);
}
/** Return the latest downloaded consensus networkstatus in encoded, signed,
@@ -1734,7 +1768,7 @@ static uint64_t total_exit_bandwidth = 0;
/** Helper: estimate the uptime of a router given its stated uptime and the
* amount of time since it last stated its stated uptime. */
static INLINE long
-real_uptime(routerinfo_t *router, time_t now)
+real_uptime(const routerinfo_t *router, time_t now)
{
if (now < router->cache_info.published_on)
return router->uptime;
@@ -1788,7 +1822,8 @@ dirserv_thinks_router_is_unreliable(time_t now,
* been set.
*/
static int
-dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
+dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
+ const node_t *node, time_t now)
{
long uptime;
@@ -1816,7 +1851,7 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
* to fix the bug was 0.2.2.25-alpha. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime > get_options()->MinUptimeHidServDirectoryV2 &&
- router->is_running);
+ node->is_running);
}
/** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1864,19 +1899,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* Weighted fractional uptime for each active router. */
wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
+ nodelist_assert_ok();
+
/* Now, fill in the arrays. */
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
uint32_t bw;
- ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
- exit_policy_is_general_exit(ri->exit_policy));
+ node->is_exit = (!router_exit_policy_rejects_all(ri) &&
+ exit_policy_is_general_exit(ri->exit_policy));
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
mtbfs[n_active] = rep_hist_get_stability(id, now);
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
total_bandwidth += bw;
- if (ri->is_exit && !ri->is_bad_exit) {
+ if (node->is_exit && !node->is_bad_exit) {
total_exit_bandwidth += bw;
} else {
bandwidths_excluding_exits[n_active_nonexit] = bw;
@@ -1884,7 +1922,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
}
++n_active;
}
- });
+ } SMARTLIST_FOREACH_END(node);
/* Now, compute thresholds. */
if (n_active) {
@@ -1910,15 +1948,17 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* Now that we have a time-known that 7/8 routers are known longer than,
* fill wfus with the wfu of every such "familiar" router. */
n_familiar = 0;
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
long tk = rep_hist_get_weighted_time_known(id, now);
if (tk < guard_tk)
continue;
wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
}
- });
+ } SMARTLIST_FOREACH_END(node);
if (n_familiar)
guard_wfu = median_double(wfus, n_familiar);
if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
@@ -1989,24 +2029,20 @@ version_from_platform(const char *platform)
*/
int
routerstatus_format_entry(char *buf, size_t buf_len,
- routerstatus_t *rs, const char *version,
+ const routerstatus_t *rs, const char *version,
routerstatus_format_type_t format)
{
int r;
- struct in_addr in;
char *cp;
char *summary;
char published[ISO_TIME_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char identity64[BASE64_DIGEST_LEN+1];
char digest64[BASE64_DIGEST_LEN+1];
format_iso_time(published, rs->published_on);
digest_to_base64(identity64, rs->identity_digest);
digest_to_base64(digest64, rs->descriptor_digest);
- in.s_addr = htonl(rs->addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
r = tor_snprintf(buf, buf_len,
"r %s %s %s%s%s %s %d %d\n",
@@ -2015,7 +2051,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
(format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
(format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
published,
- ipaddr,
+ fmt_addr32(rs->addr),
(int)rs->or_port,
(int)rs->dir_port);
if (r<0) {
@@ -2043,7 +2079,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
rs->is_possible_guard?" Guard":"",
rs->is_hs_dir?" HSDir":"",
rs->is_named?" Named":"",
- rs->is_running?" Running":"",
+ rs->is_flagged_running?" Running":"",
rs->is_stable?" Stable":"",
rs->is_unnamed?" Unnamed":"",
rs->is_v2_dir?" V2Dir":"",
@@ -2065,7 +2101,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
}
if (format != NS_V2) {
- routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
+ const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
uint32_t bw;
if (format != NS_CONTROL_PORT) {
@@ -2161,6 +2197,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
int first_is_auth, second_is_auth;
uint32_t bw_first, bw_second;
+ const node_t *node_first, *node_second;
+ int first_is_running, second_is_running;
/* we return -1 if first should appear before second... that is,
* if first is a better router. */
@@ -2183,9 +2221,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
else if (!first_is_auth && second_is_auth)
return 1;
- else if (first->is_running && !second->is_running)
+ node_first = node_get_by_id(first->cache_info.identity_digest);
+ node_second = node_get_by_id(second->cache_info.identity_digest);
+ first_is_running = node_first && node_first->is_running;
+ second_is_running = node_second && node_second->is_running;
+
+ if (first_is_running && !second_is_running)
return -1;
- else if (!first->is_running && second->is_running)
+ else if (!first_is_running && second_is_running)
return 1;
bw_first = router_get_advertised_bandwidth(first);
@@ -2209,7 +2252,7 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
static digestmap_t *
get_possible_sybil_list(const smartlist_t *routers)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *omit_as_sybil;
smartlist_t *routers_by_ip = smartlist_create();
uint32_t last_addr;
@@ -2254,7 +2297,9 @@ get_possible_sybil_list(const smartlist_t *routers)
*/
void
set_routerstatus_from_routerinfo(routerstatus_t *rs,
- routerinfo_t *ri, time_t now,
+ node_t *node,
+ routerinfo_t *ri,
+ time_t now,
int naming, int listbadexits,
int listbaddirs)
{
@@ -2266,48 +2311,46 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
router_digest_is_trusted_dir(ri->cache_info.identity_digest);
/* Already set by compute_performance_thresholds. */
- rs->is_exit = ri->is_exit;
- rs->is_stable = ri->is_stable =
- router_is_active(ri, now) &&
+ rs->is_exit = node->is_exit;
+ rs->is_stable = node->is_stable =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
!unstable_version;
- rs->is_fast = ri->is_fast =
- router_is_active(ri, now) &&
+ rs->is_fast = node->is_fast =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
- rs->is_running = ri->is_running; /* computed above */
+ rs->is_flagged_running = node->is_running; /* computed above */
if (naming) {
uint32_t name_status = dirserv_get_name_status(
- ri->cache_info.identity_digest, ri->nickname);
+ node->identity, ri->nickname);
rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
}
- rs->is_valid = ri->is_valid;
+ rs->is_valid = node->is_valid;
- if (rs->is_fast &&
+ if (node->is_fast &&
(router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
router_get_advertised_bandwidth(ri) >=
MIN(guard_bandwidth_including_exits,
guard_bandwidth_excluding_exits))) {
- long tk = rep_hist_get_weighted_time_known(
- ri->cache_info.identity_digest, now);
- double wfu = rep_hist_get_weighted_fractional_uptime(
- ri->cache_info.identity_digest, now);
+ long tk = rep_hist_get_weighted_time_known(node->identity, now);
+ double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
} else {
rs->is_possible_guard = 0;
}
- rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
- rs->is_bad_exit = listbadexits && ri->is_bad_exit;
- ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
- rs->is_hs_dir = ri->is_hs_dir;
+ rs->is_bad_directory = listbaddirs && node->is_bad_directory;
+ rs->is_bad_exit = listbadexits && node->is_bad_exit;
+ node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
+ rs->is_hs_dir = node->is_hs_dir;
rs->is_v2_dir = ri->dir_port != 0;
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
rs->is_named = rs->is_unnamed = 0;
rs->published_on = ri->cache_info.published_on;
- memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
+ memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
DIGEST_LEN);
rs->addr = ri->addr;
@@ -2324,7 +2367,7 @@ static void
clear_status_flags_on_sybil(routerstatus_t *rs)
{
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
- rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
+ rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
rs->is_bad_directory = 0;
/* FFFF we might want some mechanism to check later on if we
@@ -2332,18 +2375,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
* forget to add it to this clause. */
}
-/** Clear all the status flags in routerinfo <b>router</b>. We put this
- * function here because it's eerily similar to
- * clear_status_flags_on_sybil() above. One day we should merge them. */
-void
-router_clear_status_flags(routerinfo_t *router)
-{
- router->is_valid = router->is_running = router->is_hs_dir =
- router->is_fast = router->is_stable =
- router->is_possible_guard = router->is_exit =
- router->is_bad_exit = router->is_bad_directory = 0;
-}
-
/**
* Helper function to parse out a line in the measured bandwidth file
* into a measured_bw_line_t output structure. Returns -1 on failure
@@ -2409,7 +2440,7 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line)
tor_free(line);
return -1;
}
- strncpy(out->node_hex, cp, sizeof(out->node_hex));
+ strlcpy(out->node_hex, cp, sizeof(out->node_hex));
got_node_id=1;
}
} while ((cp = tor_strtok_r(NULL, " \t", &strtok_state)));
@@ -2461,7 +2492,7 @@ dirserv_read_measured_bandwidths(const char *from_file,
smartlist_t *routerstatuses)
{
char line[256];
- FILE *fp = fopen(from_file, "r");
+ FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
time_t file_time;
int ok;
@@ -2521,7 +2552,7 @@ networkstatus_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
authority_cert_t *cert)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *v3_out = NULL;
uint32_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -2591,17 +2622,20 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
routerstatus_t *rs;
vote_routerstatus_t *vrs;
microdesc_t *md;
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
- set_routerstatus_from_routerinfo(rs, ri, now,
+ set_routerstatus_from_routerinfo(rs, node, ri, now,
naming, listbadexits, listbaddirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(rs);
if (!vote_on_reachability)
- rs->is_running = 0;
+ rs->is_flagged_running = 0;
vrs->version = version_from_platform(ri->platform);
md = dirvote_create_microdescriptor(ri);
@@ -2699,7 +2733,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
voter->sigs = smartlist_create();
voter->address = hostname;
voter->addr = addr;
- voter->dir_port = router_get_advertised_dir_port(options);
+ voter->dir_port = router_get_advertised_dir_port(options, 0);
voter->or_port = router_get_advertised_or_port(options);
voter->contact = tor_strdup(contact);
if (options->V3AuthUseLegacyKey) {
@@ -2733,12 +2767,10 @@ generate_v2_networkstatus_opinion(void)
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
char *outp, *endp;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char fingerprint[FINGERPRINT_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
- struct in_addr in;
uint32_t addr;
crypto_pk_env_t *private_key;
routerlist_t *rl = router_get_routerlist();
@@ -2759,8 +2791,6 @@ generate_v2_networkstatus_opinion(void)
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
format_iso_time(published, now);
@@ -2806,7 +2836,8 @@ generate_v2_networkstatus_opinion(void)
"dir-options%s%s%s%s\n"
"%s" /* client version line, server version line. */
"dir-signing-key\n%s",
- hostname, ipaddr, (int)router_get_advertised_dir_port(options),
+ hostname, fmt_addr32(addr),
+ (int)router_get_advertised_dir_port(options, 0),
fingerprint,
contact,
published,
@@ -2837,8 +2868,12 @@ generate_v2_networkstatus_opinion(void)
if (ri->cache_info.published_on >= cutoff) {
routerstatus_t rs;
char *version = version_from_platform(ri->platform);
-
- set_routerstatus_from_routerinfo(&rs, ri, now,
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node) {
+ tor_free(version);
+ continue;
+ }
+ set_routerstatus_from_routerinfo(&rs, node, ri, now,
naming, listbadexits, listbaddirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
@@ -2921,7 +2956,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
if (!strcmp(key,"authority")) {
if (authdir_mode_v2(get_options())) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me)
smartlist_add(result,
tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
@@ -2940,7 +2975,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
} else {
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if (ds->type & V2_AUTHORITY)
+ if (ds->type & V2_DIRINFO)
smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN)));
}
smartlist_sort_digests(result);
@@ -3009,7 +3044,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
/* Treat "all" requests as if they were unencrypted */
for_unencrypted_conn = 1;
} else if (!strcmp(key, "authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
smartlist_add(fps_out,
tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
@@ -3029,8 +3064,8 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
if (for_unencrypted_conn) {
/* Remove anything that insists it not be sent unencrypted. */
- SMARTLIST_FOREACH(fps_out, char *, cp, {
- signed_descriptor_t *sd;
+ SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) {
+ const signed_descriptor_t *sd;
if (by_id)
sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0);
else if (is_extrainfo)
@@ -3041,7 +3076,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
tor_free(cp);
SMARTLIST_DEL_CURRENT(fps_out, cp);
}
- });
+ } SMARTLIST_FOREACH_END(cp);
}
if (!smartlist_len(fps_out)) {
@@ -3080,9 +3115,9 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
smartlist_add(descs_out, &(r->cache_info)));
} else if (!strcmp(key, "/tor/server/authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
} else if (!strcmpstart(key, "/tor/server/d/")) {
smartlist_t *digests = smartlist_create();
key += strlen("/tor/server/d/");
@@ -3106,17 +3141,17 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
{
if (router_digest_is_me(d)) {
/* make sure desc_routerinfo exists */
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
} else {
- routerinfo_t *ri = router_get_by_digest(d);
+ const routerinfo_t *ri = router_get_by_id_digest(d);
/* Don't actually serve a descriptor that everyone will think is
* expired. This is an (ugly) workaround to keep buggy 0.1.1.10
* Tors from downloading descriptors that they will throw away.
*/
if (ri && ri->cache_info.published_on > cutoff)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
}
});
SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
@@ -3163,7 +3198,8 @@ dirserv_orconn_tls_done(const char *address,
if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) {
tor_addr_t addr, *addrp=NULL;
log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
- ri->nickname, address, ri->or_port );
+ router_describe(ri),
+ address, ri->or_port);
if (tor_addr_from_str(&addr, ri->address) != -1)
addrp = &addr;
else
@@ -3182,7 +3218,8 @@ dirserv_orconn_tls_done(const char *address,
* an upload or a download. Used to decide whether to relaunch reachability
* testing for the server. */
int
-dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old)
+dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old)
{
if (!authdir_mode_handles_descs(get_options(), ri->purpose))
return 0;
@@ -3306,7 +3343,7 @@ dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff)
* its extra-info document if <b>extrainfo</b> is true. Return
* NULL if not found or if the descriptor is older than
* <b>publish_cutoff</b>. */
-static signed_descriptor_t *
+static const signed_descriptor_t *
get_signed_descriptor_by_fp(const char *fp, int extrainfo,
time_t publish_cutoff)
{
@@ -3316,7 +3353,7 @@ get_signed_descriptor_by_fp(const char *fp, int extrainfo,
else
return &(router_get_my_routerinfo()->cache_info);
} else {
- routerinfo_t *ri = router_get_by_digest(fp);
+ const routerinfo_t *ri = router_get_by_id_digest(fp);
if (ri &&
ri->cache_info.published_on > publish_cutoff) {
if (extrainfo)
@@ -3384,7 +3421,7 @@ dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
tor_assert(fps);
if (is_serverdescs) {
int n = smartlist_len(fps);
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
result = (me?me->cache_info.signed_descriptor_len:2048) * n;
if (compressed)
result /= 2; /* observed compressibility is between 35 and 55%. */
@@ -3448,10 +3485,10 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
const char *body;
char *fp = smartlist_pop_last(conn->fingerprint_stack);
- signed_descriptor_t *sd = NULL;
+ const signed_descriptor_t *sd = NULL;
if (by_fp) {
sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff);
} else {
@@ -3509,7 +3546,7 @@ connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn)
{
microdesc_cache_t *cache = get_microdesc_cache();
while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
char *fp256 = smartlist_pop_last(conn->fingerprint_stack);
microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256);
tor_free(fp256);
@@ -3548,7 +3585,7 @@ connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
ssize_t bytes;
int64_t remaining;
- bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
+ bytes = DIRSERV_BUFFER_MIN - connection_get_outbuf_len(TO_CONN(conn));
tor_assert(bytes > 0);
tor_assert(conn->cached_dir);
if (bytes < 8192)
@@ -3587,7 +3624,7 @@ static int
connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
{
- while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
if (conn->cached_dir) {
int uncompressing = (conn->zlib_state != NULL);
int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
@@ -3633,7 +3670,7 @@ connection_dirserv_flushed_some(dir_connection_t *conn)
{
tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
- if (buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
+ if (connection_get_outbuf_len(TO_CONN(conn)) >= DIRSERV_BUFFER_MIN)
return 0;
switch (conn->dir_spool_src) {
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index 569abfca2..d3fd90ceb 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -52,8 +52,6 @@
MAX_V_LINE_LEN \
)
-#define UNNAMED_ROUTER_NICKNAME "Unnamed"
-
int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
@@ -73,15 +71,16 @@ int list_server_status_v1(smartlist_t *routers, char **router_status_out,
int dirserv_dump_directory_to_string(char **dir_out,
crypto_pk_env_t *private_key);
-int directory_fetches_from_authorities(or_options_t *options);
-int directory_fetches_dir_info_early(or_options_t *options);
-int directory_fetches_dir_info_later(or_options_t *options);
-int directory_caches_v2_dir_info(or_options_t *options);
+int directory_fetches_from_authorities(const or_options_t *options);
+int directory_fetches_dir_info_early(const or_options_t *options);
+int directory_fetches_dir_info_later(const or_options_t *options);
+int directory_caches_v2_dir_info(const or_options_t *options);
#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o)
-int directory_caches_dir_info(or_options_t *options);
-int directory_permits_begindir_requests(or_options_t *options);
-int directory_permits_controller_requests(or_options_t *options);
-int directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now);
+int directory_caches_dir_info(const or_options_t *options);
+int directory_permits_begindir_requests(const or_options_t *options);
+int directory_permits_controller_requests(const or_options_t *options);
+int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now);
void directory_set_dirty(void);
cached_dir_t *dirserv_get_directory(void);
@@ -111,13 +110,19 @@ void dirserv_orconn_tls_done(const char *address,
uint16_t or_port,
const char *digest_rcvd,
int as_advertised);
-int dirserv_should_launch_reachability_test(routerinfo_t *ri,
- routerinfo_t *ri_old);
+int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old);
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
void dirserv_test_reachability(time_t now);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain);
-int dirserv_would_reject_router(routerstatus_t *rs);
+ int complain,
+ int *valid_out);
+uint32_t dirserv_router_get_status(const routerinfo_t *router,
+ const char **msg);
+void dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus);
+
+int dirserv_would_reject_router(const routerstatus_t *rs);
int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);
int dirserv_have_any_microdesc(const smartlist_t *fps);
@@ -126,7 +131,7 @@ size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
size_t dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed);
int routerstatus_format_entry(char *buf, size_t buf_len,
- routerstatus_t *rs, const char *platform,
+ const routerstatus_t *rs, const char *platform,
routerstatus_format_type_t format);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 96e3df5ce..bf34c62af 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -83,9 +83,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
const char *client_versions = NULL, *server_versions = NULL;
char *outp, *endp;
char fingerprint[FINGERPRINT_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char digest[DIGEST_LEN];
- struct in_addr in;
uint32_t addr;
routerlist_t *rl = router_get_routerlist();
char *version_lines = NULL;
@@ -98,8 +96,6 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
voter = smartlist_get(v3_ns->voters, 0);
addr = voter->addr;
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
base16_encode(fingerprint, sizeof(fingerprint),
v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
@@ -186,7 +182,8 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
flags,
params,
voter->nickname, fingerprint, voter->address,
- ipaddr, voter->dir_port, voter->or_port, voter->contact);
+ fmt_addr32(addr), voter->dir_port, voter->or_port,
+ voter->contact);
if (r < 0) {
log_err(LD_BUG, "Insufficient memory for network status line");
@@ -1530,8 +1527,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id);
SMARTLIST_FOREACH_BEGIN(dir_sources, const dir_src_ent_t *, e) {
- struct in_addr in;
- char ip[INET_NTOA_BUF_LEN];
char fingerprint[HEX_DIGEST_LEN+1];
char votedigest[HEX_DIGEST_LEN+1];
networkstatus_t *v = e->v;
@@ -1541,8 +1536,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
if (e->is_legacy)
tor_assert(consensus_method >= 2);
- in.s_addr = htonl(voter->addr);
- tor_inet_ntoa(&in, ip, sizeof(ip));
base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
DIGEST_LEN);
@@ -1550,7 +1543,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
tor_asprintf(&buf,
"dir-source %s%s %s %s %s %d %d\n",
voter->nickname, e->is_legacy ? "-legacy" : "",
- fingerprint, voter->address, ip,
+ fingerprint, voter->address, fmt_addr32(voter->addr),
voter->dir_port,
voter->or_port);
smartlist_add(chunks, buf);
@@ -1592,7 +1585,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
* is the same flag as votes[j]->known_flags[b]. */
int *named_flag; /* Index of the flag "Named" for votes[j] */
int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */
- int chosen_named_idx, chosen_unnamed_idx;
+ int chosen_named_idx;
strmap_t *name_to_id_map = strmap_new();
char conflict[DIGEST_LEN];
@@ -1610,7 +1603,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
for (i = 0; i < smartlist_len(votes); ++i)
unnamed_flag[i] = named_flag[i] = -1;
chosen_named_idx = smartlist_string_pos(flags, "Named");
- chosen_unnamed_idx = smartlist_string_pos(flags, "Unnamed");
/* Build the flag index. */
SMARTLIST_FOREACH(votes, networkstatus_t *, v,
@@ -2512,7 +2504,7 @@ authority_cert_dup(authority_cert_t *cert)
void
dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(timing_out);
@@ -2586,7 +2578,7 @@ static struct {
/** Set voting_schedule to hold the timing for the next vote we should be
* doing. */
void
-dirvote_recalculate_timing(or_options_t *options, time_t now)
+dirvote_recalculate_timing(const or_options_t *options, time_t now)
{
int interval, vote_delay, dist_delay;
time_t start;
@@ -2637,7 +2629,7 @@ dirvote_recalculate_timing(or_options_t *options, time_t now)
/** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
void
-dirvote_act(or_options_t *options, time_t now)
+dirvote_act(const or_options_t *options, time_t now)
{
if (!authdir_mode_v3(options))
return;
@@ -2752,7 +2744,7 @@ dirvote_perform_vote(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_vote->vote_body->dir,
pending_vote->vote_body->dir_len, 0);
log_notice(LD_DIR, "Vote posted.");
@@ -2771,7 +2763,7 @@ dirvote_fetch_missing_votes(void)
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
if (!dirvote_get_vote(ds->v3_identity_digest,
DGV_BY_ID|DGV_INCLUDE_PENDING)) {
@@ -2884,7 +2876,7 @@ list_v3_auth_ids(void)
char *keys;
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!tor_digest_is_zero(ds->v3_identity_digest))
smartlist_add(known_v3_keys,
tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
@@ -3079,7 +3071,7 @@ dirvote_compute_consensuses(void)
if (!pending_vote_list)
pending_vote_list = smartlist_create();
- n_voters = get_n_authorities(V3_AUTHORITY);
+ n_voters = get_n_authorities(V3_DIRINFO);
n_votes = smartlist_len(pending_vote_list);
if (n_votes <= n_voters/2) {
log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
@@ -3218,7 +3210,7 @@ dirvote_compute_consensuses(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_consensus_signatures,
strlen(pending_consensus_signatures), 0);
log_notice(LD_DIR, "Signature(s) posted.");
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index 67540a37f..b6746c655 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -41,8 +41,8 @@ authority_cert_t *authority_cert_dup(authority_cert_t *cert);
/* vote scheduling */
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
time_t dirvote_get_start_of_next_interval(time_t now, int interval);
-void dirvote_recalculate_timing(or_options_t *options, time_t now);
-void dirvote_act(or_options_t *options, time_t now);
+void dirvote_recalculate_timing(const or_options_t *options, time_t now);
+void dirvote_act(const or_options_t *options, time_t now);
/* invoked on timers and by outside triggers. */
struct pending_vote_t * dirvote_add_vote(const char *vote_body,
@@ -60,6 +60,7 @@ const char *dirvote_get_pending_detached_signatures(void);
#define DGV_INCLUDE_PREVIOUS 4
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+ node_t *node,
routerinfo_t *ri, time_t now,
int naming, int listbadexits,
int listbaddirs);
diff --git a/src/or/dns.c b/src/or/dns.c
index 9b6b98afa..5d86e81fa 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -276,7 +276,7 @@ dns_init(void)
int
dns_reset(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (! server_mode(options)) {
if (!the_evdns_base) {
@@ -675,7 +675,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
cached_resolve_t *resolve;
cached_resolve_t search;
pending_connection_t *pending_connection;
- routerinfo_t *me;
+ const routerinfo_t *me;
tor_addr_t addr;
time_t now = time(NULL);
uint8_t is_reverse = 0;
@@ -1026,7 +1026,7 @@ add_answer_to_cache(const char *address, uint8_t is_reverse, uint32_t addr,
static INLINE int
is_test_address(const char *address)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return options->ServerDNSTestAddresses &&
smartlist_string_isin_case(options->ServerDNSTestAddresses, address);
}
@@ -1177,7 +1177,7 @@ evdns_err_is_transient(int err)
static int
configure_nameservers(int force)
{
- or_options_t *options;
+ const or_options_t *options;
const char *conf_fname;
struct stat st;
int r;
@@ -1595,7 +1595,7 @@ launch_wildcard_check(int min_len, int max_len, const char *suffix)
static void
launch_test_addresses(int fd, short event, void *args)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
struct evdns_request *req;
(void)fd;
(void)event;
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index 243b730cb..f2c473dfc 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -95,8 +95,8 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
}
if (!q) {
log_info(LD_APP, "None of the questions we got were ones we're willing "
- "to support. Sending NODATA.");
- evdns_server_request_respond(req, DNS_ERR_NONE);
+ "to support. Sending NOTIMPL.");
+ evdns_server_request_respond(req, DNS_ERR_NOTIMPL);
return;
}
if (q->type != EVDNS_TYPE_A) {
@@ -306,7 +306,7 @@ void
dnsserv_configure_listener(connection_t *conn)
{
tor_assert(conn);
- tor_assert(conn->s >= 0);
+ tor_assert(SOCKET_OK(conn->s));
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
conn->dns_server_port =
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index fc005df2d..7fe376baf 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -1028,6 +1028,9 @@ request_parse(u8 *packet, ssize_t length, struct evdns_server_port *port, struct
GET16(answers);
GET16(authority);
GET16(additional);
+ (void)additional;
+ (void)authority;
+ (void)answers;
if (flags & 0x8000) return -1; /* Must not be an answer. */
flags &= 0x0110; /* Only RD and CD get preserved. */
@@ -1560,7 +1563,7 @@ evdns_request_data_build(const char *const name, const size_t name_len,
/* exported function */
struct evdns_server_port *
-evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data)
+evdns_add_server_port(tor_socket_t socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data)
{
struct evdns_server_port *port;
if (!(port = mm_malloc(sizeof(struct evdns_server_port))))
@@ -1828,8 +1831,8 @@ evdns_server_request_respond(struct evdns_server_request *_req, int err)
r = sendto(port->socket, req->response, req->response_len, 0,
(struct sockaddr*) &req->addr, req->addrlen);
if (r<0) {
- int err = last_error(port->socket);
- if (! error_is_eagain(err))
+ int error = last_error(port->socket);
+ if (! error_is_eagain(error))
return -1;
if (port->pending_replies) {
@@ -2288,7 +2291,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
+ ns->socket = tor_open_socket(address->sa_family, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
#ifdef WIN32
{
@@ -3037,7 +3040,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) {
log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
- fd = open(filename, O_RDONLY);
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
if (fd < 0) {
evdns_resolv_set_defaults(flags);
return 1;
@@ -3457,7 +3460,7 @@ main(int c, char **v) {
if (servertest) {
int sock;
struct sockaddr_in my_addr;
- sock = socket(PF_INET, SOCK_DGRAM, 0);
+ sock = tor_open_socket(PF_INET, SOCK_DGRAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(10053);
diff --git a/src/or/eventdns.h b/src/or/eventdns.h
index 2fe4ac937..3ff8bba4b 100644
--- a/src/or/eventdns.h
+++ b/src/or/eventdns.h
@@ -319,7 +319,7 @@ typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, vo
#define EVDNS_CLASS_INET 1
-struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
+struct evdns_server_port *evdns_add_server_port(tor_socket_t socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
void evdns_close_server_port(struct evdns_server_port *port);
int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data);
diff --git a/src/or/geoip.c b/src/or/geoip.c
index 5bb2410a7..62c7a5c39 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -44,6 +44,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL;
/** A list of all known geoip_entry_t, sorted by ip_low. */
static smartlist_t *geoip_entries = NULL;
+/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */
+static char geoip_digest[DIGEST_LEN];
+
/** Return the index of the <b>country</b>'s entry in the GeoIP DB
* if it is a valid 2-letter country code, otherwise return -1.
*/
@@ -113,10 +116,10 @@ geoip_parse_entry(const char *line)
++line;
if (*line == '#')
return 0;
- if (sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
+ if (tor_sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
geoip_add_entry(low, high, b);
return 0;
- } else if (sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
+ } else if (tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
geoip_add_entry(low, high, b);
return 0;
} else {
@@ -159,7 +162,7 @@ _geoip_compare_key_to_entry(const void *_key, const void **_member)
/** Return 1 if we should collect geoip stats on bridge users, and
* include them in our extrainfo descriptor. Else return 0. */
int
-should_record_bridge_info(or_options_t *options)
+should_record_bridge_info(const or_options_t *options)
{
return options->BridgeRelay && options->BridgeRecordUsageByCountry;
}
@@ -196,13 +199,14 @@ init_geoip_countries(void)
* with '#' (comments).
*/
int
-geoip_load_file(const char *filename, or_options_t *options)
+geoip_load_file(const char *filename, const or_options_t *options)
{
FILE *f;
const char *msg = "";
int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
+ crypto_digest_env_t *geoip_digest_env = NULL;
clear_geoip_db();
- if (!(f = fopen(filename, "r"))) {
+ if (!(f = tor_fopen_cloexec(filename, "r"))) {
log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s",
filename, msg);
return -1;
@@ -214,11 +218,13 @@ geoip_load_file(const char *filename, or_options_t *options)
smartlist_free(geoip_entries);
}
geoip_entries = smartlist_create();
+ geoip_digest_env = crypto_new_digest_env();
log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename);
while (!feof(f)) {
char buf[512];
if (fgets(buf, (int)sizeof(buf), f) == NULL)
break;
+ crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf));
/* FFFF track full country name. */
geoip_parse_entry(buf);
}
@@ -231,6 +237,11 @@ geoip_load_file(const char *filename, or_options_t *options)
* country. */
refresh_all_country_info();
+ /* Remember file digest so that we can include it in our extra-info
+ * descriptors. */
+ crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
+ crypto_free_digest_env(geoip_digest_env);
+
return 0;
}
@@ -278,6 +289,15 @@ geoip_is_loaded(void)
return geoip_countries != NULL && geoip_entries != NULL;
}
+/** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The
+ * result does not need to be deallocated, but will be overwritten by the
+ * next call of hex_str(). */
+const char *
+geoip_db_digest(void)
+{
+ return hex_str(geoip_digest, DIGEST_LEN);
+}
+
/** Entry in a map from IP address to the last time we've seen an incoming
* connection from that IP address. Used by bridges only, to track which
* countries have them blocked. */
@@ -404,7 +424,7 @@ void
geoip_note_client_seen(geoip_client_action_t action,
uint32_t addr, time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
clientmap_entry_t lookup, *ent;
if (action == GEOIP_CLIENT_CONNECT) {
/* Only remember statistics as entry guard or as bridge. */
@@ -970,7 +990,7 @@ geoip_dirreq_stats_write(time_t now)
geoip_remove_old_clients(start_of_dirreq_stats_interval);
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE) < 0)
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
goto done;
filename = get_datadir_fname2("stats", "dirreq-stats");
data_v2 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
@@ -1209,7 +1229,7 @@ geoip_bridge_stats_write(time_t now)
/* Write it to disk. */
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE) < 0)
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
goto done;
filename = get_datadir_fname2("stats", "bridge-stats");
@@ -1304,7 +1324,7 @@ geoip_entry_stats_write(time_t now)
geoip_remove_old_clients(start_of_entry_stats_interval);
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE) < 0)
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
goto done;
filename = get_datadir_fname2("stats", "entry-stats");
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
diff --git a/src/or/geoip.h b/src/or/geoip.h
index 24f7c5b93..b50da74dc 100644
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@ -15,12 +15,13 @@
#ifdef GEOIP_PRIVATE
int geoip_parse_entry(const char *line);
#endif
-int should_record_bridge_info(or_options_t *options);
-int geoip_load_file(const char *filename, or_options_t *options);
+int should_record_bridge_info(const or_options_t *options);
+int geoip_load_file(const char *filename, const or_options_t *options);
int geoip_get_country_by_ip(uint32_t ipaddr);
int geoip_get_n_countries(void);
const char *geoip_get_country_name(country_t num);
int geoip_is_loaded(void);
+const char *geoip_db_digest(void);
country_t geoip_get_country(const char *countrycode);
void geoip_note_client_seen(geoip_client_action_t action,
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index aebce4cc8..f03433a27 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -134,7 +134,7 @@ static void accounting_set_wakeup_time(void);
* options->AccountingStart. Return 0 on success, -1 on failure. If
* <b>validate_only</b> is true, do not change the current settings. */
int
-accounting_parse_options(or_options_t *options, int validate_only)
+accounting_parse_options(const or_options_t *options, int validate_only)
{
time_unit_t unit;
int ok, idx;
@@ -249,7 +249,7 @@ accounting_parse_options(or_options_t *options, int validate_only)
* hibernate, return 1, else return 0.
*/
int
-accounting_is_enabled(or_options_t *options)
+accounting_is_enabled(const or_options_t *options)
{
if (options->AccountingMax)
return 1;
@@ -411,7 +411,7 @@ static void
update_expected_bandwidth(void)
{
uint64_t expected;
- or_options_t *options= get_options();
+ const or_options_t *options= get_options();
uint64_t max_configured = (options->RelayBandwidthRate > 0 ?
options->RelayBandwidthRate :
options->BandwidthRate) * 60;
@@ -750,7 +750,7 @@ static void
hibernate_begin(hibernate_state_t new_state, time_t now)
{
connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (new_state == HIBERNATE_STATE_EXITING &&
hibernate_state != HIBERNATE_STATE_LIVE) {
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index 2aea0fab0..b5826bced 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -12,8 +12,8 @@
#ifndef _TOR_HIBERNATE_H
#define _TOR_HIBERNATE_H
-int accounting_parse_options(or_options_t *options, int validate_only);
-int accounting_is_enabled(or_options_t *options);
+int accounting_parse_options(const or_options_t *options, int validate_only);
+int accounting_is_enabled(const or_options_t *options);
void configure_accounting(time_t now);
void accounting_run_housekeeping(time_t now);
void accounting_add_bytes(size_t n_read, size_t n_written, int seconds);
diff --git a/src/or/main.c b/src/or/main.c
index d1ceeec34..9536ae449 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -33,6 +33,7 @@
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "ntmain.h"
#include "onion.h"
#include "policies.h"
@@ -44,6 +45,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#include "status.h"
#ifdef USE_DMALLOC
#include <dmalloc.h>
#include <openssl/crypto.h>
@@ -56,14 +58,18 @@
#include <event.h>
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
+
void evdns_shutdown(int);
/********* PROTOTYPES **********/
static void dumpmemusage(int severity);
static void dumpstats(int severity); /* log stats */
-static void conn_read_callback(int fd, short event, void *_conn);
-static void conn_write_callback(int fd, short event, void *_conn);
+static void conn_read_callback(evutil_socket_t fd, short event, void *_conn);
+static void conn_write_callback(evutil_socket_t fd, short event, void *_conn);
static void second_elapsed_callback(periodic_timer_t *timer, void *args);
static int conn_close_if_marked(int i);
static void connection_start_reading_from_linked_conn(connection_t *conn);
@@ -71,6 +77,7 @@ static int connection_should_read_from_linked_conn(connection_t *conn);
/********* START VARIABLES **********/
+#ifndef USE_BUFFEREVENTS
int global_read_bucket; /**< Max number of bytes I can read this second. */
int global_write_bucket; /**< Max number of bytes I can write this second. */
@@ -78,13 +85,17 @@ int global_write_bucket; /**< Max number of bytes I can write this second. */
int global_relayed_read_bucket;
/** Max number of relayed (bandwidth class 1) bytes I can write this second. */
int global_relayed_write_bucket;
-
/** What was the read bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've read). */
static int stats_prev_global_read_bucket;
/** What was the write bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've written). */
static int stats_prev_global_write_bucket;
+#else
+static uint64_t stats_prev_n_read = 0;
+static uint64_t stats_prev_n_written = 0;
+#endif
+
/* XXX we might want to keep stats about global_relayed_*_bucket too. Or not.*/
/** How many bytes have we read since we started the process? */
static uint64_t stats_n_bytes_read = 0;
@@ -150,15 +161,41 @@ int can_complete_circuit=0;
*
****************************************************************************/
+#if 0 && defined(USE_BUFFEREVENTS)
+static void
+free_old_inbuf(connection_t *conn)
+{
+ if (! conn->inbuf)
+ return;
+
+ tor_assert(conn->outbuf);
+ tor_assert(buf_datalen(conn->inbuf) == 0);
+ tor_assert(buf_datalen(conn->outbuf) == 0);
+ buf_free(conn->inbuf);
+ buf_free(conn->outbuf);
+ conn->inbuf = conn->outbuf = NULL;
+
+ if (conn->read_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->read_event);
+ }
+ if (conn->write_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->write_event);
+ }
+ conn->read_event = conn->write_event = NULL;
+}
+#endif
+
/** Add <b>conn</b> to the array of connections that we can poll on. The
* connection's socket must be set; the connection starts out
* non-reading and non-writing.
*/
int
-connection_add(connection_t *conn)
+connection_add_impl(connection_t *conn, int is_connecting)
{
tor_assert(conn);
- tor_assert(conn->s >= 0 ||
+ tor_assert(SOCKET_OK(conn->s) ||
conn->linked ||
(conn->type == CONN_TYPE_AP &&
TO_EDGE_CONN(conn)->is_dns_request));
@@ -167,15 +204,67 @@ connection_add(connection_t *conn)
conn->conn_array_index = smartlist_len(connection_array);
smartlist_add(connection_array, conn);
- if (conn->s >= 0 || conn->linked) {
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(conn)) {
+ if (SOCKET_OK(conn->s) && !conn->linked) {
+ conn->bufev = bufferevent_socket_new(
+ tor_libevent_get_base(),
+ conn->s,
+ BEV_OPT_DEFER_CALLBACKS);
+ if (!conn->bufev) {
+ log_warn(LD_BUG, "Unable to create socket bufferevent");
+ smartlist_del(connection_array, conn->conn_array_index);
+ conn->conn_array_index = -1;
+ return -1;
+ }
+ if (is_connecting) {
+ /* Put the bufferevent into a "connecting" state so that we'll get
+ * a "connected" event callback on successful write. */
+ bufferevent_socket_connect(conn->bufev, NULL, 0);
+ }
+ connection_configure_bufferevent_callbacks(conn);
+ } else if (conn->linked && conn->linked_conn &&
+ connection_type_uses_bufferevent(conn->linked_conn)) {
+ tor_assert(!(SOCKET_OK(conn->s)));
+ if (!conn->bufev) {
+ struct bufferevent *pair[2] = { NULL, NULL };
+ if (bufferevent_pair_new(tor_libevent_get_base(),
+ BEV_OPT_DEFER_CALLBACKS,
+ pair) < 0) {
+ log_warn(LD_BUG, "Unable to create bufferevent pair");
+ smartlist_del(connection_array, conn->conn_array_index);
+ conn->conn_array_index = -1;
+ return -1;
+ }
+ tor_assert(pair[0]);
+ conn->bufev = pair[0];
+ conn->linked_conn->bufev = pair[1];
+ } /* else the other side already was added, and got a bufferevent_pair */
+ connection_configure_bufferevent_callbacks(conn);
+ } else {
+ tor_assert(!conn->linked);
+ }
+
+ if (conn->bufev)
+ tor_assert(conn->inbuf == NULL);
+
+ if (conn->linked_conn && conn->linked_conn->bufev)
+ tor_assert(conn->linked_conn->inbuf == NULL);
+ }
+#else
+ (void) is_connecting;
+#endif
+
+ if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) {
conn->read_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
conn->write_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
+ /* XXXX CHECK FOR NULL RETURN! */
}
log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
- conn_type_to_string(conn->type), conn->s, conn->address,
+ conn_type_to_string(conn->type), (int)conn->s, conn->address,
smartlist_len(connection_array));
return 0;
@@ -187,14 +276,20 @@ connection_unregister_events(connection_t *conn)
{
if (conn->read_event) {
if (event_del(conn->read_event))
- log_warn(LD_BUG, "Error removing read event for %d", conn->s);
+ log_warn(LD_BUG, "Error removing read event for %d", (int)conn->s);
tor_free(conn->read_event);
}
if (conn->write_event) {
if (event_del(conn->write_event))
- log_warn(LD_BUG, "Error removing write event for %d", conn->s);
+ log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s);
tor_free(conn->write_event);
}
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ bufferevent_free(conn->bufev);
+ conn->bufev = NULL;
+ }
+#endif
if (conn->dns_server_port) {
dnsserv_close_listener(conn);
}
@@ -213,7 +308,7 @@ connection_remove(connection_t *conn)
tor_assert(conn);
log_debug(LD_NET,"removing socket %d (type %s), n_conns now %d",
- conn->s, conn_type_to_string(conn->type),
+ (int)conn->s, conn_type_to_string(conn->type),
smartlist_len(connection_array));
tor_assert(conn->conn_array_index >= 0);
@@ -303,12 +398,37 @@ get_connection_array(void)
return connection_array;
}
+/** Provides the traffic read and written over the life of the process. */
+
+uint64_t
+get_bytes_read(void)
+{
+ return stats_n_bytes_read;
+}
+
+uint64_t
+get_bytes_written(void)
+{
+ return stats_n_bytes_written;
+}
+
/** Set the event mask on <b>conn</b> to <b>events</b>. (The event
* mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)
*/
void
connection_watch_events(connection_t *conn, watchable_events_t events)
{
+ IF_HAS_BUFFEREVENT(conn, {
+ short ev = ((short)events) & (EV_READ|EV_WRITE);
+ short old_ev = bufferevent_get_enabled(conn->bufev);
+ if ((ev & ~old_ev) != 0) {
+ bufferevent_enable(conn->bufev, ev);
+ }
+ if ((old_ev & ~ev) != 0) {
+ bufferevent_disable(conn->bufev, old_ev & ~ev);
+ }
+ return;
+ });
if (events & READ_EVENT)
connection_start_reading(conn);
else
@@ -326,6 +446,9 @@ connection_is_reading(connection_t *conn)
{
tor_assert(conn);
+ IF_HAS_BUFFEREVENT(conn,
+ return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
+ );
return conn->reading_from_linked_conn ||
(conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
}
@@ -335,6 +458,12 @@ void
connection_stop_reading(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_disable(conn->bufev, EV_READ);
+ return;
+ });
+
tor_assert(conn->read_event);
if (conn->linked) {
@@ -344,7 +473,7 @@ connection_stop_reading(connection_t *conn)
if (event_del(conn->read_event))
log_warn(LD_NET, "Error from libevent setting read event state for %d "
"to unwatched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -354,6 +483,12 @@ void
connection_start_reading(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_enable(conn->bufev, EV_READ);
+ return;
+ });
+
tor_assert(conn->read_event);
if (conn->linked) {
@@ -364,7 +499,7 @@ connection_start_reading(connection_t *conn)
if (event_add(conn->read_event, NULL))
log_warn(LD_NET, "Error from libevent setting read event state for %d "
"to watched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -375,6 +510,10 @@ connection_is_writing(connection_t *conn)
{
tor_assert(conn);
+ IF_HAS_BUFFEREVENT(conn,
+ return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
+ );
+
return conn->writing_to_linked_conn ||
(conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
}
@@ -384,6 +523,12 @@ void
connection_stop_writing(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_disable(conn->bufev, EV_WRITE);
+ return;
+ });
+
tor_assert(conn->write_event);
if (conn->linked) {
@@ -394,7 +539,7 @@ connection_stop_writing(connection_t *conn)
if (event_del(conn->write_event))
log_warn(LD_NET, "Error from libevent setting write event state for %d "
"to unwatched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -404,6 +549,12 @@ void
connection_start_writing(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_enable(conn->bufev, EV_WRITE);
+ return;
+ });
+
tor_assert(conn->write_event);
if (conn->linked) {
@@ -415,7 +566,7 @@ connection_start_writing(connection_t *conn)
if (event_add(conn->write_event, NULL))
log_warn(LD_NET, "Error from libevent setting write event state for %d "
"to watched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -501,13 +652,13 @@ close_closeable_connections(void)
/** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has
* some data to read. */
static void
-conn_read_callback(int fd, short event, void *_conn)
+conn_read_callback(evutil_socket_t fd, short event, void *_conn)
{
connection_t *conn = _conn;
(void)fd;
(void)event;
- log_debug(LD_NET,"socket %d wants to read.",conn->s);
+ log_debug(LD_NET,"socket %d wants to read.",(int)conn->s);
/* assert_connection_ok(conn, time(NULL)); */
@@ -516,7 +667,7 @@ conn_read_callback(int fd, short event, void *_conn)
#ifndef MS_WINDOWS
log_warn(LD_BUG,"Unhandled error on read for %s connection "
"(fd %d); removing",
- conn_type_to_string(conn->type), conn->s);
+ conn_type_to_string(conn->type), (int)conn->s);
tor_fragile_assert();
#endif
if (CONN_IS_EDGE(conn))
@@ -533,13 +684,14 @@ conn_read_callback(int fd, short event, void *_conn)
/** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has
* some data to write. */
static void
-conn_write_callback(int fd, short events, void *_conn)
+conn_write_callback(evutil_socket_t fd, short events, void *_conn)
{
connection_t *conn = _conn;
(void)fd;
(void)events;
- LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.",conn->s));
+ LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.",
+ (int)conn->s));
/* assert_connection_ok(conn, time(NULL)); */
@@ -548,7 +700,7 @@ conn_write_callback(int fd, short events, void *_conn)
/* this connection is broken. remove it. */
log_fn(LOG_WARN,LD_BUG,
"unhandled error on write for %s connection (fd %d); removing",
- conn_type_to_string(conn->type), conn->s);
+ conn_type_to_string(conn->type), (int)conn->s);
tor_fragile_assert();
if (CONN_IS_EDGE(conn)) {
/* otherwise we cry wolf about duplicate close */
@@ -589,8 +741,25 @@ conn_close_if_marked(int i)
assert_connection_ok(conn, now);
/* assert_all_pending_dns_resolves_ok(); */
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ if (conn->hold_open_until_flushed &&
+ evbuffer_get_length(bufferevent_get_output(conn->bufev))) {
+ /* don't close yet. */
+ return 0;
+ }
+ if (conn->linked_conn && ! conn->linked_conn->marked_for_close) {
+ /* We need to do this explicitly so that the linked connection
+ * notices that there was an EOF. */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
+#endif
+
log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
- if ((conn->s >= 0 || conn->linked_conn) && connection_wants_to_flush(conn)) {
+ IF_HAS_BUFFEREVENT(conn, goto unlink);
+ if ((SOCKET_OK(conn->s) || conn->linked_conn) &&
+ connection_wants_to_flush(conn)) {
/* s == -1 means it's an incomplete edge connection, or that the socket
* has already been closed as unflushable. */
ssize_t sz = connection_bucket_write_limit(conn, now);
@@ -599,7 +768,7 @@ conn_close_if_marked(int i)
"Conn (addr %s, fd %d, type %s, state %d) marked, but wants "
"to flush %d bytes. (Marked at %s:%d)",
escaped_safe_str_client(conn->address),
- conn->s, conn_type_to_string(conn->type), conn->state,
+ (int)conn->s, conn_type_to_string(conn->type), conn->state,
(int)conn->outbuf_flushlen,
conn->marked_for_close_file, conn->marked_for_close);
if (conn->linked_conn) {
@@ -612,8 +781,8 @@ conn_close_if_marked(int i)
}
log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; "
"%d left; flushlen %d; wants-to-flush==%d", retval,
- (int)buf_datalen(conn->outbuf),
- (int)conn->outbuf_flushlen,
+ (int)connection_get_outbuf_len(conn),
+ (int)conn->outbuf_flushlen,
connection_wants_to_flush(conn));
} else if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) {
@@ -630,7 +799,7 @@ conn_close_if_marked(int i)
if (retval > 0) {
LOG_FN_CONN(conn, (LOG_INFO,LD_NET,
"Holding conn (fd %d) open for more flushing.",
- conn->s));
+ (int)conn->s));
conn->timestamp_lastwritten = now; /* reset so we can flush more */
}
return 0;
@@ -650,13 +819,17 @@ conn_close_if_marked(int i)
"something is wrong with your network connection, or "
"something is wrong with theirs. "
"(fd %d, type %s, state %d, marked at %s:%d).",
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
escaped_safe_str_client(conn->address),
- conn->s, conn_type_to_string(conn->type), conn->state,
+ (int)conn->s, conn_type_to_string(conn->type), conn->state,
conn->marked_for_close_file,
conn->marked_for_close);
}
}
+
+#ifdef USE_BUFFEREVENTS
+ unlink:
+#endif
connection_unlink(conn); /* unlink, remove, free */
return 1;
}
@@ -694,18 +867,19 @@ directory_all_unreachable(time_t now)
void
directory_info_has_arrived(time_t now, int from_cache)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!router_have_minimum_dir_info()) {
int quiet = directory_too_idle_to_fetch_descriptors(options, now);
log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"I learned some more directory information, but not enough to "
"build a circuit: %s", get_dir_info_status_string());
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
return;
} else {
- if (directory_fetches_from_authorities(options))
- update_router_descriptor_downloads(now);
+ if (directory_fetches_from_authorities(options)) {
+ update_all_descriptor_downloads(now);
+ }
/* if we have enough dir info, then update our guard status with
* whatever we just learned. */
@@ -738,12 +912,13 @@ run_connection_housekeeping(int i, time_t now)
{
cell_t cell;
connection_t *conn = smartlist_get(connection_array, i);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
or_connection_t *or_conn;
int past_keepalive =
now >= conn->timestamp_lastwritten + options->KeepalivePeriod;
- if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR)
+ if (conn->outbuf && !connection_get_outbuf_len(conn) &&
+ conn->type == CONN_TYPE_OR)
TO_OR_CONN(conn)->timestamp_lastempty = now;
if (conn->marked_for_close) {
@@ -759,11 +934,11 @@ run_connection_housekeeping(int i, time_t now)
(!DIR_CONN_IS_SERVER(conn) &&
conn->timestamp_lastread + DIR_CONN_MAX_STALL < now))) {
log_info(LD_DIR,"Expiring wedged directory conn (fd %d, purpose %d)",
- conn->s, conn->purpose);
+ (int)conn->s, conn->purpose);
/* This check is temporary; it's to let us know whether we should consider
* parsing partial serverdesc responses. */
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
- buf_datalen(conn->inbuf)>=1024) {
+ connection_get_inbuf_len(conn) >= 1024) {
log_info(LD_DIR,"Trying to extract information from wedged server desc "
"download.");
connection_dir_reached_eof(TO_DIR_CONN(conn));
@@ -780,54 +955,55 @@ run_connection_housekeeping(int i, time_t now)
the connection or send a keepalive, depending. */
or_conn = TO_OR_CONN(conn);
+#ifdef USE_BUFFEREVENTS
+ tor_assert(conn->bufev);
+#else
tor_assert(conn->outbuf);
+#endif
if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) {
/* It's bad for new circuits, and has no unmarked circuits on it:
* mark it now. */
log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Too old].",
- conn->s, conn->address, conn->port);
+ (int)conn->s, conn->address, conn->port);
if (conn->state == OR_CONN_STATE_CONNECTING)
connection_or_connect_failed(TO_OR_CONN(conn),
END_OR_CONN_REASON_TIMEOUT,
"Tor gave up on the connection");
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ connection_mark_and_flush(conn);
} else if (!connection_state_is_open(conn)) {
if (past_keepalive) {
/* We never managed to actually get this connection open and happy. */
log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
- conn->s,conn->address, conn->port);
+ (int)conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
}
} else if (we_are_hibernating() && !or_conn->n_circuits &&
- !buf_datalen(conn->outbuf)) {
+ !connection_get_outbuf_len(conn)) {
/* We're hibernating, there's no circuits, and nothing to flush.*/
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
- conn->s,conn->address, conn->port);
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ (int)conn->s,conn->address, conn->port);
+ connection_mark_and_flush(conn);
} else if (!or_conn->n_circuits &&
now >= or_conn->timestamp_last_added_nonpadding +
IDLE_OR_CONN_TIMEOUT) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
- "[idle %d].", conn->s,conn->address, conn->port,
+ "[idle %d].", (int)conn->s,conn->address, conn->port,
(int)(now - or_conn->timestamp_last_added_nonpadding));
connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
} else if (
now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
"Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
"flush; %d seconds since last write)",
- conn->s, conn->address, conn->port,
- (int)buf_datalen(conn->outbuf),
+ (int)conn->s, conn->address, conn->port,
+ (int)connection_get_outbuf_len(conn),
(int)(now-conn->timestamp_lastwritten));
connection_mark_for_close(conn);
- } else if (past_keepalive && !buf_datalen(conn->outbuf)) {
+ } else if (past_keepalive && !connection_get_outbuf_len(conn)) {
/* send a padding cell */
log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)",
conn->address, conn->port);
@@ -842,7 +1018,7 @@ run_connection_housekeeping(int i, time_t now)
static void
signewnym_impl(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!proxy_mode(options)) {
log_info(LD_CONTROL, "Ignoring SIGNAL NEWNYM because client functionality "
"is disabled.");
@@ -851,10 +1027,11 @@ signewnym_impl(time_t now)
circuit_expire_all_dirty_circs();
addressmap_clear_transient();
- rend_cache_purge();
- rend_client_cancel_descriptor_fetches();
+ rend_client_purge_state();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
+
+ control_event_signal(SIGNEWNYM);
}
/** Perform regular maintenance tasks. This function gets run once per
@@ -880,10 +1057,12 @@ run_scheduled_events(time_t now)
static time_t time_to_check_for_expired_networkstatus = 0;
static time_t time_to_write_stats_files = 0;
static time_t time_to_write_bridge_stats = 0;
+ static time_t time_to_check_port_forwarding = 0;
static time_t time_to_launch_reachability_tests = 0;
static int should_init_bridge_stats = 1;
static time_t time_to_retry_dns_init = 0;
- or_options_t *options = get_options();
+ static time_t time_to_next_heartbeat = 0;
+ const or_options_t *options = get_options();
int is_server = server_mode(options);
int i;
int have_dir_info;
@@ -894,6 +1073,16 @@ run_scheduled_events(time_t now)
*/
consider_hibernation(now);
+#if 0
+ {
+ static time_t nl_check_time = 0;
+ if (nl_check_time <= now) {
+ nodelist_assert_ok();
+ nl_check_time = now + 30;
+ }
+ }
+#endif
+
/* 0b. If we've deferred a signewnym, make sure it gets handled
* eventually. */
if (signewnym_is_pending &&
@@ -922,7 +1111,7 @@ run_scheduled_events(time_t now)
}
if (time_to_try_getting_descriptors < now) {
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
update_extrainfo_downloads(now);
if (router_have_minimum_dir_info())
time_to_try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL;
@@ -1046,6 +1235,11 @@ run_scheduled_events(time_t now)
if (next_write && next_write < next_time_to_write_stats_files)
next_time_to_write_stats_files = next_write;
}
+ if (options->ConnDirectionStatistics) {
+ time_t next_write = rep_hist_conn_stats_write(time_to_write_stats_files);
+ if (next_write && next_write < next_time_to_write_stats_files)
+ next_time_to_write_stats_files = next_write;
+ }
time_to_write_stats_files = next_time_to_write_stats_files;
}
@@ -1074,10 +1268,9 @@ run_scheduled_events(time_t now)
/* Remove old information from rephist and the rend cache. */
if (time_to_clean_caches < now) {
rep_history_clean(now - options->RephistTrackTime);
- rend_cache_clean();
- rend_cache_clean_v2_descs_as_dir();
- if (authdir_mode_v3(options))
- microdesc_cache_rebuild(NULL, 0);
+ rend_cache_clean(now);
+ rend_cache_clean_v2_descs_as_dir(now);
+ microdesc_cache_rebuild(NULL, 0);
#define CLEAN_CACHES_INTERVAL (30*60)
time_to_clean_caches = now + CLEAN_CACHES_INTERVAL;
}
@@ -1086,7 +1279,7 @@ run_scheduled_events(time_t now)
/* If we're a server and initializing dns failed, retry periodically. */
if (time_to_retry_dns_init < now) {
time_to_retry_dns_init = now + RETRY_DNS_INTERVAL;
- if (server_mode(options) && has_dns_init_failed())
+ if (is_server && has_dns_init_failed())
dns_init();
}
@@ -1117,7 +1310,7 @@ run_scheduled_events(time_t now)
consider_publishable_server(0);
/* also, check religiously for reachability, if it's within the first
* 20 minutes of our uptime. */
- if (server_mode(options) &&
+ if (is_server &&
(can_complete_circuit || !any_predicted_circuits(now)) &&
!we_are_hibernating()) {
if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
@@ -1128,7 +1321,7 @@ run_scheduled_events(time_t now)
/* If we haven't checked for 12 hours and our bandwidth estimate is
* low, do another bandwidth test. This is especially important for
* bridges, since they might go long periods without much use. */
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (time_to_recheck_bandwidth && me &&
me->bandwidthcapacity < me->bandwidthrate &&
me->bandwidthcapacity < 51200) {
@@ -1162,7 +1355,10 @@ run_scheduled_events(time_t now)
* it's not comfortable with the number of available circuits.
*/
/* XXXX022 If our circuit build timeout is much lower than a second, maybe
- we should do this more often? */
+ * we should do this more often? -NM
+ * It can't be lower than 1.5 seconds currently; see
+ * circuit_build_times_min_timeout(). -RD
+ */
circuit_expire_building();
/** 3b. Also look at pending streams and prune the ones that 'began'
@@ -1253,6 +1449,24 @@ run_scheduled_events(time_t now)
#define BRIDGE_STATUSFILE_INTERVAL (30*60)
time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL;
}
+
+ if (time_to_check_port_forwarding < now &&
+ options->PortForwarding &&
+ is_server) {
+#define PORT_FORWARDING_CHECK_INTERVAL 5
+ tor_check_port_forwarding(options->PortForwardingHelper,
+ options->DirPort,
+ options->ORPort,
+ now);
+ time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
+ }
+
+ /** 11. write the heartbeat message */
+ if (options->HeartbeatPeriod &&
+ time_to_next_heartbeat < now) {
+ log_heartbeat(now);
+ time_to_next_heartbeat = now+options->HeartbeatPeriod;
+ }
}
/** Timer: used to invoke second_elapsed_callback() once per second. */
@@ -1272,7 +1486,10 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
size_t bytes_written;
size_t bytes_read;
int seconds_elapsed;
- or_options_t *options = get_options();
+#ifdef USE_BUFFEREVENTS
+ uint64_t cur_read,cur_written;
+#endif
+ const or_options_t *options = get_options();
(void)timer;
(void)arg;
@@ -1283,9 +1500,15 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
update_approx_time(now);
/* the second has rolled over. check more stuff. */
+ seconds_elapsed = current_second ? (int)(now - current_second) : 0;
+#ifdef USE_BUFFEREVENTS
+ connection_get_rate_limit_totals(&cur_read, &cur_written);
+ bytes_written = (size_t)(cur_written - stats_prev_n_written);
+ bytes_read = (size_t)(cur_read - stats_prev_n_read);
+#else
bytes_written = stats_prev_global_write_bucket - global_write_bucket;
bytes_read = stats_prev_global_read_bucket - global_read_bucket;
- seconds_elapsed = current_second ? (int)(now - current_second) : 0;
+#endif
stats_n_bytes_read += bytes_read;
stats_n_bytes_written += bytes_written;
if (accounting_is_enabled(options) && seconds_elapsed >= 0)
@@ -1295,8 +1518,13 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
if (seconds_elapsed > 0)
connection_bucket_refill(seconds_elapsed, now);
+#ifdef USE_BUFFEREVENTS
+ stats_prev_n_written = cur_written;
+ stats_prev_n_read = cur_read;
+#else
stats_prev_global_read_bucket = global_read_bucket;
stats_prev_global_write_bucket = global_write_bucket;
+#endif
if (server_mode(options) &&
!we_are_hibernating() &&
@@ -1306,7 +1534,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
(stats_n_seconds_working+seconds_elapsed) /
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
/* every 20 minutes, check and complain if necessary */
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me && !check_whether_orport_reachable()) {
log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
"its ORPort is reachable. Please check your firewalls, ports, "
@@ -1404,7 +1632,7 @@ dns_servers_relaunch_checks(void)
static int
do_hup(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
#ifdef USE_DMALLOC
dmalloc_log_stats();
@@ -1496,8 +1724,10 @@ do_main_loop(void)
/* Set up our buckets */
connection_bucket_init();
+#ifndef USE_BUFFEREVENTS
stats_prev_global_read_bucket = global_read_bucket;
stats_prev_global_write_bucket = global_write_bucket;
+#endif
/* initialize the bootstrap status events to know we're starting up */
control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
@@ -1628,11 +1858,13 @@ process_signal(uintptr_t sig)
case SIGUSR1:
/* prefer to log it at INFO, but make sure we always see it */
dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO);
+ control_event_signal(sig);
break;
case SIGUSR2:
switch_logs_debug();
log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. "
"Send HUP to change back.");
+ control_event_signal(sig);
break;
case SIGHUP:
if (do_hup() < 0) {
@@ -1640,6 +1872,7 @@ process_signal(uintptr_t sig)
tor_cleanup();
exit(1);
}
+ control_event_signal(sig);
break;
#ifdef SIGCHLD
case SIGCHLD:
@@ -1661,10 +1894,18 @@ process_signal(uintptr_t sig)
}
case SIGCLEARDNSCACHE:
addressmap_clear_transient();
+ control_event_signal(sig);
break;
}
}
+/** Returns Tor's uptime. */
+long
+get_uptime(void)
+{
+ return stats_n_seconds_working;
+}
+
extern uint64_t rephist_total_alloc;
extern uint32_t rephist_total_num;
@@ -1700,7 +1941,7 @@ dumpstats(int severity)
int i = conn_sl_idx;
log(severity, LD_GENERAL,
"Conn %d (socket %d) type %d (%s), state %d (%s), created %d secs ago",
- i, conn->s, conn->type, conn_type_to_string(conn->type),
+ i, (int)conn->s, conn->type, conn_type_to_string(conn->type),
conn->state, conn_state_to_string(conn->type, conn->state),
(int)(now - conn->timestamp_created));
if (!connection_is_listener(conn)) {
@@ -1711,13 +1952,13 @@ dumpstats(int severity)
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
i,
- (int)buf_datalen(conn->inbuf),
+ (int)connection_get_inbuf_len(conn),
(int)buf_allocation(conn->inbuf),
(int)(now - conn->timestamp_lastread));
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on outbuf "
"(len %d, last written %d secs ago)",i,
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
(int)buf_allocation(conn->outbuf),
(int)(now - conn->timestamp_lastwritten));
if (conn->type == CONN_TYPE_OR) {
@@ -1932,7 +2173,7 @@ static tor_lockfile_t *lockfile = NULL;
* return -1 if we can't get the lockfile. Return 0 on success.
*/
int
-try_locking(or_options_t *options, int err_if_locked)
+try_locking(const or_options_t *options, int err_if_locked)
{
if (lockfile)
return 0;
@@ -2014,6 +2255,7 @@ tor_free_all(int postfork)
connection_free_all();
buf_shrink_freelists(1);
memarea_clear_freelist();
+ nodelist_free_all();
microdesc_free_all();
if (!postfork) {
config_free_all();
@@ -2045,7 +2287,7 @@ tor_free_all(int postfork)
void
tor_cleanup(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->command == CMD_RUN_TOR) {
time_t now = time(NULL);
/* Remove our pid file. We don't care if there was an error when we
diff --git a/src/or/main.h b/src/or/main.h
index 0551f7aaf..db251356f 100644
--- a/src/or/main.h
+++ b/src/or/main.h
@@ -14,7 +14,9 @@
extern int can_complete_circuit;
-int connection_add(connection_t *conn);
+int connection_add_impl(connection_t *conn, int is_connecting);
+#define connection_add(conn) connection_add_impl((conn), 0)
+#define connection_add_connecting(conn) connection_add_impl((conn), 1)
int connection_remove(connection_t *conn);
void connection_unregister_events(connection_t *conn);
int connection_in_array(connection_t *conn);
@@ -22,10 +24,13 @@ void add_connection_to_closeable_list(connection_t *conn);
int connection_is_on_closeable_list(connection_t *conn);
smartlist_t *get_connection_array(void);
+uint64_t get_bytes_read(void);
+uint64_t get_bytes_written(void);
/** Bitmask for events that we can turn on and off with
* connection_watch_events. */
typedef enum watchable_events {
+ /* Yes, it is intentional that these match Libevent's EV_READ and EV_WRITE */
READ_EVENT=0x02, /**< We want to know when a connection is readable */
WRITE_EVENT=0x04 /**< We want to know when a connection is writable */
} watchable_events_t;
@@ -46,10 +51,12 @@ void directory_info_has_arrived(time_t now, int from_cache);
void ip_address_changed(int at_interface);
void dns_servers_relaunch_checks(void);
+long get_uptime(void);
+
void handle_signals(int is_parent);
void process_signal(uintptr_t sig);
-int try_locking(or_options_t *options, int err_if_locked);
+int try_locking(const or_options_t *options, int err_if_locked);
int have_lockfile(void);
void release_lockfile(void);
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 7c67d5144..cae31fe4c 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -3,7 +3,14 @@
#include "or.h"
#include "config.h"
+#include "directory.h"
+#include "dirserv.h"
#include "microdesc.h"
+#include "networkstatus.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
#include "routerparse.h"
/** A data structure to hold a bunch of cached microdescriptors. There are
@@ -121,15 +128,19 @@ get_microdesc_cache(void)
* ending at <b>eos</b>, and store them in <b>cache</b>. If <b>no-save</b>,
* mark them as non-writable to disk. If <b>where</b> is SAVED_IN_CACHE,
* leave their bodies as pointers to the mmap'd cache. If where is
- * <b>SAVED_NOWHERE</b>, do not allow annotations. Return a list of the added
- * microdescriptors. */
+ * <b>SAVED_NOWHERE</b>, do not allow annotations. If listed_at is positive,
+ * set the last_listed field of every microdesc to listed_at. If
+ * requested_digests is non-null, then it contains a list of digests we mean
+ * to allow, so we should reject any non-requested microdesc with a different
+ * digest, and alter the list to contain only the digests of those microdescs
+ * we didn't find.
+ * Return a newly allocated list of the added microdescriptors, or NULL */
smartlist_t *
microdescs_add_to_cache(microdesc_cache_t *cache,
const char *s, const char *eos, saved_location_t where,
- int no_save)
+ int no_save, time_t listed_at,
+ smartlist_t *requested_digests256)
{
- /*XXXX need an argument that sets last_listed as appropriate. */
-
smartlist_t *descriptors, *added;
const int allow_annotations = (where != SAVED_NOWHERE);
const int copy_body = (where != SAVED_IN_CACHE);
@@ -137,6 +148,33 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
descriptors = microdescs_parse_from_string(s, eos,
allow_annotations,
copy_body);
+ if (listed_at > 0) {
+ SMARTLIST_FOREACH(descriptors, microdesc_t *, md,
+ md->last_listed = listed_at);
+ }
+ if (requested_digests256) {
+ digestmap_t *requested; /* XXXX actuqlly we should just use a
+ digest256map */
+ requested = digestmap_new();
+ SMARTLIST_FOREACH(requested_digests256, const char *, cp,
+ digestmap_set(requested, cp, (void*)1));
+ SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) {
+ if (digestmap_get(requested, md->digest)) {
+ digestmap_set(requested, md->digest, (void*)2);
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microcdesc");
+ microdesc_free(md);
+ SMARTLIST_DEL_CURRENT(descriptors, md);
+ }
+ } SMARTLIST_FOREACH_END(md);
+ SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) {
+ if (digestmap_get(requested, cp) == (void*)2) {
+ tor_free(cp);
+ SMARTLIST_DEL_CURRENT(requested_digests256, cp);
+ }
+ } SMARTLIST_FOREACH_END(cp);
+ digestmap_free(requested, NULL);
+ }
added = microdescs_add_list_to_cache(cache, descriptors, where, no_save);
smartlist_free(descriptors);
@@ -144,7 +182,7 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
}
/* As microdescs_add_to_cache, but takes a list of micrdescriptors instead of
- * a string to encode. Frees any members of <b>descriptors</b> that it does
+ * a string to decode. Frees any members of <b>descriptors</b> that it does
* not add. */
smartlist_t *
microdescs_add_list_to_cache(microdesc_cache_t *cache,
@@ -208,6 +246,15 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
if (f)
finish_writing_to_file(open_file); /*XXX Check me.*/
+ {
+ networkstatus_t *ns = networkstatus_get_latest_consensus();
+ if (ns && ns->flavor == FLAV_MICRODESC)
+ SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md));
+ }
+
+ if (smartlist_len(added))
+ router_dir_info_changed();
+
return added;
}
@@ -247,7 +294,7 @@ microdesc_cache_reload(microdesc_cache_t *cache)
mm = cache->cache_content = tor_mmap_file(cache->cache_fname);
if (mm) {
added = microdescs_add_to_cache(cache, mm->data, mm->data+mm->size,
- SAVED_IN_CACHE, 0);
+ SAVED_IN_CACHE, 0, -1, NULL);
if (added) {
total += smartlist_len(added);
smartlist_free(added);
@@ -260,7 +307,7 @@ microdesc_cache_reload(microdesc_cache_t *cache)
cache->journal_len = (size_t) st.st_size;
added = microdescs_add_to_cache(cache, journal_content,
journal_content+st.st_size,
- SAVED_IN_JOURNAL, 0);
+ SAVED_IN_JOURNAL, 0, -1, NULL);
if (added) {
total += smartlist_len(added);
smartlist_free(added);
@@ -293,9 +340,11 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
size_t bytes_dropped = 0;
time_t now = time(NULL);
- (void) force;
- /* In 0.2.2, we let this proceed unconditionally: only authorities have
- * microdesc caches. */
+ /* If we don't know a live consensus, don't believe last_listed values: we
+ * might be starting up after being down for a while. */
+ if (! force &&
+ ! networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC))
+ return;
if (cutoff <= 0)
cutoff = now - TOLERATE_MICRODESC_AGE;
@@ -390,6 +439,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
/* log? return -1? die? coredump the universe? */
continue;
}
+ tor_assert(((size_t)size) == annotation_len + md->bodylen);
md->off = off + annotation_len;
off += size;
if (md->saved_location != SAVED_IN_CACHE) {
@@ -415,7 +465,21 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) {
tor_assert(md->saved_location == SAVED_IN_CACHE);
md->body = (char*)cache->cache_content->data + md->off;
- tor_assert(fast_memeq(md->body, "onion-key", 9));
+ if (PREDICT_UNLIKELY(
+ md->bodylen < 9 || fast_memneq(md->body, "onion-key", 9) != 0)) {
+ /* XXXX023 once bug 2022 is solved, we can kill this block and turn it
+ * into just the tor_assert(!memcmp) */
+ off_t avail = cache->cache_content->size - md->off;
+ char *bad_str;
+ tor_assert(avail >= 0);
+ bad_str = tor_strndup(md->body, MIN(128, (size_t)avail));
+ log_err(LD_BUG, "After rebuilding microdesc cache, offsets seem wrong. "
+ " At offset %d, I expected to find a microdescriptor starting "
+ " with \"onion-key\". Instead I got %s.",
+ (int)md->off, escaped(bad_str));
+ tor_free(bad_str);
+ tor_assert(fast_memeq(md->body, "onion-key", 9));
+ }
} SMARTLIST_FOREACH_END(md);
smartlist_free(wrote);
@@ -449,7 +513,7 @@ microdesc_free(microdesc_t *md)
SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp));
smartlist_free(md->family);
}
- tor_free(md->exitsummary);
+ short_policy_free(md->exit_policy);
tor_free(md);
}
@@ -491,3 +555,148 @@ microdesc_average_size(microdesc_cache_t *cache)
return (size_t)(cache->total_len_seen / cache->n_seen);
}
+/** Return a smartlist of all the sha256 digest of the microdescriptors that
+ * are listed in <b>ns</b> but not present in <b>cache</b>. Returns pointers
+ * to internals of <b>ns</b>; you should not free the members of the resulting
+ * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */
+smartlist_t *
+microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache,
+ int downloadable_only, digestmap_t *skip)
+{
+ smartlist_t *result = smartlist_create();
+ time_t now = time(NULL);
+ tor_assert(ns->flavor == FLAV_MICRODESC);
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ if (microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest))
+ continue;
+ if (downloadable_only &&
+ !download_status_is_ready(&rs->dl_status, now,
+ MAX_MICRODESC_DOWNLOAD_FAILURES))
+ continue;
+ if (skip && digestmap_get(skip, rs->descriptor_digest))
+ continue;
+ if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN))
+ continue; /* This indicates a bug somewhere XXXX023*/
+ /* XXXX Also skip if we're a noncache and wouldn't use this router.
+ * XXXX NM Microdesc
+ */
+ smartlist_add(result, rs->descriptor_digest);
+ } SMARTLIST_FOREACH_END(rs);
+ return result;
+}
+
+/** Launch download requests for mircodescriptors as appropriate.
+ *
+ * Specifically, we should launch download requests if we are configured to
+ * download mirodescriptors, and there are some microdescriptors listed the
+ * current microdesc consensus that we don't have, and either we never asked
+ * for them, or we failed to download them but we're willing to retry.
+ */
+void
+update_microdesc_downloads(time_t now)
+{
+ const or_options_t *options = get_options();
+ networkstatus_t *consensus;
+ smartlist_t *missing;
+ digestmap_t *pending;
+
+ if (should_delay_dir_fetches(options))
+ return;
+ if (directory_too_idle_to_fetch_descriptors(options, now))
+ return;
+
+ consensus = networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
+ if (!consensus)
+ return;
+
+ if (!we_fetch_microdescriptors(options))
+ return;
+
+ pending = digestmap_new();
+ list_pending_microdesc_downloads(pending);
+
+ missing = microdesc_list_missing_digest256(consensus,
+ get_microdesc_cache(),
+ 1,
+ pending);
+ digestmap_free(pending, NULL);
+
+ launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC,
+ missing, NULL, now);
+
+ smartlist_free(missing);
+}
+
+/** For every microdescriptor listed in the current microdecriptor consensus,
+ * update its last_listed field to be at least as recent as the publication
+ * time of the current microdescriptor consensus.
+ */
+void
+update_microdescs_from_networkstatus(time_t now)
+{
+ microdesc_cache_t *cache = get_microdesc_cache();
+ microdesc_t *md;
+ networkstatus_t *ns =
+ networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
+
+ if (! ns)
+ return;
+
+ tor_assert(ns->flavor == FLAV_MICRODESC);
+
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ md = microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest);
+ if (md && ns->valid_after > md->last_listed)
+ md->last_listed = ns->valid_after;
+ } SMARTLIST_FOREACH_END(rs);
+}
+
+/** Return true iff we should prefer to use microdescriptors rather than
+ * routerdescs for building circuits. */
+int
+we_use_microdescriptors_for_circuits(const or_options_t *options)
+{
+ int ret = options->UseMicrodescriptors;
+ if (ret == -1) {
+ /* UseMicrodescriptors is "auto"; we need to decide: */
+#if 0
+ /* So we decide that we'll use microdescriptors iff we are not a server */
+ ret = ! server_mode(options);
+#else
+ /* We don't use microdescs for now: not enough caches are running
+ * 0.2.3.1-alpha */
+ ret = 0;
+#endif
+ }
+ return ret;
+}
+
+/** Return true iff we should try to download microdescriptors at all. */
+int
+we_fetch_microdescriptors(const or_options_t *options)
+{
+ if (directory_caches_dir_info(options))
+ return 1;
+ return we_use_microdescriptors_for_circuits(options);
+}
+
+/** Return true iff we should try to download router descriptors at all. */
+int
+we_fetch_router_descriptors(const or_options_t *options)
+{
+ if (directory_caches_dir_info(options))
+ return 1;
+ return ! we_use_microdescriptors_for_circuits(options);
+}
+
+/** Return the consensus flavor we actually want to use to build circuits. */
+int
+usable_consensus_flavor(void)
+{
+ if (we_use_microdescriptors_for_circuits(get_options())) {
+ return FLAV_MICRODESC;
+ } else {
+ return FLAV_NS;
+ }
+}
+
diff --git a/src/or/microdesc.h b/src/or/microdesc.h
index 77ce8536b..72e4572f9 100644
--- a/src/or/microdesc.h
+++ b/src/or/microdesc.h
@@ -16,7 +16,8 @@ microdesc_cache_t *get_microdesc_cache(void);
smartlist_t *microdescs_add_to_cache(microdesc_cache_t *cache,
const char *s, const char *eos, saved_location_t where,
- int no_save);
+ int no_save, time_t listed_at,
+ smartlist_t *requested_digests256);
smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache,
smartlist_t *descriptors, saved_location_t where,
int no_save);
@@ -31,8 +32,21 @@ microdesc_t *microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache,
size_t microdesc_average_size(microdesc_cache_t *cache);
+smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns,
+ microdesc_cache_t *cache,
+ int downloadable_only,
+ digestmap_t *skip);
+
void microdesc_free(microdesc_t *md);
void microdesc_free_all(void);
+void update_microdesc_downloads(time_t now);
+void update_microdescs_from_networkstatus(time_t now);
+
+int usable_consensus_flavor(void);
+int we_fetch_microdescriptors(const or_options_t *options);
+int we_fetch_router_descriptors(const or_options_t *options);
+int we_use_microdescriptors_for_circuits(const or_options_t *options);
+
#endif
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 1aa4e4a23..2586ce6eb 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -20,7 +20,9 @@
#include "dirserv.h"
#include "dirvote.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "relay.h"
#include "router.h"
#include "routerlist.h"
@@ -44,8 +46,21 @@ static strmap_t *named_server_map = NULL;
* as unnamed for some server in the consensus. */
static strmap_t *unnamed_server_map = NULL;
-/** Most recently received and validated v3 consensus network status. */
-static networkstatus_t *current_consensus = NULL;
+/** Most recently received and validated v3 consensus network status,
+ * of whichever type we are using for our own circuits. This will be the same
+ * as one of current_ns_consensus or current_md_consensus.
+ */
+#define current_consensus \
+ (we_use_microdescriptors_for_circuits(get_options()) ? \
+ current_md_consensus : current_ns_consensus)
+
+/** Most recently received and validated v3 "ns"-flavored consensus network
+ * status. */
+static networkstatus_t *current_ns_consensus = NULL;
+
+/** Most recently received and validated v3 "microdec"-flavored consensus
+ * network status. */
+static networkstatus_t *current_md_consensus = NULL;
/** A v3 consensus networkstatus that we've received, but which we don't
* have enough certificates to be happy about. */
@@ -94,9 +109,8 @@ void
networkstatus_reset_warnings(void)
{
if (current_consensus) {
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
- rs->name_lookup_warned = 0);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ node->name_lookup_warned = 0);
}
have_warned_about_old_version = 0;
@@ -199,7 +213,7 @@ router_reload_consensus_networkstatus(void)
char *filename;
char *s;
struct stat st;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS;
int flav;
@@ -271,6 +285,7 @@ router_reload_consensus_networkstatus(void)
update_certificate_downloads(time(NULL));
routers_update_all_from_networkstatus(time(NULL), 3);
+ update_microdescs_from_networkstatus(time(NULL));
return 0;
}
@@ -469,7 +484,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
int n_bad = 0;
int n_unknown = 0;
int n_no_signature = 0;
- int n_v3_authorities = get_n_authorities(V3_AUTHORITY);
+ int n_v3_authorities = get_n_authorities(V3_DIRINFO);
int n_required = n_v3_authorities/2 + 1;
smartlist_t *need_certs_from = smartlist_create();
smartlist_t *unrecognized = smartlist_create();
@@ -540,7 +555,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest))
smartlist_add(missing_authorities, ds);
});
@@ -723,7 +738,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at,
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest)) ||
- !(trusted_dir->type & V2_AUTHORITY)) {
+ !(trusted_dir->type & V2_DIRINFO)) {
log_info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize.");
source_desc = fp;
@@ -927,10 +942,9 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member)
return tor_memcmp(key, rs->identity_digest, DIGEST_LEN);
}
-/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
- * NULL if none was found. */
+/** As networkstatus_v2_find_entry, but do not return a const pointer */
routerstatus_t *
-networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
+networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest)
{
return smartlist_bsearch(ns->entries, digest,
compare_digest_to_routerstatus_entry);
@@ -938,14 +952,29 @@ networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
* NULL if none was found. */
+const routerstatus_t *
+networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
+{
+ return networkstatus_v2_find_mutable_entry(ns, digest);
+}
+
+/** As networkstatus_find_entry, but do not return a const pointer */
routerstatus_t *
-networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
+networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest)
{
return smartlist_bsearch(ns->routerstatus_list, digest,
compare_digest_to_routerstatus_entry);
}
-/*XXXX make this static once functions are moved into this file. */
+/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
+ * NULL if none was found. */
+const routerstatus_t *
+networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
+{
+ return networkstatus_vote_find_mutable_entry(ns, digest);
+}
+
+/*XXXX MOVE make this static once functions are moved into this file. */
/** Search the routerstatuses in <b>ns</b> for one whose identity digest is
* <b>digest</b>. Return value and set *<b>found_out</b> as for
* smartlist_bsearch_idx(). */
@@ -967,22 +996,37 @@ networkstatus_get_v2_list(void)
return networkstatus_v2_list;
}
-/** Return the consensus view of the status of the router whose current
- * <i>descriptor</i> digest is <b>digest</b>, or NULL if no such router is
- * known. */
+/* As router_get_consensus_status_by_descriptor_digest, but does not return
+ * a const pointer */
routerstatus_t *
-router_get_consensus_status_by_descriptor_digest(const char *digest)
+router_get_mutable_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest)
{
- if (!current_consensus) return NULL;
- if (!current_consensus->desc_digest_map) {
- digestmap_t * m = current_consensus->desc_digest_map = digestmap_new();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
+ if (!consensus)
+ consensus = current_consensus;
+ if (!consensus)
+ return NULL;
+ if (!consensus->desc_digest_map) {
+ digestmap_t *m = consensus->desc_digest_map = digestmap_new();
+ SMARTLIST_FOREACH(consensus->routerstatus_list,
routerstatus_t *, rs,
{
digestmap_set(m, rs->descriptor_digest, rs);
});
}
- return digestmap_get(current_consensus->desc_digest_map, digest);
+ return digestmap_get(consensus->desc_digest_map, digest);
+}
+
+/** Return the consensus view of the status of the router whose current
+ * <i>descriptor</i> digest in <b>consensus</b> is <b>digest</b>, or NULL if
+ * no such router is known. */
+const routerstatus_t *
+router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
+ const char *digest)
+{
+ return router_get_mutable_consensus_status_by_descriptor_digest(
+ consensus, digest);
}
/** Given the digest of a router descriptor, return its current download
@@ -991,7 +1035,10 @@ download_status_t *
router_get_dl_status_by_descriptor_digest(const char *d)
{
routerstatus_t *rs;
- if ((rs = router_get_consensus_status_by_descriptor_digest(d)))
+ if (!current_ns_consensus)
+ return NULL;
+ if ((rs = router_get_mutable_consensus_status_by_descriptor_digest(
+ current_ns_consensus, d)))
return &rs->dl_status;
if (v2_download_status_map)
return digestmap_get(v2_download_status_map, d);
@@ -999,10 +1046,9 @@ router_get_dl_status_by_descriptor_digest(const char *d)
return NULL;
}
-/** Return the consensus view of the status of the router whose identity
- * digest is <b>digest</b>, or NULL if we don't know about any such router. */
+/** As router_get_consensus_status_by_id, but do not return a const pointer */
routerstatus_t *
-router_get_consensus_status_by_id(const char *digest)
+router_get_mutable_consensus_status_by_id(const char *digest)
{
if (!current_consensus)
return NULL;
@@ -1010,100 +1056,27 @@ router_get_consensus_status_by_id(const char *digest)
compare_digest_to_routerstatus_entry);
}
+/** Return the consensus view of the status of the router whose identity
+ * digest is <b>digest</b>, or NULL if we don't know about any such router. */
+const routerstatus_t *
+router_get_consensus_status_by_id(const char *digest)
+{
+ return router_get_mutable_consensus_status_by_id(digest);
+}
+
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
* the corresponding routerstatus_t, or NULL if none exists. Warn the
* user if <b>warn_if_unnamed</b> is set, and they have specified a router by
* nickname, but the Named flag isn't set for that router. */
-routerstatus_t *
+const routerstatus_t *
router_get_consensus_status_by_nickname(const char *nickname,
int warn_if_unnamed)
{
- char digest[DIGEST_LEN];
- routerstatus_t *best=NULL;
- smartlist_t *matches=NULL;
- const char *named_id=NULL;
-
- if (!current_consensus || !nickname)
- return NULL;
-
- /* Is this name really a hexadecimal identity digest? */
- if (nickname[0] == '$') {
- if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
- return NULL;
- return networkstatus_vote_find_entry(current_consensus, digest);
- } else if (strlen(nickname) == HEX_DIGEST_LEN &&
- (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
- return networkstatus_vote_find_entry(current_consensus, digest);
- }
-
- /* Is there a server that is Named with this name? */
- if (named_server_map)
- named_id = strmap_get_lc(named_server_map, nickname);
- if (named_id)
- return networkstatus_vote_find_entry(current_consensus, named_id);
-
- /* Okay; is this name listed as Unnamed? */
- if (unnamed_server_map &&
- strmap_get_lc(unnamed_server_map, nickname)) {
- log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
- "canonical name of any server we know.", escaped(nickname));
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->rs;
+ else
return NULL;
- }
-
- /* This name is not canonical for any server; go through the list and
- * see who it matches. */
- /*XXXX This is inefficient; optimize it if it matters. */
- matches = smartlist_create();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, lrs,
- {
- if (!strcasecmp(lrs->nickname, nickname)) {
- if (lrs->is_named) {
- tor_fragile_assert() /* This should never happen. */
- smartlist_free(matches);
- return lrs;
- } else {
- if (lrs->is_unnamed) {
- tor_fragile_assert(); /* nor should this. */
- smartlist_clear(matches);
- best=NULL;
- break;
- }
- smartlist_add(matches, lrs);
- best = lrs;
- }
- }
- });
-
- if (smartlist_len(matches)>1 && warn_if_unnamed) {
- int any_unwarned=0;
- SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
- {
- if (! lrs->name_lookup_warned) {
- lrs->name_lookup_warned=1;
- any_unwarned=1;
- }
- });
- if (any_unwarned) {
- log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
- " but none is listed as named by the directory authorities. "
- "Choosing one arbitrarily.", nickname);
- }
- } else if (warn_if_unnamed && best && !best->name_lookup_warned) {
- char fp[HEX_DIGEST_LEN+1];
- base16_encode(fp, sizeof(fp),
- best->identity_digest, DIGEST_LEN);
- log_warn(LD_CONFIG,
- "When looking up a status, you specified a server \"%s\" by name, "
- "but the directory authorities do not have any key registered for "
- "this nickname -- so it could be used by any server, "
- "not just the one you meant. "
- "To make sure you get the same server in the future, refer to "
- "it by key, as \"$%s\".", nickname, fp);
- best->name_lookup_warned = 1;
- }
- smartlist_free(matches);
- return best;
}
/** Return the identity digest that's mapped to officially by
@@ -1159,7 +1132,7 @@ update_v2_networkstatus_cache_downloads(time_t now)
{
char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
tor_addr_t addr;
- if (!(ds->type & V2_AUTHORITY))
+ if (!(ds->type & V2_DIRINFO))
continue;
if (router_digest_is_me(ds->digest))
continue;
@@ -1200,6 +1173,25 @@ update_v2_networkstatus_cache_downloads(time_t now)
}
}
+/** DOCDOC */
+static int
+we_want_to_fetch_flavor(const or_options_t *options, int flavor)
+{
+ if (flavor < 0 || flavor > N_CONSENSUS_FLAVORS) {
+ /* This flavor is crazy; we don't want it */
+ /*XXXX handle unrecognized flavors later */
+ return 0;
+ }
+ if (authdir_mode_v3(options) || directory_caches_dir_info(options)) {
+ /* We want to serve all flavors to others, regardless if we would use
+ * it ourselves. */
+ return 1;
+ }
+ /* Otherwise, we want the flavor only if we want to use it to build
+ * circuits. */
+ return flavor == usable_consensus_flavor();
+}
+
/** How many times will we try to fetch a consensus before we give up? */
#define CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES 8
/** How long will we hang onto a possibly live consensus for which we're
@@ -1212,48 +1204,65 @@ static void
update_consensus_networkstatus_downloads(time_t now)
{
int i;
+ const or_options_t *options = get_options();
+
if (!networkstatus_get_live_consensus(now))
time_to_download_next_consensus = now; /* No live consensus? Get one now!*/
if (time_to_download_next_consensus > now)
return; /* Wait until the current consensus is older. */
- /* XXXXNM Microdescs: may need to download more types. */
- if (!download_status_is_ready(&consensus_dl_status[FLAV_NS], now,
- CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
- return; /* We failed downloading a consensus too recently. */
- if (connection_get_by_type_purpose(CONN_TYPE_DIR,
- DIR_PURPOSE_FETCH_CONSENSUS))
- return; /* There's an in-progress download.*/
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
- consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i];
+ /* XXXX need some way to download unknown flavors if we are caching. */
+ const char *resource;
+ consensus_waiting_for_certs_t *waiting;
+
+ if (! we_want_to_fetch_flavor(options, i))
+ continue;
+
+ resource = networkstatus_get_flavor_name(i);
+
+ if (!download_status_is_ready(&consensus_dl_status[i], now,
+ CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
+ continue; /* We failed downloading a consensus too recently. */
+ if (connection_dir_get_by_purpose_and_resource(
+ DIR_PURPOSE_FETCH_CONSENSUS, resource))
+ continue; /* There's an in-progress download.*/
+
+ waiting = &consensus_waiting_for_certs[i];
if (waiting->consensus) {
/* XXXX make sure this doesn't delay sane downloads. */
- if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now)
- return; /* We're still getting certs for this one. */
- else {
+ if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now) {
+ continue; /* We're still getting certs for this one. */
+ } else {
if (!waiting->dl_failed) {
- download_status_failed(&consensus_dl_status[FLAV_NS], 0);
+ download_status_failed(&consensus_dl_status[i], 0);
waiting->dl_failed=1;
}
}
}
- }
- log_info(LD_DIR, "Launching networkstatus consensus download.");
- directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
- ROUTER_PURPOSE_GENERAL, NULL,
- PDS_RETRY_IF_NO_SERVERS);
+ log_info(LD_DIR, "Launching %s networkstatus consensus download.",
+ networkstatus_get_flavor_name(i));
+
+ directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
+ ROUTER_PURPOSE_GENERAL, resource,
+ PDS_RETRY_IF_NO_SERVERS);
+ }
}
/** Called when an attempt to download a consensus fails: note that the
* failure occurred, and possibly retry. */
void
-networkstatus_consensus_download_failed(int status_code)
+networkstatus_consensus_download_failed(int status_code, const char *flavname)
{
- /* XXXXNM Microdescs: may need to handle more types. */
- download_status_failed(&consensus_dl_status[FLAV_NS], status_code);
- /* Retry immediately, if appropriate. */
- update_consensus_networkstatus_downloads(time(NULL));
+ int flav = networkstatus_parse_flavor_name(flavname);
+ if (flav >= 0) {
+ tor_assert(flav < N_CONSENSUS_FLAVORS);
+ /* XXXX handle unrecognized flavors */
+ download_status_failed(&consensus_dl_status[flav], status_code);
+ /* Retry immediately, if appropriate. */
+ update_consensus_networkstatus_downloads(time(NULL));
+ }
}
/** How long do we (as a cache) wait after a consensus becomes non-fresh
@@ -1265,7 +1274,7 @@ networkstatus_consensus_download_failed(int status_code)
void
update_consensus_networkstatus_fetch_time(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *c = networkstatus_get_live_consensus(now);
if (c) {
long dl_interval;
@@ -1339,7 +1348,7 @@ update_consensus_networkstatus_fetch_time(time_t now)
* fetches yet (e.g. we demand bridges and none are yet known).
* Else return 0. */
int
-should_delay_dir_fetches(or_options_t *options)
+should_delay_dir_fetches(const or_options_t *options)
{
if (options->UseBridges && !any_bridge_descriptors_known()) {
log_info(LD_DIR, "delaying dir fetches (no running bridges known)");
@@ -1353,7 +1362,7 @@ should_delay_dir_fetches(or_options_t *options)
void
update_networkstatus_downloads(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (should_delay_dir_fetches(options))
return;
if (authdir_mode_any_main(options) || options->FetchV2Networkstatus)
@@ -1374,7 +1383,10 @@ update_certificate_downloads(time_t now)
now);
}
- authority_certs_fetch_missing(current_consensus, now);
+ if (current_ns_consensus)
+ authority_certs_fetch_missing(current_ns_consensus, now);
+ if (current_md_consensus)
+ authority_certs_fetch_missing(current_md_consensus, now);
}
/** Return 1 if we have a consensus but we don't have enough certificates
@@ -1382,7 +1394,7 @@ update_certificate_downloads(time_t now)
int
consensus_is_waiting_for_certs(void)
{
- return consensus_waiting_for_certs[USABLE_CONSENSUS_FLAVOR].consensus
+ return consensus_waiting_for_certs[usable_consensus_flavor()].consensus
? 1 : 0;
}
@@ -1406,6 +1418,18 @@ networkstatus_get_latest_consensus(void)
return current_consensus;
}
+/** DOCDOC */
+networkstatus_t *
+networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
+{
+ if (f == FLAV_NS)
+ return current_ns_consensus;
+ else if (f == FLAV_MICRODESC)
+ return current_md_consensus;
+ else
+ tor_assert(0);
+}
+
/** Return the most recent consensus that we have downloaded, or NULL if it is
* no longer live. */
networkstatus_t *
@@ -1425,13 +1449,15 @@ networkstatus_get_live_consensus(time_t now)
/** As networkstatus_get_live_consensus(), but is way more tolerant of expired
* consensuses. */
networkstatus_t *
-networkstatus_get_reasonably_live_consensus(time_t now)
+networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
{
#define REASONABLY_LIVE_TIME (24*60*60)
- if (current_consensus &&
- current_consensus->valid_after <= now &&
- now <= current_consensus->valid_until+REASONABLY_LIVE_TIME)
- return current_consensus;
+ networkstatus_t *consensus =
+ networkstatus_get_latest_consensus_by_flavor(flavor);
+ if (consensus &&
+ consensus->valid_after <= now &&
+ now <= consensus->valid_until+REASONABLY_LIVE_TIME)
+ return consensus;
else
return NULL;
}
@@ -1452,7 +1478,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
a->is_exit != b->is_exit ||
a->is_stable != b->is_stable ||
a->is_fast != b->is_fast ||
- a->is_running != b->is_running ||
+ a->is_flagged_running != b->is_flagged_running ||
a->is_named != b->is_named ||
a->is_unnamed != b->is_unnamed ||
a->is_valid != b->is_valid ||
@@ -1493,13 +1519,14 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
}
changed = smartlist_create();
- SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
- new_c->routerstatus_list, routerstatus_t *, rs_new,
- tor_memcmp(rs_old->identity_digest,
- rs_new->identity_digest, DIGEST_LEN),
- smartlist_add(changed, rs_new)) {
+ SMARTLIST_FOREACH_JOIN(
+ old_c->routerstatus_list, const routerstatus_t *, rs_old,
+ new_c->routerstatus_list, const routerstatus_t *, rs_new,
+ tor_memcmp(rs_old->identity_digest,
+ rs_new->identity_digest, DIGEST_LEN),
+ smartlist_add(changed, (void*) rs_new)) {
if (routerstatus_has_changed(rs_old, rs_new))
- smartlist_add(changed, rs_new);
+ smartlist_add(changed, (void*)rs_new);
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
control_event_networkstatus_changed(changed);
@@ -1523,7 +1550,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->identity_digest, DIGEST_LEN),
STMT_NIL) {
/* Okay, so we're looking at the same identity. */
- rs_new->name_lookup_warned = rs_old->name_lookup_warned;
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
@@ -1559,7 +1585,7 @@ networkstatus_set_current_consensus(const char *consensus,
networkstatus_t *c=NULL;
int r, result = -1;
time_t now = time(NULL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *unverified_fname = NULL, *consensus_fname = NULL;
int flav = networkstatus_parse_flavor_name(flavor);
const unsigned from_cache = flags & NSSET_FROM_CACHE;
@@ -1597,7 +1623,7 @@ networkstatus_set_current_consensus(const char *consensus,
flavor = networkstatus_get_flavor_name(flav);
}
- if (flav != USABLE_CONSENSUS_FLAVOR &&
+ if (flav != usable_consensus_flavor() &&
!directory_caches_dir_info(options)) {
/* This consensus is totally boring to us: we won't use it, and we won't
* serve it. Drop it. */
@@ -1616,9 +1642,16 @@ networkstatus_set_current_consensus(const char *consensus,
if (!strcmp(flavor, "ns")) {
consensus_fname = get_datadir_fname("cached-consensus");
unverified_fname = get_datadir_fname("unverified-consensus");
- if (current_consensus) {
- current_digests = &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 +1728,36 @@ networkstatus_set_current_consensus(const char *consensus,
}
}
- if (!from_cache && flav == USABLE_CONSENSUS_FLAVOR)
+ if (!from_cache && flav == usable_consensus_flavor())
control_event_client_status(LOG_NOTICE, "CONSENSUS_ARRIVED");
/* Are we missing any certificates at all? */
if (r != 1 && dl_certs)
authority_certs_fetch_missing(c, now);
- if (flav == USABLE_CONSENSUS_FLAVOR) {
+ if (flav == usable_consensus_flavor()) {
notify_control_networkstatus_changed(current_consensus, c);
-
- if (current_consensus) {
- networkstatus_copy_old_consensus_info(c, current_consensus);
- networkstatus_vote_free(current_consensus);
+ }
+ if (flav == FLAV_NS) {
+ if (current_ns_consensus) {
+ networkstatus_copy_old_consensus_info(c, current_ns_consensus);
+ networkstatus_vote_free(current_ns_consensus);
/* Defensive programming : we should set current_consensus very soon,
* but we're about to call some stuff in the meantime, and leaving this
* dangling pointer around has proven to be trouble. */
- current_consensus = NULL;
+ current_ns_consensus = NULL;
+ }
+ current_ns_consensus = c;
+ free_consensus = 0; /* avoid free */
+ } else if (flav == FLAV_MICRODESC) {
+ if (current_md_consensus) {
+ networkstatus_copy_old_consensus_info(c, current_md_consensus);
+ networkstatus_vote_free(current_md_consensus);
+ /* more defensive programming */
+ current_md_consensus = NULL;
}
+ current_md_consensus = c;
+ free_consensus = 0; /* avoid free */
}
waiting = &consensus_waiting_for_certs[flav];
@@ -1737,12 +1782,12 @@ networkstatus_set_current_consensus(const char *consensus,
download_status_failed(&consensus_dl_status[flav], 0);
}
- if (flav == USABLE_CONSENSUS_FLAVOR) {
- current_consensus = c;
- free_consensus = 0; /* Prevent free. */
-
- /* XXXXNM Microdescs: needs a non-ns variant. */
+ if (flav == usable_consensus_flavor()) {
+ /* XXXXNM Microdescs: needs a non-ns variant. ???? NM*/
update_consensus_networkstatus_fetch_time(now);
+
+ nodelist_set_consensus(current_consensus);
+
dirvote_recalculate_timing(options, now);
routerstatus_list_update_named_server_map();
cell_ewma_set_scale_factor(options, current_consensus);
@@ -1769,11 +1814,11 @@ networkstatus_set_current_consensus(const char *consensus,
* valid-after time, declare that our clock is skewed. */
#define EARLY_CONSENSUS_NOTICE_SKEW 60
- if (now < current_consensus->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) {
+ if (now < c->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) {
char tbuf[ISO_TIME_LEN+1];
char dbuf[64];
- long delta = now - current_consensus->valid_after;
- format_iso_time(tbuf, current_consensus->valid_after);
+ long delta = now - c->valid_after;
+ format_iso_time(tbuf, c->valid_after);
format_time_interval(dbuf, sizeof(dbuf), delta);
log_warn(LD_GENERAL, "Our clock is %s behind the time published in the "
"consensus network status document (%s GMT). Tor needs an "
@@ -1824,7 +1869,8 @@ void
routers_update_all_from_networkstatus(time_t now, int dir_version)
{
routerlist_t *rl = router_get_routerlist();
- networkstatus_t *consensus = networkstatus_get_live_consensus(now);
+ networkstatus_t *consensus = networkstatus_get_reasonably_live_consensus(now,
+ FLAV_NS);
if (networkstatus_v2_list_has_changed)
download_status_map_update_from_v2_networkstatus();
@@ -1896,7 +1942,7 @@ download_status_map_update_from_v2_networkstatus(void)
dl_status = digestmap_new();
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
- SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
+ SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) {
const char *d = rs->descriptor_digest;
download_status_t *s;
if (digestmap_get(dl_status, d))
@@ -1924,7 +1970,8 @@ routerstatus_list_update_named_server_map(void)
named_server_map = strmap_new();
strmap_free(unnamed_server_map, NULL);
unnamed_server_map = strmap_new();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs,
+ SMARTLIST_FOREACH(current_consensus->routerstatus_list,
+ const routerstatus_t *, rs,
{
if (rs->is_named) {
strmap_set_lc(named_server_map, rs->nickname,
@@ -1944,9 +1991,8 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures)
{
trusted_dir_server_t *ds;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
- int namingdir = authdir && options->NamingAuthoritativeDir;
networkstatus_t *ns = current_consensus;
if (!ns || !smartlist_len(ns->routerstatus_list))
return;
@@ -1960,25 +2006,19 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
tor_memcmp(rs->identity_digest,
router->cache_info.identity_digest, DIGEST_LEN),
{
+#if 0
/* We have no routerstatus for this router. Clear flags and skip it. */
- if (!namingdir)
- router->is_named = 0;
if (!authdir) {
if (router->purpose == ROUTER_PURPOSE_GENERAL)
router_clear_status_flags(router);
}
+#endif
}) {
/* We have a routerstatus for this router. */
const char *digest = router->cache_info.identity_digest;
ds = router_get_trusteddirserver_by_digest(digest);
- if (!namingdir) {
- if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
- router->is_named = 1;
- else
- router->is_named = 0;
- }
/* Is it the same descriptor, or only the same identity? */
if (tor_memeq(router->cache_info.signed_descriptor_digest,
rs->descriptor_digest, DIGEST_LEN)) {
@@ -1986,28 +2026,17 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
router->cache_info.last_listed_as_valid_until = ns->valid_until;
}
- if (!authdir) {
- /* If we're not an authdir, believe others. */
- router->is_valid = rs->is_valid;
- router->is_running = rs->is_running;
- router->is_fast = rs->is_fast;
- router->is_stable = rs->is_stable;
- router->is_possible_guard = rs->is_possible_guard;
- router->is_exit = rs->is_exit;
- router->is_bad_directory = rs->is_bad_directory;
- router->is_bad_exit = rs->is_bad_exit;
- router->is_hs_dir = rs->is_hs_dir;
- } else {
+ if (authdir) {
/* If we _are_ an authority, we should check whether this router
* is one that will cause us to need a reachability test. */
routerinfo_t *old_router =
- router_get_by_digest(router->cache_info.identity_digest);
+ router_get_mutable_by_digest(router->cache_info.identity_digest);
if (old_router != router) {
router->needs_retest_if_added =
dirserv_should_launch_reachability_test(router, old_router);
}
}
- if (router->is_running && ds) {
+ if (rs->is_flagged_running && ds) {
download_status_reset(&ds->v2_ns_dl_status);
}
if (reset_failures) {
@@ -2016,10 +2045,9 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
} SMARTLIST_FOREACH_JOIN_END(rs, router);
/* Now update last_listed_as_valid_until from v2 networkstatuses. */
- /* XXXX If this is slow, we need to rethink the code. */
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, {
time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
- SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
+ SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs,
routers, routerinfo_t *, ri,
tor_memcmp(rs->identity_digest,
ri->cache_info.identity_digest, DIGEST_LEN),
@@ -2040,7 +2068,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
void
signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
{
- networkstatus_t *ns = current_consensus;
+ networkstatus_t *ns = current_ns_consensus;
if (!ns)
return;
@@ -2048,11 +2076,11 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
char dummy[DIGEST_LEN];
/* instantiates the digest map. */
memset(dummy, 0, sizeof(dummy));
- router_get_consensus_status_by_descriptor_digest(dummy);
+ router_get_consensus_status_by_descriptor_digest(ns, dummy);
}
SMARTLIST_FOREACH(descs, signed_descriptor_t *, d,
{
- routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
+ const routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
d->signed_descriptor_digest);
if (rs) {
if (ns->valid_until > d->last_listed_as_valid_until)
@@ -2065,7 +2093,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
* return the result in a newly allocated string. Used only by controller
* interface (for now.) */
char *
-networkstatus_getinfo_helper_single(routerstatus_t *rs)
+networkstatus_getinfo_helper_single(const routerstatus_t *rs)
{
char buf[RS_ENTRY_LEN+1];
routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT);
@@ -2098,6 +2126,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
statuses = smartlist_create();
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
if (ri->cache_info.published_on < cutoff)
continue;
if (ri->purpose != purpose)
@@ -2105,7 +2136,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
dirserv_set_router_is_running(ri, now);
/* then generate and write out status lines for each of them */
- set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0);
+ set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0);
smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
});
@@ -2120,7 +2151,7 @@ void
networkstatus_dump_bridge_status_to_file(time_t now)
{
char *status = networkstatus_getinfo_by_purpose("bridge", now);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
size_t len = strlen(options->DataDirectory) + 32;
char *fname = tor_malloc(len);
tor_snprintf(fname, len, "%s"PATH_SEPARATOR"networkstatus-bridges",
@@ -2174,7 +2205,7 @@ get_net_param_from_list(smartlist_t *net_params, const char *param_name,
* <b>min_val</b> and at most <b>max_val</b> and raise/cap the parsed value
* if necessary. */
int32_t
-networkstatus_get_param(networkstatus_t *ns, const char *param_name,
+networkstatus_get_param(const networkstatus_t *ns, const char *param_name,
int32_t default_val, int32_t min_val, int32_t max_val)
{
if (!ns) /* if they pass in null, go find it ourselves */
@@ -2253,7 +2284,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg)
{
- routerstatus_t *status;
+ const routerstatus_t *status;
(void) conn;
if (!current_consensus) {
@@ -2264,7 +2295,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
if (!strcmp(question, "ns/all")) {
smartlist_t *statuses = smartlist_create();
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
+ const routerstatus_t *, rs,
{
smartlist_add(statuses, networkstatus_getinfo_helper_single(rs));
});
@@ -2308,8 +2339,9 @@ networkstatus_free_all(void)
digestmap_free(v2_download_status_map, _tor_free);
v2_download_status_map = NULL;
- networkstatus_vote_free(current_consensus);
- current_consensus = NULL;
+ networkstatus_vote_free(current_ns_consensus);
+ networkstatus_vote_free(current_md_consensus);
+ current_md_consensus = current_ns_consensus = NULL;
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i];
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index ec2e8f884..1b10f2738 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -38,31 +38,46 @@ int router_set_networkstatus_v2(const char *s, time_t arrived_at,
void networkstatus_v2_list_clean(time_t now);
int compare_digest_to_routerstatus_entry(const void *_key,
const void **_member);
-routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
+const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
const char *digest);
-routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
+const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
+ const char *digest);
+routerstatus_t *networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns,
+ const char *digest);
+routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
const smartlist_t *networkstatus_get_v2_list(void);
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
-routerstatus_t *router_get_consensus_status_by_id(const char *digest);
-routerstatus_t *router_get_consensus_status_by_descriptor_digest(
- const char *digest);
-routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
- int warn_if_unnamed);
+const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
+routerstatus_t *router_get_mutable_consensus_status_by_id(
+ const char *digest);
+const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest);
+routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest);
+const routerstatus_t *router_get_consensus_status_by_nickname(
+ const char *nickname,
+ int warn_if_unnamed);
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
int networkstatus_nickname_is_unnamed(const char *nickname);
-void networkstatus_consensus_download_failed(int status_code);
+void networkstatus_consensus_download_failed(int status_code,
+ const char *flavname);
void update_consensus_networkstatus_fetch_time(time_t now);
-int should_delay_dir_fetches(or_options_t *options);
+int should_delay_dir_fetches(const or_options_t *options);
void update_networkstatus_downloads(time_t now);
void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_t *networkstatus_get_latest_consensus(void);
+networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
+ consensus_flavor_t f);
networkstatus_t *networkstatus_get_live_consensus(time_t now);
-networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now);
+networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
+ int flavor);
#define NSSET_FROM_CACHE 1
#define NSSET_WAS_WAITING_FOR_CERTS 2
#define NSSET_DONT_DOWNLOAD_CERTS 4
@@ -78,10 +93,11 @@ void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
void signed_descs_update_status_from_consensus_networkstatus(
smartlist_t *descs);
-char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
+char *networkstatus_getinfo_helper_single(const routerstatus_t *rs);
char *networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now);
void networkstatus_dump_bridge_status_to_file(time_t now);
-int32_t networkstatus_get_param(networkstatus_t *ns, const char *param_name,
+int32_t networkstatus_get_param(const networkstatus_t *ns,
+ const char *param_name,
int32_t default_val, int32_t min_val,
int32_t max_val);
int getinfo_helper_networkstatus(control_connection_t *conn,
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
new file mode 100644
index 000000000..96b65a132
--- /dev/null
+++ b/src/or/nodelist.c
@@ -0,0 +1,735 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "config.h"
+#include "dirserv.h"
+#include "microdesc.h"
+#include "networkstatus.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
+
+#include <string.h>
+
+static void nodelist_drop_node(node_t *node, int remove_from_ht);
+static void node_free(node_t *node);
+
+/** A nodelist_t holds a node_t object for every router we're "willing to use
+ * for something". Specifically, it should hold a node_t for every node that
+ * is currently in the routerlist, or currently in the consensus we're using.
+ */
+typedef struct nodelist_t {
+ /* A list of all the nodes. */
+ smartlist_t *nodes;
+ /* Hash table to map from node ID digest to node. */
+ HT_HEAD(nodelist_map, node_t) nodes_by_id;
+
+} nodelist_t;
+
+static INLINE unsigned int
+node_id_hash(const node_t *node)
+{
+#if SIZEOF_INT == 4
+ const uint32_t *p = (const uint32_t*)node->identity;
+ return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
+#elif SIZEOF_INT == 8
+ const uint64_t *p = (const uint32_t*)node->identity;
+ const uint32_t *p32 = (const uint32_t*)node->identity;
+ return p[0] ^ p[1] ^ p32[4];
+#endif
+}
+
+static INLINE unsigned int
+node_id_eq(const node_t *node1, const node_t *node2)
+{
+ return tor_memeq(node1->identity, node2->identity, DIGEST_LEN);
+}
+
+HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq);
+HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq,
+ 0.6, malloc, realloc, free);
+
+/** The global nodelist. */
+static nodelist_t *the_nodelist=NULL;
+
+/** Create an empty nodelist if we haven't done so already. */
+static void
+init_nodelist(void)
+{
+ if (PREDICT_UNLIKELY(the_nodelist == NULL)) {
+ the_nodelist = tor_malloc_zero(sizeof(nodelist_t));
+ HT_INIT(nodelist_map, &the_nodelist->nodes_by_id);
+ the_nodelist->nodes = smartlist_create();
+ }
+}
+
+/** As node_get_by_id, but returns a non-const pointer */
+node_t *
+node_get_mutable_by_id(const char *identity_digest)
+{
+ node_t search, *node;
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return NULL;
+
+ memcpy(&search.identity, identity_digest, DIGEST_LEN);
+ node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search);
+ return node;
+}
+
+/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
+ * if no such node exists. */
+const node_t *
+node_get_by_id(const char *identity_digest)
+{
+ return node_get_mutable_by_id(identity_digest);
+}
+
+/** Internal: return the node_t whose identity_digest is
+ * <b>identity_digest</b>. If none exists, create a new one, add it to the
+ * nodelist, and return it.
+ *
+ * Requires that the nodelist be initialized.
+ */
+static node_t *
+node_get_or_create(const char *identity_digest)
+{
+ node_t *node;
+
+ if ((node = node_get_mutable_by_id(identity_digest)))
+ return node;
+
+ node = tor_malloc_zero(sizeof(node_t));
+ memcpy(node->identity, identity_digest, DIGEST_LEN);
+ HT_INSERT(nodelist_map, &the_nodelist->nodes_by_id, node);
+
+ smartlist_add(the_nodelist->nodes, node);
+ node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1;
+
+ node->country = -1;
+
+ return node;
+}
+
+/** Add <b>ri</b> to the nodelist. */
+node_t *
+nodelist_add_routerinfo(routerinfo_t *ri)
+{
+ node_t *node;
+ init_nodelist();
+ node = node_get_or_create(ri->cache_info.identity_digest);
+ node->ri = ri;
+
+ if (node->country == -1)
+ node_set_country(node);
+
+ if (authdir_mode(get_options())) {
+ const char *discard=NULL;
+ uint32_t status = dirserv_router_get_status(ri, &discard);
+ dirserv_set_node_flags_from_authoritative_status(node, status);
+ }
+
+ return node;
+}
+
+/** Set the appropriate node_t to use <b>md</b> as its microdescriptor.
+ *
+ * Called when a new microdesc has arrived and the usable consensus flavor
+ * is "microdesc".
+ **/
+node_t *
+nodelist_add_microdesc(microdesc_t *md)
+{
+ networkstatus_t *ns =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ const routerstatus_t *rs;
+ node_t *node;
+ if (ns == NULL)
+ return NULL;
+ init_nodelist();
+
+ /* Microdescriptors don't carry an identity digest, so we need to figure
+ * it out by looking up the routerstatus. */
+ rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
+ if (rs == NULL)
+ return NULL;
+ node = node_get_mutable_by_id(rs->identity_digest);
+ if (node)
+ node->md = md;
+ return node;
+}
+
+/** Tell the nodelist that the current usable consensus to <b>ns</b>.
+ * This makes the nodelist change all of the routerstatus entries for
+ * the nodes, drop nodes that no longer have enough info to get used,
+ * and grab microdescriptors into nodes as appropriate.
+ */
+void
+nodelist_set_consensus(networkstatus_t *ns)
+{
+ const or_options_t *options = get_options();
+ int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
+ init_nodelist();
+
+ SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
+ node->rs = NULL);
+
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ node_t *node = node_get_or_create(rs->identity_digest);
+ node->rs = rs;
+ if (ns->flavor == FLAV_MICRODESC) {
+ if (node->md == NULL ||
+ tor_memneq(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) {
+ node->md = microdesc_cache_lookup_by_digest256(NULL,
+ rs->descriptor_digest);
+ }
+ }
+
+ node_set_country(node);
+
+ /* If we're not an authdir, believe others. */
+ if (!authdir) {
+ node->is_valid = rs->is_valid;
+ node->is_running = rs->is_flagged_running;
+ node->is_fast = rs->is_fast;
+ node->is_stable = rs->is_stable;
+ node->is_possible_guard = rs->is_possible_guard;
+ node->is_exit = rs->is_exit;
+ node->is_bad_directory = rs->is_bad_directory;
+ node->is_bad_exit = rs->is_bad_exit;
+ node->is_hs_dir = rs->is_hs_dir;
+ }
+
+ } SMARTLIST_FOREACH_END(rs);
+
+ nodelist_purge();
+
+ if (! authdir) {
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ /* We have no routerstatus for this router. Clear flags so we can skip
+ * it, maybe.*/
+ if (!node->rs) {
+ tor_assert(node->ri); /* if it had only an md, or nothing, purge
+ * would have removed it. */
+ if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) {
+ /* Clear all flags. */
+ node->is_valid = node->is_running = node->is_hs_dir =
+ node->is_fast = node->is_stable =
+ node->is_possible_guard = node->is_exit =
+ node->is_bad_exit = node->is_bad_directory = 0;
+ }
+ }
+ } SMARTLIST_FOREACH_END(node);
+ }
+}
+
+/** Helper: return true iff a node has a usable amount of information*/
+static INLINE int
+node_is_usable(const node_t *node)
+{
+ return (node->rs) || (node->ri);
+}
+
+/** Tell the nodelist that <b>md</b> is no longer a microdescriptor for the
+ * node with <b>identity_digest</b>. */
+void
+nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
+{
+ node_t *node = node_get_mutable_by_id(identity_digest);
+ if (node && node->md == md)
+ node->md = NULL;
+}
+
+/** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */
+void
+nodelist_remove_routerinfo(routerinfo_t *ri)
+{
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (node && node->ri == ri) {
+ node->ri = NULL;
+ if (! node_is_usable(node)) {
+ nodelist_drop_node(node, 1);
+ node_free(node);
+ }
+ }
+}
+
+/** Remove <b>node</b> from the nodelist. (Asserts that it was there to begin
+ * with.) */
+static void
+nodelist_drop_node(node_t *node, int remove_from_ht)
+{
+ node_t *tmp;
+ int idx;
+ if (remove_from_ht) {
+ tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
+ tor_assert(tmp == node);
+ }
+
+ idx = node->nodelist_idx;
+ tor_assert(idx >= 0);
+
+ tor_assert(node == smartlist_get(the_nodelist->nodes, idx));
+ smartlist_del(the_nodelist->nodes, idx);
+ if (idx < smartlist_len(the_nodelist->nodes)) {
+ tmp = smartlist_get(the_nodelist->nodes, idx);
+ tmp->nodelist_idx = idx;
+ }
+ node->nodelist_idx = -1;
+}
+
+/** Release storage held by <b>node</b> */
+static void
+node_free(node_t *node)
+{
+ if (!node)
+ return;
+ tor_assert(node->nodelist_idx == -1);
+ tor_free(node);
+}
+
+/** Remove all entries from the nodelist that don't have enough info to be
+ * usable for anything. */
+void
+nodelist_purge(void)
+{
+ node_t **iter;
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return;
+
+ /* Remove the non-usable nodes. */
+ for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) {
+ node_t *node = *iter;
+
+ if (node_is_usable(node)) {
+ iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter);
+ } else {
+ iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter);
+ nodelist_drop_node(node, 0);
+ node_free(node);
+ }
+ }
+ nodelist_assert_ok();
+}
+
+/** Release all storage held by the nodelist. */
+void
+nodelist_free_all(void)
+{
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return;
+
+ HT_CLEAR(nodelist_map, &the_nodelist->nodes_by_id);
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ node->nodelist_idx = -1;
+ node_free(node);
+ } SMARTLIST_FOREACH_END(node);
+
+ smartlist_free(the_nodelist->nodes);
+
+ tor_free(the_nodelist);
+}
+
+/** Check that the nodelist is internally consistent, and consistent with
+ * the directory info it's derived from.
+ */
+void
+nodelist_assert_ok(void)
+{
+ routerlist_t *rl = router_get_routerlist();
+ networkstatus_t *ns = networkstatus_get_latest_consensus();
+ digestmap_t *dm;
+
+ if (!the_nodelist)
+ return;
+
+ dm = digestmap_new();
+
+ /* every routerinfo in rl->routers should be in the nodelist. */
+ if (rl) {
+ SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node && node->ri == ri);
+ tor_assert(fast_memeq(ri->cache_info.identity_digest,
+ node->identity, DIGEST_LEN));
+ tor_assert(! digestmap_get(dm, node->identity));
+ digestmap_set(dm, node->identity, (void*)node);
+ } SMARTLIST_FOREACH_END(ri);
+ }
+
+ /* every routerstatus in ns should be in the nodelist */
+ if (ns) {
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ const node_t *node = node_get_by_id(rs->identity_digest);
+ tor_assert(node && node->rs == rs);
+ tor_assert(fast_memeq(rs->identity_digest, node->identity, DIGEST_LEN));
+ digestmap_set(dm, node->identity, (void*)node);
+ if (ns->flavor == FLAV_MICRODESC) {
+ /* If it's a microdesc consensus, every entry that has a
+ * microdescriptor should be in the nodelist.
+ */
+ microdesc_t *md =
+ microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
+ tor_assert(md == node->md);
+ }
+ } SMARTLIST_FOREACH_END(rs);
+ }
+
+ /* The nodelist should have no other entries, and its entries should be
+ * well-formed. */
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ tor_assert(digestmap_get(dm, node->identity) != NULL);
+ tor_assert(node_sl_idx == node->nodelist_idx);
+ } SMARTLIST_FOREACH_END(node);
+
+ tor_assert((long)smartlist_len(the_nodelist->nodes) ==
+ (long)HT_SIZE(&the_nodelist->nodes_by_id));
+
+ digestmap_free(dm, NULL);
+}
+
+/** Return a list of a node_t * for every node we know about. The caller
+ * MUST NOT modify the list. (You can set and clear flags in the nodes if
+ * you must, but you must not add or remove nodes.) */
+smartlist_t *
+nodelist_get_list(void)
+{
+ init_nodelist();
+ return the_nodelist->nodes;
+}
+
+/** Given a hex-encoded nickname of the format DIGEST, $DIGEST, $DIGEST=name,
+ * or $DIGEST~name, return the node with the matching identity digest and
+ * nickname (if any). Return NULL if no such node exists, or if <b>hex_id</b>
+ * is not well-formed. */
+const node_t *
+node_get_by_hex_id(const char *hex_id)
+{
+ char digest_buf[DIGEST_LEN];
+ char nn_buf[MAX_NICKNAME_LEN+1];
+ char nn_char='\0';
+
+ if (hex_digest_nickname_decode(hex_id, digest_buf, &nn_char, nn_buf)==0) {
+ const node_t *node = node_get_by_id(digest_buf);
+ if (!node)
+ return NULL;
+ if (nn_char) {
+ const char *real_name = node_get_nickname(node);
+ if (!real_name || strcasecmp(real_name, nn_buf))
+ return NULL;
+ if (nn_char == '=') {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nn_buf);
+ if (!named_id || tor_memneq(named_id, digest_buf, DIGEST_LEN))
+ return NULL;
+ }
+ }
+ return node;
+ }
+
+ return NULL;
+}
+
+/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
+ * the corresponding node_t, or NULL if none exists. Warn the user if
+ * <b>warn_if_unnamed</b> is set, and they have specified a router by
+ * nickname, but the Named flag isn't set for that router. */
+const node_t *
+node_get_by_nickname(const char *nickname, int warn_if_unnamed)
+{
+ const node_t *node;
+ if (!the_nodelist)
+ return NULL;
+
+ /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
+ if ((node = node_get_by_hex_id(nickname)) != NULL)
+ return node;
+
+ if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME))
+ return NULL;
+
+ /* Okay, so if we get here, the nickname is just a nickname. Is there
+ * a binding for it in the consensus? */
+ {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nickname);
+ if (named_id)
+ return node_get_by_id(named_id);
+ }
+
+ /* Is it marked as owned-by-someone-else? */
+ if (networkstatus_nickname_is_unnamed(nickname)) {
+ log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some "
+ "router that holds it, but not one listed in the current "
+ "consensus.", escaped(nickname));
+ return NULL;
+ }
+
+ /* Okay, so the name is not canonical for anybody. */
+ {
+ smartlist_t *matches = smartlist_create();
+ const node_t *choice = NULL;
+
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ if (!strcasecmp(node_get_nickname(node), nickname))
+ smartlist_add(matches, node);
+ } SMARTLIST_FOREACH_END(node);
+
+ if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ int any_unwarned = 0;
+ SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) {
+ if (!node->name_lookup_warned) {
+ node->name_lookup_warned = 1;
+ any_unwarned = 1;
+ }
+ } SMARTLIST_FOREACH_END(node);
+
+ if (any_unwarned) {
+ log_warn(LD_CONFIG, "There are multiple matches for the name %s, "
+ "but none is listed as Named in the directory consensus. "
+ "Choosing one arbitrarily.", nickname);
+ }
+ } else if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ char fp[HEX_DIGEST_LEN+1];
+ node_t *node = smartlist_get(matches, 0);
+ if (node->name_lookup_warned) {
+ base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN);
+ log_warn(LD_CONFIG,
+ "You specified a server \"%s\" by name, but the directory "
+ "authorities do not have any key registered for this "
+ "nickname -- so it could be used by any server, not just "
+ "the one you meant. "
+ "To make sure you get the same server in the future, refer "
+ "to it by key, as \"$%s\".", nickname, fp);
+ node->name_lookup_warned = 1;
+ }
+ }
+
+ if (smartlist_len(matches))
+ choice = smartlist_get(matches, 0);
+
+ smartlist_free(matches);
+ return choice;
+ }
+}
+
+/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
+const char *
+node_get_nickname(const node_t *node)
+{
+ tor_assert(node);
+ if (node->rs)
+ return node->rs->nickname;
+ else if (node->ri)
+ return node->ri->nickname;
+ else
+ return NULL;
+}
+
+/** Return true iff the nickname of <b>node</b> is canonical, based on the
+ * latest consensus. */
+int
+node_is_named(const node_t *node)
+{
+ const char *named_id;
+ const char *nickname = node_get_nickname(node);
+ if (!nickname)
+ return 0;
+ named_id = networkstatus_get_router_digest_by_nickname(nickname);
+ if (!named_id)
+ return 0;
+ return tor_memeq(named_id, node->identity, DIGEST_LEN);
+}
+
+/** Return true iff <b>node</b> appears to be a directory authority or
+ * directory cache */
+int
+node_is_dir(const node_t *node)
+{
+ if (node->rs)
+ return node->rs->dir_port != 0;
+ else if (node->ri)
+ return node->ri->dir_port != 0;
+ else
+ return 0;
+}
+
+/** Return true iff <b>node</b> has either kind of usable descriptor -- that
+ * is, a routerdecriptor or a microdescriptor. */
+int
+node_has_descriptor(const node_t *node)
+{
+ return (node->ri ||
+ (node->rs && node->md));
+}
+
+/** Return the router_purpose of <b>node</b>. */
+int
+node_get_purpose(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->purpose;
+ else
+ return ROUTER_PURPOSE_GENERAL;
+}
+
+/** Compute the verbose ("extended") nickname of <b>node</b> and store it
+ * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at
+ * <b>verbose_nickname_out</b> */
+void
+node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out)
+{
+ const char *nickname = node_get_nickname(node);
+ int is_named = node_is_named(node);
+ verbose_name_out[0] = '$';
+ base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity,
+ DIGEST_LEN);
+ if (!nickname)
+ return;
+ verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+ strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+}
+
+/** Return true iff it seems that <b>node</b> allows circuits to exit
+ * through it directlry from the client. */
+int
+node_allows_single_hop_exits(const node_t *node)
+{
+ if (node && node->ri)
+ return node->ri->allow_single_hop_exits;
+ else
+ return 0;
+}
+
+/** Return true iff it seems that <b>node</b> has an exit policy that doesn't
+ * actually permit anything to exit, or we don't know its exit policy */
+int
+node_exit_policy_rejects_all(const node_t *node)
+{
+ if (node->rejects_all)
+ return 1;
+
+ if (node->ri)
+ return node->ri->policy_is_reject_star;
+ else if (node->md)
+ return node->md->exit_policy == NULL ||
+ short_policy_is_reject_star(node->md->exit_policy);
+ else
+ return 1;
+}
+
+/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
+int
+node_get_addr(const node_t *node, tor_addr_t *addr_out)
+{
+ if (node->ri) {
+ tor_addr_from_ipv4h(addr_out, node->ri->addr);
+ return 0;
+ } else if (node->rs) {
+ tor_addr_from_ipv4h(addr_out, node->rs->addr);
+ return 0;
+ }
+ return -1;
+}
+
+/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
+ * seem to have one. */
+uint32_t
+node_get_addr_ipv4h(const node_t *node)
+{
+ if (node->ri) {
+ return node->ri->addr;
+ } else if (node->rs) {
+ return node->rs->addr;
+ }
+ return 0;
+}
+
+/** Copy a string representation of the IP address for <b>node</b> into the
+ * <b>len</b>-byte buffer at <b>buf</b>.
+ */
+void
+node_get_address_string(const node_t *node, char *buf, size_t len)
+{
+ if (node->ri) {
+ strlcpy(buf, node->ri->address, len);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ tor_addr_to_str(buf, &addr, len, 0);
+ } else {
+ buf[0] = '\0';
+ }
+}
+
+/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have
+ * one. */
+long
+node_get_declared_uptime(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->uptime;
+ else
+ return -1;
+}
+
+/** Return <b>node</b>'s declared or_port */
+uint16_t
+node_get_orport(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->or_port;
+ else if (node->rs)
+ return node->rs->or_port;
+ else
+ return 0;
+}
+
+/** Return <b>node</b>'s platform string, or NULL if we don't know it. */
+const char *
+node_get_platform(const node_t *node)
+{
+ /* If we wanted, we could record the version in the routerstatus_t, since
+ * the consensus lists it. We don't, though, so this function just won't
+ * work with microdescriptors. */
+ if (node->ri)
+ return node->ri->platform;
+ else
+ return NULL;
+}
+
+/** Return <b>node</b>'s time of publication, or 0 if we don't have one. */
+time_t
+node_get_published_on(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->cache_info.published_on;
+ else
+ return 0;
+}
+
+/** Return true iff <b>node</b> is one representing this router. */
+int
+node_is_me(const node_t *node)
+{
+ return router_digest_is_me(node->identity);
+}
+
+/** Return <b>node</b> declared family (as a list of names), or NULL if
+ * the node didn't declare a family. */
+const smartlist_t *
+node_get_declared_family(const node_t *node)
+{
+ if (node->ri && node->ri->declared_family)
+ return node->ri->declared_family;
+ else if (node->md && node->md->family)
+ return node->md->family;
+ else
+ return NULL;
+}
+
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
new file mode 100644
index 000000000..08f11da59
--- /dev/null
+++ b/src/or/nodelist.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file microdesc.h
+ * \brief Header file for microdesc.c.
+ **/
+
+#ifndef _TOR_NODELIST_H
+#define _TOR_NODELIST_H
+
+node_t *node_get_mutable_by_id(const char *identity_digest);
+const node_t *node_get_by_id(const char *identity_digest);
+const node_t *node_get_by_hex_id(const char *identity_digest);
+node_t *nodelist_add_routerinfo(routerinfo_t *ri);
+node_t *nodelist_add_microdesc(microdesc_t *md);
+void nodelist_set_consensus(networkstatus_t *ns);
+
+void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
+void nodelist_remove_routerinfo(routerinfo_t *ri);
+void nodelist_purge(void);
+
+void nodelist_free_all(void);
+void nodelist_assert_ok(void);
+
+const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed);
+void node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out);
+int node_is_named(const node_t *node);
+int node_is_dir(const node_t *node);
+int node_has_descriptor(const node_t *node);
+int node_get_purpose(const node_t *node);
+#define node_is_bridge(node) \
+ (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
+int node_is_me(const node_t *node);
+int node_exit_policy_rejects_all(const node_t *node);
+int node_get_addr(const node_t *node, tor_addr_t *addr_out);
+uint32_t node_get_addr_ipv4h(const node_t *node);
+int node_allows_single_hop_exits(const node_t *node);
+uint16_t node_get_orport(const node_t *node);
+const char *node_get_nickname(const node_t *node);
+const char *node_get_platform(const node_t *node);
+void node_get_address_string(const node_t *node, char *cp, size_t len);
+long node_get_declared_uptime(const node_t *node);
+time_t node_get_published_on(const node_t *node);
+const smartlist_t *node_get_declared_family(const node_t *node);
+
+smartlist_t *nodelist_get_list(void);
+
+/* XXXX These need to move out of routerlist.c */
+void nodelist_refresh_countries(void);
+void node_set_country(node_t *node);
+void nodelist_add_node_family(smartlist_t *nodes, const node_t *node);
+int nodes_in_same_family(const node_t *node1, const node_t *node2);
+
+#endif
+
diff --git a/src/or/ntmain.c b/src/or/ntmain.c
index b2fee648c..4eb487e97 100644
--- a/src/or/ntmain.c
+++ b/src/or/ntmain.c
@@ -193,7 +193,6 @@ nt_service_loadlibrary(void)
*/
int
nt_service_is_stopping(void)
-/* XXXX this function would probably _love_ to be inline, in 0.2.0. */
{
/* If we haven't loaded the function pointers, we can't possibly be an NT
* service trying to shut down. */
diff --git a/src/or/or.h b/src/or/or.h
index b9d8319ba..c9fe4ff8d 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -83,6 +83,13 @@
#define snprintf _snprintf
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#include <event2/buffer.h>
+#include <event2/util.h>
+#endif
+
+#include "crypto.h"
#include "tortls.h"
#include "../common/torlog.h"
#include "container.h"
@@ -384,7 +391,9 @@ typedef enum {
/** A connection to a hidden service directory server: download a v2 rendezvous
* descriptor. */
#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
-#define _DIR_PURPOSE_MAX 18
+/** A connection to a directory server: download a microdescriptor. */
+#define DIR_PURPOSE_FETCH_MICRODESC 19
+#define _DIR_PURPOSE_MAX 19
/** True iff <b>p</b> is a purpose corresponding to uploading data to a
* directory server. */
@@ -805,6 +814,9 @@ typedef enum {
* Tor 0.1.2.x is obsolete, we can remove this. */
#define DEFAULT_CLIENT_NICKNAME "client"
+/** Name chosen by routers that don't configure nicknames */
+#define UNNAMED_ROUTER_NICKNAME "Unnamed"
+
/** Number of bytes in a SOCKS4 header. */
#define SOCKS4_NETWORK_LEN 8
@@ -855,7 +867,7 @@ typedef struct var_cell_t {
/** Number of bytes actually stored in <b>payload</b> */
uint16_t payload_len;
/** Payload of this cell */
- uint8_t payload[1];
+ uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
} var_cell_t;
/** A cell as packed for writing to the network. */
@@ -970,8 +982,9 @@ typedef struct connection_t {
unsigned int proxy_state:4;
/** Our socket; -1 if this connection is closed, or has no socket. */
- evutil_socket_t s;
+ tor_socket_t s;
int conn_array_index; /**< Index into the global connection array. */
+
struct event *read_event; /**< Libevent event structure. */
struct event *write_event; /**< Libevent event structure. */
buf_t *inbuf; /**< Buffer holding data read over this connection. */
@@ -982,6 +995,11 @@ typedef struct connection_t {
* read? */
time_t timestamp_lastwritten; /**< When was the last time libevent said we
* could write? */
+
+#ifdef USE_BUFFEREVENTS
+ struct bufferevent *bufev; /**< A Libevent buffered IO structure. */
+#endif
+
time_t timestamp_created; /**< When was this connection_t created? */
/* XXXX_IP6 make this IPv6-capable */
@@ -1009,7 +1027,7 @@ typedef struct connection_t {
/* XXXX023 move this field, and all the listener-only fields (just
socket_family, I think), into a new listener_connection_t subtype. */
/** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
- * to the evdns_server_port is uses to listen to and answer connections. */
+ * to the evdns_server_port it uses to listen to and answer connections. */
struct evdns_server_port *dns_server_port;
/** Unique ID for measuring tunneled network status requests. */
@@ -1081,10 +1099,16 @@ typedef struct or_connection_t {
/* bandwidth* and *_bucket only used by ORs in OPEN state: */
int bandwidthrate; /**< Bytes/s added to the bucket. (OPEN ORs only.) */
int bandwidthburst; /**< Max bucket size for this conn. (OPEN ORs only.) */
+#ifndef USE_BUFFEREVENTS
int read_bucket; /**< When this hits 0, stop receiving. Every second we
* add 'bandwidthrate' to this, capping it at
* bandwidthburst. (OPEN ORs only) */
int write_bucket; /**< When this hits 0, stop writing. Like read_bucket. */
+#else
+ /** DOCDOC */
+ /* XXXX we could share this among all connections. */
+ struct ev_token_bucket_cfg *bucket_cfg;
+#endif
int n_circuits; /**< How many circuits use this connection as p_conn or
* n_conn ? */
@@ -1199,8 +1223,13 @@ typedef struct edge_connection_t {
typedef struct dir_connection_t {
connection_t _base;
- char *requested_resource; /**< Which 'resource' did we ask the directory
- * for? */
+ /** Which 'resource' did we ask the directory for? This is typically the part
+ * of the URL string that defines, relative to the directory conn purpose,
+ * what thing we want. For example, in router descriptor downloads by
+ * descriptor digest, it contains "d/", then one ore more +-separated
+ * fingerprints.
+ **/
+ char *requested_resource;
unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
/* Used only for server sides of some dir connections, to implement
@@ -1242,6 +1271,9 @@ typedef struct control_connection_t {
/** True if we have sent a protocolinfo reply on this connection. */
unsigned int have_sent_protocolinfo:1;
+ /** True if we have received a takeownership command on this
+ * connection. */
+ unsigned int is_owning_control_connection:1;
/** Amount of space allocated in incoming_cmd. */
uint32_t incoming_cmd_len;
@@ -1291,6 +1323,51 @@ static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
return DOWNCAST(control_connection_t, c);
}
+/* Conditional macros to help write code that works whether bufferevents are
+ disabled or not.
+
+ We can't just write:
+ if (conn->bufev) {
+ do bufferevent stuff;
+ } else {
+ do other stuff;
+ }
+ because the bufferevent stuff won't even compile unless we have a fairly
+ new version of Libevent. Instead, we say:
+ IF_HAS_BUFFEREVENT(conn, { do_bufferevent_stuff } );
+ or:
+ IF_HAS_BUFFEREVENT(conn, {
+ do bufferevent stuff;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ do non-bufferevent stuff;
+ }
+ If we're compiling with bufferevent support, then the macros expand more or
+ less to:
+ if (conn->bufev) {
+ do_bufferevent_stuff;
+ } else {
+ do non-bufferevent stuff;
+ }
+ and if we aren't using bufferevents, they expand more or less to:
+ { do non-bufferevent stuff; }
+*/
+#ifdef USE_BUFFEREVENTS
+#define HAS_BUFFEREVENT(c) (((c)->bufev) != NULL)
+#define IF_HAS_BUFFEREVENT(c, stmt) \
+ if ((c)->bufev) do { \
+ stmt ; \
+ } while (0)
+#define ELSE_IF_NO_BUFFEREVENT ; else
+#define IF_HAS_NO_BUFFEREVENT(c) \
+ if (NULL == (c)->bufev)
+#else
+#define HAS_BUFFEREVENT(c) (0)
+#define IF_HAS_BUFFEREVENT(c, stmt) (void)0
+#define ELSE_IF_NO_BUFFEREVENT ;
+#define IF_HAS_NO_BUFFEREVENT(c) \
+ if (1)
+#endif
+
/** What action type does an address policy indicate: accept or reject? */
typedef enum {
ADDR_POLICY_ACCEPT=1,
@@ -1454,59 +1531,49 @@ typedef struct {
char *contact_info; /**< Declared contact info for this router. */
unsigned int is_hibernating:1; /**< Whether the router claims to be
* hibernating */
- unsigned int has_old_dnsworkers:1; /**< Whether the router is using
- * dnsworker code. */
- unsigned int caches_extra_info:1; /**< Whether the router caches and serves
- * extrainfo documents. */
- unsigned int allow_single_hop_exits:1; /**< Whether the router allows
- * single hop exits. */
-
- /* local info */
- unsigned int is_running:1; /**< As far as we know, is this OR currently
- * running? */
- unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
- * (For Authdir: Have we validated this OR?)
- */
- unsigned int is_named:1; /**< Do we believe the nickname that this OR gives
- * us? */
- unsigned int is_fast:1; /** Do we think this is a fast OR? */
- unsigned int is_stable:1; /** Do we think this is a stable OR? */
- unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
- unsigned int is_exit:1; /**< Do we think this is an OK exit? */
- unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
- * or otherwise nasty? */
- unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
- * underpowered, or otherwise useless? */
+ unsigned int caches_extra_info:1; /**< Whether the router says it caches and
+ * serves extrainfo documents. */
+ unsigned int allow_single_hop_exits:1; /**< Whether the router says
+ * it allows single hop exits. */
+
unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
* a hidden service directory. */
- unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
- * directory according to the authorities. */
unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
* router rejects everything. */
/** True if, after we have added this router, we should re-launch
* tests for it. */
unsigned int needs_retest_if_added:1;
-/** Tor can use this router for general positions in circuits. */
+/** Tor can use this router for general positions in circuits; we got it
+ * from a directory server as usual, or we're an authority and a server
+ * uploaded it. */
#define ROUTER_PURPOSE_GENERAL 0
-/** Tor should avoid using this router for circuit-building. */
+/** Tor should avoid using this router for circuit-building: we got it
+ * from a crontroller. If the controller wants to use it, it'll have to
+ * ask for it by identity. */
#define ROUTER_PURPOSE_CONTROLLER 1
-/** Tor should use this router only for bridge positions in circuits. */
+/** Tor should use this router only for bridge positions in circuits: we got
+ * it via a directory request from the bridge itself, or a bridge
+ * authority. x*/
#define ROUTER_PURPOSE_BRIDGE 2
/** Tor should not use this router; it was marked in cached-descriptors with
* a purpose we didn't recognize. */
#define ROUTER_PURPOSE_UNKNOWN 255
- uint8_t purpose; /** What positions in a circuit is this router good for? */
+ /* In what way did we find out about this router? One of ROUTER_PURPOSE_*.
+ * Routers of different purposes are kept segregated and used for different
+ * things; see notes on ROUTER_PURPOSE_* macros above.
+ */
+ uint8_t purpose;
/* The below items are used only by authdirservers for
* reachability testing. */
+
/** When was the last time we could reach this OR? */
time_t last_reachable;
/** When did we start testing reachability for this OR? */
time_t testing_since;
- /** According to the geoip db what country is this router in? */
- country_t country;
+
} routerinfo_t;
/** Information needed to keep and cache a signed extra-info document. */
@@ -1532,8 +1599,9 @@ typedef struct routerstatus_t {
* has. */
char identity_digest[DIGEST_LEN]; /**< Digest of the router's identity
* key. */
- char descriptor_digest[DIGEST_LEN]; /**< Digest of the router's most recent
- * descriptor. */
+ /** Digest of the router's most recent descriptor or microdescriptor.
+ * If it's a descriptor, we only use the first DIGEST_LEN bytes. */
+ char descriptor_digest[DIGEST256_LEN];
uint32_t addr; /**< IPv4 address for this router. */
uint16_t or_port; /**< OR port for this router. */
uint16_t dir_port; /**< Directory port for this router. */
@@ -1541,7 +1609,11 @@ typedef struct routerstatus_t {
unsigned int is_exit:1; /**< True iff this router is a good exit. */
unsigned int is_stable:1; /**< True iff this router stays up a long time. */
unsigned int is_fast:1; /**< True iff this router has good bandwidth. */
- unsigned int is_running:1; /**< True iff this router is up. */
+ /** True iff this router is called 'running' in the consensus. We give it
+ * this funny name so that we don't accidentally use this bit as a view of
+ * whether we think the router is *currently* running. If that's what you
+ * want to know, look at is_running in node_t. */
+ unsigned int is_flagged_running:1;
unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */
unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
* router. */
@@ -1572,6 +1644,9 @@ typedef struct routerstatus_t {
/** True iff this router is a version that, if it caches directory info,
* we can get v3 downloads from. */
unsigned int version_supports_v3_dir:1;
+ /** True iff this router is a version that, if it caches directory info,
+ * we can get microdescriptors from. */
+ unsigned int version_supports_microdesc_cache:1;
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
@@ -1593,15 +1668,31 @@ typedef struct routerstatus_t {
* from this authority.) Applies in v2 networkstatus document only.
*/
unsigned int need_to_mirror:1;
- unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
- * to this (unnamed) router by nickname?
- */
time_t last_dir_503_at; /**< When did this router last tell us that it
* was too busy to serve directory info? */
download_status_t dl_status;
} routerstatus_t;
+/** A single entry in a parsed policy summary, describing a range of ports. */
+typedef struct short_policy_entry_t {
+ uint16_t min_port, max_port;
+} short_policy_entry_t;
+
+/** A short_poliy_t is the parsed version of a policy summary. */
+typedef struct short_policy_t {
+ /** True if the members of 'entries' are port ranges to accept; false if
+ * they are port ranges to reject */
+ unsigned int is_accept : 1;
+ /** The actual number of values in 'entries'. */
+ unsigned int n_entries : 31;
+ /** An array of 0 or more short_policy_entry_t values, each describing a
+ * range of ports that this policy accepts or rejects (depending on the
+ * value of is_accept).
+ */
+ short_policy_entry_t entries[FLEXIBLE_ARRAY_MEMBER];
+} short_policy_t;
+
/** A microdescriptor is the smallest amount of information needed to build a
* circuit through a router. They are generated by the directory authorities,
* using information from the uploaded routerinfo documents. They are not
@@ -1643,15 +1734,83 @@ typedef struct microdesc_t {
crypto_pk_env_t *onion_pkey;
/** As routerinfo_t.family */
smartlist_t *family;
- /** Encoded exit policy summary */
- char *exitsummary; /**< exit policy summary -
- * XXX this probably should not stay a string. */
+ /** Exit policy summary */
+ short_policy_t *exit_policy;
} microdesc_t;
+/** A node_t represents a Tor router.
+ *
+ * Specifically, a node_t is a Tor router as we are using it: a router that
+ * we are considering for circuits, connections, and so on. A node_t is a
+ * thin wrapper around the routerstatus, routerinfo, and microdesc for a
+ * single wrapper, and provides a consistent interface for all of them.
+ *
+ * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
+ * and a microdesc have[*] only the information read from a router
+ * descriptor, a consensus entry, and a microdescriptor (respectively)...
+ * a node_t has flags based on *our own current opinion* of the node.
+ *
+ * [*] Actually, there is some leftover information in each that is mutable.
+ * We should try to excise that.
+ */
+typedef struct node_t {
+ /* Indexing information */
+
+ /** Used to look up the node_t by its identity digest. */
+ HT_ENTRY(node_t) ht_ent;
+ /** Position of the node within the list of nodes */
+ int nodelist_idx;
+
+ /** The identity digest of this node_t. No more than one node_t per
+ * identity may exist at a time. */
+ char identity[DIGEST_LEN];
+
+ microdesc_t *md;
+ routerinfo_t *ri;
+ routerstatus_t *rs;
+
+ /* local info: copied from routerstatus, then possibly frobbed based
+ * on experience. Authorities set this stuff directly. */
+
+ unsigned int is_running:1; /**< As far as we know, is this OR currently
+ * running? */
+ unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
+ * (For Authdir: Have we validated this OR?)
+ */
+ unsigned int is_fast:1; /** Do we think this is a fast OR? */
+ unsigned int is_stable:1; /** Do we think this is a stable OR? */
+ unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
+ unsigned int is_exit:1; /**< Do we think this is an OK exit? */
+ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
+ * or otherwise nasty? */
+ unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
+ * underpowered, or otherwise useless? */
+ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
+ * directory according to the authorities. */
+
+ /* Local info: warning state. */
+
+ unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
+ * to this (unnamed) router by nickname?
+ */
+
+ /** Local info: we treat this node as if it rejects everything */
+ unsigned int rejects_all:1;
+
+ /* Local info: derived. */
+
+ /** According to the geoip db what country is this router in? */
+ country_t country;
+} node_t;
+
/** How many times will we try to download a router's descriptor before giving
* up? */
#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
+/** How many times will we try to download a microdescriptor before giving
+ * up? */
+#define MAX_MICRODESC_DOWNLOAD_FAILURES 8
+
/** Contents of a v2 (non-consensus, non-vote) network status object. */
typedef struct networkstatus_v2_t {
/** When did we receive the network-status document? */
@@ -1765,9 +1924,6 @@ typedef enum {
FLAV_MICRODESC = 1,
} consensus_flavor_t;
-/** Which consensus flavor do we actually want to use to build circuits? */
-#define USABLE_CONSENSUS_FLAVOR FLAV_NS
-
/** How many different consensus flavors are there? */
#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
@@ -1937,24 +2093,33 @@ typedef struct authority_cert_t {
uint8_t is_cross_certified;
} authority_cert_t;
-/** Bitfield enum type listing types of directory authority/directory
- * server. */
+/** Bitfield enum type listing types of information that directory authorities
+ * can be authoritative about, and that directory caches may or may not cache.
+ *
+ * Note that the granularity here is based on authority granularity and on
+ * cache capabilities. Thus, one particular bit may correspond in practice to
+ * a few types of directory info, so long as every authority that pronounces
+ * officially about one of the types prounounces officially about all of them,
+ * and so long as every cache that caches one of them caches all of them.
+ */
typedef enum {
- NO_AUTHORITY = 0,
+ NO_DIRINFO = 0,
/** Serves/signs v1 directory information: Big lists of routers, and short
* routerstatus documents. */
- V1_AUTHORITY = 1 << 0,
+ V1_DIRINFO = 1 << 0,
/** Serves/signs v2 directory information: i.e. v2 networkstatus documents */
- V2_AUTHORITY = 1 << 1,
+ V2_DIRINFO = 1 << 1,
/** Serves/signs v3 directory information: votes, consensuses, certs */
- V3_AUTHORITY = 1 << 2,
+ V3_DIRINFO = 1 << 2,
/** Serves hidden service descriptors. */
- HIDSERV_AUTHORITY = 1 << 3,
+ HIDSERV_DIRINFO = 1 << 3,
/** Serves bridge descriptors. */
- BRIDGE_AUTHORITY = 1 << 4,
- /** Serves extrainfo documents. (XXX Not precisely an authority type)*/
- EXTRAINFO_CACHE = 1 << 5,
-} authority_type_t;
+ BRIDGE_DIRINFO = 1 << 4,
+ /** Serves extrainfo documents. */
+ EXTRAINFO_DIRINFO=1 << 5,
+ /** Serves microdescriptors. */
+ MICRODESC_DIRINFO=1 << 6,
+} dirinfo_type_t;
#define CRYPT_PATH_MAGIC 0x70127012u
@@ -2027,15 +2192,15 @@ typedef struct {
/** How to extend to the planned exit node. */
extend_info_t *chosen_exit;
/** Whether every node in the circ must have adequate uptime. */
- int need_uptime;
+ unsigned int need_uptime : 1;
/** Whether every node in the circ must have adequate capacity. */
- int need_capacity;
+ unsigned int need_capacity : 1;
/** Whether the last hop was picked with exiting in mind. */
- int is_internal;
- /** Did we pick this as a one-hop tunnel (not safe for other conns)?
- * These are for encrypted connections that exit to this router, not
+ unsigned int is_internal : 1;
+ /** Did we pick this as a one-hop tunnel (not safe for other streams)?
+ * These are for encrypted dir conns that exit to this router, not
* for arbitrary exits from the circuit. */
- int onehop_tunnel;
+ unsigned int onehop_tunnel : 1;
/** The crypt_path_t to append after rendezvous: used for rendezvous. */
crypt_path_t *pending_final_cpath;
/** How many times has building a circuit for this task failed? */
@@ -2133,13 +2298,21 @@ typedef struct circuit_t {
* length ONIONSKIN_CHALLENGE_LEN. */
char *n_conn_onionskin;
- struct timeval timestamp_created; /**< When was the circuit created? */
+ /** When was this circuit created? We keep this timestamp with a higher
+ * resolution than most so that the circuit-build-time tracking code can
+ * get millisecond resolution. */
+ struct timeval timestamp_created;
/** When the circuit was first used, or 0 if the circuit is clean.
*
* XXXX023 Note that some code will artifically adjust this value backward
* in time in order to indicate that a circuit shouldn't be used for new
* streams, but that it can stay alive as long as it has streams on it.
* That's a kludge we should fix.
+ *
+ * XXX023 The CBT code uses this field to record when HS-related
+ * circuits entered certain states. This usage probably won't
+ * interfere with this field's primary purpose, but we should
+ * document it more thoroughly to make sure of that.
*/
time_t timestamp_dirty;
@@ -2310,14 +2483,14 @@ typedef struct or_circuit_t {
cell_ewma_t p_cell_ewma;
} or_circuit_t;
-/** Convert a circuit subtype to a circuit_t.*/
+/** Convert a circuit subtype to a circuit_t. */
#define TO_CIRCUIT(x) (&((x)->_base))
-/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Asserts
+/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert
* if the cast is impossible. */
static or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
- * Asserts if the cast is impossible. */
+ * Assert if the cast is impossible. */
static origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
static INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
@@ -2370,6 +2543,7 @@ typedef struct {
config_line_t *Logs; /**< New-style list of configuration lines
* for logs */
+ int LogTimeGranularity; /**< Log resolution in milliseconds. */
int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
* each log message occurs? */
@@ -2489,8 +2663,8 @@ typedef struct {
/** To what authority types do we publish our descriptor? Choices are
* "v1", "v2", "v3", "bridge", or "". */
smartlist_t *PublishServerDescriptor;
- /** An authority type, derived from PublishServerDescriptor. */
- authority_type_t _PublishServerDescriptor;
+ /** A bitfield of authority types, derived from PublishServerDescriptor. */
+ dirinfo_type_t _PublishServerDescriptor;
/** Boolean: do we publish hidden service descriptors to the HS auths? */
int PublishHidServDescriptors;
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
@@ -2519,12 +2693,10 @@ typedef struct {
uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */
/** Whether we should drop exit streams from Tors that we don't know are
- * relays. One of "0" (never refuse), "1" (always refuse), or "auto" (do
+ * relays. One of "0" (never refuse), "1" (always refuse), or "-1" (do
* what the consensus says, defaulting to 'refuse' if the consensus says
* nothing). */
- char *RefuseUnknownExits;
- /** Parsed version of RefuseUnknownExits. -1 for auto. */
- int RefuseUnknownExits_;
+ int RefuseUnknownExits;
/** Application ports that require all nodes in circ to have sufficient
* uptime. */
@@ -2595,6 +2767,9 @@ typedef struct {
* authorizations for hidden services */
char *ContactInfo; /**< Contact info to be published in the directory. */
+ int HeartbeatPeriod; /**< Log heartbeat messages after this many seconds
+ * have passed. */
+
char *HTTPProxy; /**< hostname[:port] to use as http proxy, if any. */
tor_addr_t HTTPProxyAddr; /**< Parsed IPv4 addr for http proxy, if any. */
uint16_t HTTPProxyPort; /**< Parsed port for http proxy, if any. */
@@ -2632,7 +2807,8 @@ typedef struct {
char *MyFamily; /**< Declared family for this OR. */
config_line_t *NodeFamilies; /**< List of config lines for
- * node families */
+ * node families */
+ smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */
config_line_t *AuthDirBadDir; /**< Address policy for descriptors to
* mark as bad dir mirrors. */
config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
@@ -2674,6 +2850,11 @@ typedef struct {
int DisablePredictedCircuits; /**< Boolean: does Tor preemptively
* make circuits in the background (0),
* or not (1)? */
+
+ /** Process specifier for a controller that ‘owns’ this Tor
+ * instance. Tor will terminate if its owning controller does. */
+ char *OwningControllerProcess;
+
int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how
* long do we wait before exiting? */
char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */
@@ -2727,7 +2908,9 @@ typedef struct {
/** Boolean: if set, we start even if our resolv.conf file is missing
* or broken. */
int ServerDNSAllowBrokenConfig;
-
+ /** Boolean: if set, then even connections to private addresses will get
+ * rate-limited. */
+ int CountPrivateBandwidth;
smartlist_t *ServerDNSTestAddresses; /**< A list of addresses that definitely
* should be resolvable. Used for
* testing our DNS server. */
@@ -2737,6 +2920,10 @@ typedef struct {
* possible. */
int PreferTunneledDirConns; /**< If true, avoid dirservers that don't
* support BEGIN_DIR, when possible. */
+ int PortForwarding; /**< If true, use NAT-PMP or UPnP to automatically
+ * forward the DirPort and ORPort on the NAT device */
+ char *PortForwardingHelper; /** < Filename or full path of the port
+ forwarding helper executable */
int AllowNonRFC953Hostnames; /**< If true, we allow connections to hostnames
* with weird characters. */
/** If true, we try resolving hostnames with weird characters. */
@@ -2774,6 +2961,9 @@ typedef struct {
/** If true, the user wants us to collect statistics on port usage. */
int ExitPortStatistics;
+ /** If true, the user wants us to collect connection statistics. */
+ int ConnDirectionStatistics;
+
/** If true, the user wants us to collect cell statistics. */
int CellStatistics;
@@ -2870,11 +3060,21 @@ typedef struct {
*/
double CircuitPriorityHalflife;
+ /** If true, do not enable IOCP on windows with bufferevents, even if
+ * we think we could. */
+ int DisableIOCP;
+ /** For testing only: will go away in 0.2.3.x. */
+ int _UseFilteringSSLBufferevents;
+
/** Set to true if the TestingTorNetwork configuration option is set.
* This is used so that options_validate() has a chance to realize that
* the defaults have changed. */
int _UsingTestNetworkDefaults;
+ /** If 1, we try to use microdescriptors to build circuits. If 0, we don't.
+ * If -1, Tor decides. */
+ int UseMicrodescriptors;
+
/** File where we should write the ControlPort. */
char *ControlPortWriteToFile;
/** Should that file be group-readable? */
@@ -2994,8 +3194,6 @@ struct socks_request_t {
* every connection. */
};
-/* all the function prototypes go here */
-
/********************************* circuitbuild.c **********************/
/** How many hops does a general-purpose circuit have by default? */
@@ -3408,7 +3606,7 @@ typedef enum {
ADDR_POLICY_PROBABLY_ACCEPTED=1,
/** Part of the address was unknown, but as far as we can tell, it was
* rejected. */
- ADDR_POLICY_PROBABLY_REJECTED=2
+ ADDR_POLICY_PROBABLY_REJECTED=2,
} addr_policy_result_t;
/********************************* rephist.c ***************************/
@@ -3493,7 +3691,7 @@ typedef struct trusted_dir_server_t {
unsigned int has_accepted_serverdesc:1;
/** What kind of authority is this? (Bitfield.) */
- authority_type_t type;
+ dirinfo_type_t type;
download_status_t v2_ns_dl_status; /**< Status of downloading this server's
* v2 network status. */
@@ -3539,6 +3737,8 @@ typedef struct trusted_dir_server_t {
* fetches to _any_ single directory server.]
*/
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
+#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
+
#define _PDS_PREFER_TUNNELED_DIR_CONNS (1<<16)
/** Possible ways to weight routers when choosing one randomly. See
@@ -3556,7 +3756,8 @@ typedef enum {
CRN_NEED_GUARD = 1<<2,
CRN_ALLOW_INVALID = 1<<3,
/* XXXX not used, apparently. */
- CRN_WEIGHT_AS_EXIT = 1<<5
+ CRN_WEIGHT_AS_EXIT = 1<<5,
+ CRN_NEED_DESC = 1<<6
} router_crn_flags_t;
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
diff --git a/src/or/policies.c b/src/or/policies.c
index e48f42058..1b5408c77 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "config.h"
#include "dirserv.h"
+#include "nodelist.h"
#include "policies.h"
#include "routerparse.h"
#include "ht.h"
@@ -45,7 +46,7 @@ typedef struct policy_summary_item_t {
uint16_t prt_max; /**< Highest port number to accept/reject. */
uint64_t reject_count; /**< Number of IP-Addresses that are rejected to
this port range. */
- int accepted:1; /** Has this port already been accepted */
+ unsigned int accepted:1; /** Has this port already been accepted */
} policy_summary_item_t;
/** Private networks. This list is used in two places, once to expand the
@@ -82,15 +83,15 @@ policy_expand_private(smartlist_t **policy)
continue;
}
for (i = 0; private_nets[i]; ++i) {
- addr_policy_t policy;
- memcpy(&policy, p, sizeof(addr_policy_t));
- policy.is_private = 0;
- policy.is_canonical = 0;
- if (tor_addr_parse_mask_ports(private_nets[i], &policy.addr,
- &policy.maskbits, &port_min, &port_max)<0) {
+ addr_policy_t newpolicy;
+ memcpy(&newpolicy, p, sizeof(addr_policy_t));
+ newpolicy.is_private = 0;
+ newpolicy.is_canonical = 0;
+ if (tor_addr_parse_mask_ports(private_nets[i], &newpolicy.addr,
+ &newpolicy.maskbits, &port_min, &port_max)<0) {
tor_assert(0);
}
- smartlist_add(tmp, addr_policy_get_canonical_entry(&policy));
+ smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy));
}
addr_policy_free(p);
});
@@ -163,7 +164,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
static int
parse_reachable_addresses(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int ret = 0;
if (options->ReachableDirAddresses &&
@@ -261,7 +262,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port)
/** Return true iff we think our firewall will let us make an OR connection to
* <b>ri</b>. */
int
-fascist_firewall_allows_or(routerinfo_t *ri)
+fascist_firewall_allows_or(const routerinfo_t *ri)
{
/* XXXX proposal 118 */
tor_addr_t addr;
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(routerinfo_t *ri)
return fascist_firewall_allows_address_or(&addr, ri->or_port);
}
+/** Return true iff we think our firewall will let us make an OR connection to
+ * <b>node</b>. */
+int
+fascist_firewall_allows_node(const node_t *node)
+{
+ if (node->ri) {
+ return fascist_firewall_allows_or(node->ri);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+ } else {
+ return 1;
+ }
+}
+
/** Return true iff we think our firewall will let us make a directory
* connection to addr:port. */
int
@@ -339,7 +356,7 @@ authdir_policy_badexit_address(uint32_t addr, uint16_t port)
* options in <b>options</b>, return -1 and set <b>msg</b> to a newly
* allocated description of the error. Else return 0. */
int
-validate_addr_policies(or_options_t *options, char **msg)
+validate_addr_policies(const or_options_t *options, char **msg)
{
/* XXXX Maybe merge this into parse_policies_from_options, to make sure
* that the two can't go out of sync. */
@@ -423,7 +440,7 @@ load_policy_from_option(config_line_t *config, smartlist_t **policy,
/** Set all policies based on <b>options</b>, which should have been validated
* first by validate_addr_policies. */
int
-policies_parse_from_options(or_options_t *options)
+policies_parse_from_options(const or_options_t *options)
{
int ret = 0;
if (load_policy_from_option(options->SocksPolicy, &socks_policy, -1) < 0)
@@ -866,15 +883,11 @@ policies_exit_policy_append_reject_star(smartlist_t **dest)
append_exit_policy_string(dest, "reject *:*");
}
-/** Replace the exit policy of <b>r</b> with reject *:*. */
+/** Replace the exit policy of <b>node</b> with reject *:* */
void
-policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
+policies_set_node_exitpolicy_to_reject_all(node_t *node)
{
- addr_policy_t *item;
- addr_policy_list_free(r->exit_policy);
- r->exit_policy = smartlist_create();
- item = router_parse_addr_policy_item_from_string("reject *:*", -1);
- smartlist_add(r->exit_policy, item);
+ node->rejects_all = 1;
}
/** Return 1 if there is at least one /8 subnet in <b>policy</b> that
@@ -1085,7 +1098,7 @@ policy_summary_split(smartlist_t *summary,
int start_at_index;
int i = 0;
- /* XXXX Do a binary search if run time matters */
+
while (AT(i)->prt_max < prt_min)
i++;
if (AT(i)->prt_min != prt_min) {
@@ -1298,6 +1311,195 @@ policy_summarize(smartlist_t *policy)
return result;
}
+/** Convert a summarized policy string into a short_policy_t. Return NULL
+ * if the string is not well-formed. */
+short_policy_t *
+parse_short_policy(const char *summary)
+{
+ const char *orig_summary = summary;
+ short_policy_t *result;
+ int is_accept;
+ int n_entries;
+ short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */
+ const char *next;
+
+ if (!strcmpstart(summary, "accept ")) {
+ is_accept = 1;
+ summary += strlen("accept ");
+ } else if (!strcmpstart(summary, "reject ")) {
+ is_accept = 0;
+ summary += strlen("reject ");
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword");
+ return NULL;
+ }
+
+ n_entries = 0;
+ for ( ; *summary; summary = next) {
+ const char *comma = strchr(summary, ',');
+ unsigned low, high;
+ char dummy;
+ char ent_buf[32];
+
+ next = comma ? comma+1 : strchr(summary, '\0');
+
+ if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) {
+ /* unrecognized entry format. skip it. */
+ continue;
+ }
+ if (next-summary < 2) {
+ /* empty; skip it. */
+ continue;
+ }
+
+ memcpy(ent_buf, summary, next-summary-1);
+ ent_buf[next-summary-1] = '\0';
+
+ if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) {
+ if (low<1 || low>65535 || high<1 || high>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ } else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) {
+ if (low<1 || low>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ high = low;
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ entries[n_entries].min_port = low;
+ entries[n_entries].max_port = high;
+ n_entries++;
+ }
+
+ if (n_entries == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found no port-range entries in summary %s", escaped(orig_summary));
+ return NULL;
+ }
+
+ {
+ size_t size = STRUCT_OFFSET(short_policy_t, entries) +
+ sizeof(short_policy_entry_t)*(n_entries);
+ result = tor_malloc_zero(size);
+
+ tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size);
+ }
+
+ result->is_accept = is_accept;
+ result->n_entries = n_entries;
+ memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries);
+ return result;
+}
+
+/** Release all storage held in <b>policy</b>. */
+void
+short_policy_free(short_policy_t *policy)
+{
+ tor_free(policy);
+}
+
+/** See whether the <b>addr</b>:<b>port</b> address is likely to be accepted
+ * or rejected by the summarized policy <b>policy</b>. Return values are as
+ * for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy
+ * functions, requires the <b>port</b> be specified. */
+addr_policy_result_t
+compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy)
+{
+ int i;
+ int found_match = 0;
+ int accept;
+ (void)addr;
+
+ tor_assert(port != 0);
+
+ if (addr && (tor_addr_is_internal(addr, 0) ||
+ tor_addr_is_null(addr) ||
+ tor_addr_is_loopback(addr)))
+ return ADDR_POLICY_REJECTED;
+
+ for (i=0; i < policy->n_entries; ++i) {
+ const short_policy_entry_t *e = &policy->entries[i];
+ if (e->min_port <= port && port <= e->max_port) {
+ found_match = 1;
+ break;
+ }
+ }
+
+ if (found_match)
+ accept = policy->is_accept;
+ else
+ accept = ! policy->is_accept;
+
+ /* ???? are these right? */
+ if (accept)
+ return ADDR_POLICY_PROBABLY_ACCEPTED;
+ else
+ return ADDR_POLICY_REJECTED;
+}
+
+/** Return true iff <b>policy</b> seems reject all ports */
+int
+short_policy_is_reject_star(const short_policy_t *policy)
+{
+ /* This doesn't need to be as much on the lookout as policy_is_reject_star,
+ * since policy summaries are from the consensus or from consensus
+ * microdescs.
+ */
+ tor_assert(policy);
+ /* Check for an exact match of "reject 1-65535". */
+ return (policy->is_accept == 0 && policy->n_entries == 1 &&
+ policy->entries[0].min_port == 1 &&
+ policy->entries[0].max_port == 65535);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_addr_to_node_policy(uint32_t addr, uint16_t port, const node_t *node)
+{
+ tor_addr_t a;
+ tor_addr_from_ipv4h(&a, addr);
+ return compare_tor_addr_to_node_policy(&a, port, node);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
+ const node_t *node)
+{
+ if (node->rejects_all)
+ return ADDR_POLICY_REJECTED;
+
+ if (node->ri)
+ return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy);
+ else if (node->md && node->md) {
+ if (node->md->exit_policy == NULL)
+ return ADDR_POLICY_REJECTED;
+ else
+ return compare_tor_addr_to_short_policy(addr, port,
+ node->md->exit_policy);
+ } else
+ return ADDR_POLICY_PROBABLY_REJECTED;
+}
+
/** Implementation for GETINFO control command: knows the answer for questions
* about "exit-policy/..." */
int
diff --git a/src/or/policies.h b/src/or/policies.h
index b2947c67e..6f3624aba 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -19,7 +19,8 @@
int firewall_is_fascist_or(void);
int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
-int fascist_firewall_allows_or(routerinfo_t *ri);
+int fascist_firewall_allows_or(const routerinfo_t *ri);
+int fascist_firewall_allows_node(const node_t *node);
int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
int dir_policy_permits_address(const tor_addr_t *addr);
int socks_policy_permits_address(const tor_addr_t *addr);
@@ -28,9 +29,9 @@ int authdir_policy_valid_address(uint32_t addr, uint16_t port);
int authdir_policy_baddir_address(uint32_t addr, uint16_t port);
int authdir_policy_badexit_address(uint32_t addr, uint16_t port);
-int validate_addr_policies(or_options_t *options, char **msg);
+int validate_addr_policies(const or_options_t *options, char **msg);
void policy_expand_private(smartlist_t **policy);
-int policies_parse_from_options(or_options_t *options);
+int policies_parse_from_options(const or_options_t *options);
addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent);
int cmp_addr_policies(smartlist_t *a, smartlist_t *b);
@@ -38,11 +39,17 @@ addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
uint16_t port, const smartlist_t *policy);
addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
uint16_t port, const smartlist_t *policy);
+
+addr_policy_result_t compare_addr_to_node_policy(uint32_t addr,
+ uint16_t port, const node_t *node);
+addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
+ uint16_t port, const node_t *node);
+
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int rejectprivate, const char *local_address,
int add_default_policy);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
-void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter);
+void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
int exit_policy_is_general_exit(smartlist_t *policy);
int policy_is_reject_star(const smartlist_t *policy);
int getinfo_helper_policies(control_connection_t *conn,
@@ -57,5 +64,12 @@ void policies_free_all(void);
char *policy_summarize(smartlist_t *policy);
+short_policy_t *parse_short_policy(const char *summary);
+void short_policy_free(short_policy_t *policy);
+int short_policy_is_reject_star(const short_policy_t *policy);
+addr_policy_result_t compare_tor_addr_to_short_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy);
+
#endif
diff --git a/src/or/relay.c b/src/or/relay.c
index 9effae303..df6d0a8a5 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -24,10 +24,12 @@
#include "main.h"
#include "mempool.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
#include "rendcommon.h"
+#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
@@ -704,7 +706,7 @@ connection_ap_process_end_not_open(
edge_connection_t *conn, crypt_path_t *layer_hint)
{
struct in_addr in;
- routerinfo_t *exitrouter;
+ node_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE);
int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
(void) layer_hint; /* unused */
@@ -712,11 +714,12 @@ connection_ap_process_end_not_open(
if (rh->length > 0 && edge_reason_is_retriable(reason) &&
!connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */
) {
+ const char *chosen_exit_digest =
+ circ->build_state->chosen_exit->identity_digest;
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address),
stream_end_reason_to_string(reason));
- exitrouter =
- router_get_by_digest(circ->build_state->chosen_exit->identity_digest);
+ exitrouter = node_get_mutable_by_id(chosen_exit_digest);
switch (reason) {
case END_STREAM_REASON_EXITPOLICY:
if (rh->length >= 5) {
@@ -749,10 +752,10 @@ connection_ap_process_end_not_open(
(tor_inet_aton(conn->socks_request->address, &in) &&
!conn->chosen_exit_name))) {
log_info(LD_APP,
- "Exitrouter '%s' seems to be more restrictive than its exit "
+ "Exitrouter %s seems to be more restrictive than its exit "
"policy. Not using this router as exit for now.",
- exitrouter->nickname);
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ node_describe(exitrouter));
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
/* rewrite it to an IP if we learned one. */
if (addressmap_rewrite(conn->socks_request->address,
@@ -817,7 +820,7 @@ connection_ap_process_end_not_open(
case END_STREAM_REASON_HIBERNATING:
case END_STREAM_REASON_RESOURCELIMIT:
if (exitrouter) {
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
if (conn->chosen_exit_optional) {
/* stop wanting a specific exit */
@@ -900,12 +903,8 @@ connection_edge_process_relay_cell_not_open(
int ttl;
if (!addr || (get_options()->ClientDNSRejectInternalAddresses &&
is_internal_IP(addr, 0))) {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
- a.s_addr = htonl(addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_APP,
- "...but it claims the IP address was %s. Closing.", buf);
+ log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
+ fmt_addr32(addr));
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return 0;
@@ -982,11 +981,8 @@ connection_edge_process_relay_cell_not_open(
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
if (get_options()->ClientDNSRejectInternalAddresses &&
is_internal_IP(addr, 0)) {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
- a.s_addr = htonl(addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", buf);
+ log_info(LD_APP,"Got a resolve with answer %s. Rejecting.",
+ fmt_addr32(addr));
connection_ap_handshake_socks_resolved(conn,
RESOLVED_TYPE_ERROR_TRANSIENT,
0, NULL, 0, TIME_MAX);
@@ -1038,6 +1034,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
relay_header_t rh;
unsigned domain = layer_hint?LD_APP:LD_EXIT;
int reason;
+ int optimistic_data = 0; /* Set to 1 if we receive data on a stream
+ * that's in the EXIT_CONN_STATE_RESOLVING
+ * or EXIT_CONN_STATE_CONNECTING states. */
tor_assert(cell);
tor_assert(circ);
@@ -1057,9 +1056,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
/* either conn is NULL, in which case we've got a control cell, or else
* conn points to the recognized stream. */
- if (conn && !connection_state_is_open(TO_CONN(conn)))
- return connection_edge_process_relay_cell_not_open(
- &rh, cell, circ, conn, layer_hint);
+ if (conn && !connection_state_is_open(TO_CONN(conn))) {
+ if (conn->_base.type == CONN_TYPE_EXIT &&
+ (conn->_base.state == EXIT_CONN_STATE_CONNECTING ||
+ conn->_base.state == EXIT_CONN_STATE_RESOLVING) &&
+ rh.command == RELAY_COMMAND_DATA) {
+ /* Allow DATA cells to be delivered to an exit node in state
+ * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
+ * This speeds up HTTP, for example. */
+ optimistic_data = 1;
+ } else {
+ return connection_edge_process_relay_cell_not_open(
+ &rh, cell, circ, conn, layer_hint);
+ }
+ }
switch (rh.command) {
case RELAY_COMMAND_DROP:
@@ -1126,7 +1136,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
stats_n_data_bytes_received += rh.length;
connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
rh.length, TO_CONN(conn));
- connection_edge_consider_sending_sendme(conn);
+
+ if (!optimistic_data) {
+ /* Only send a SENDME if we're not getting optimistic data; otherwise
+ * a SENDME could arrive before the CONNECTED.
+ */
+ connection_edge_consider_sending_sendme(conn);
+ }
+
return 0;
case RELAY_COMMAND_END:
reason = rh.length > 0 ?
@@ -1151,8 +1168,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (!conn->_base.marked_for_close) {
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
return 0;
case RELAY_COMMAND_EXTEND:
@@ -1359,7 +1375,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return 0;
}
- amount_to_process = buf_datalen(conn->_base.inbuf);
+ amount_to_process = connection_get_inbuf_len(TO_CONN(conn));
if (!amount_to_process)
return 0;
@@ -1378,7 +1394,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
connection_fetch_from_buf(payload, length, TO_CONN(conn));
log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s,
- (int)length, (int)buf_datalen(conn->_base.inbuf));
+ (int)length, (int)connection_get_inbuf_len(TO_CONN(conn)));
if (connection_edge_send_command(conn, RELAY_COMMAND_DATA,
payload, length) < 0 )
@@ -1531,7 +1547,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
- if (buf_datalen(conn->_base.inbuf) > 0)
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
@@ -1542,7 +1558,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
- if (buf_datalen(conn->_base.inbuf) > 0)
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
@@ -1581,7 +1597,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
}
/* If there's still data to read, we'll be coming back to this stream. */
- if (buf_datalen(conn->_base.inbuf))
+ if (connection_get_inbuf_len(TO_CONN(conn)))
++n_streams_left;
/* If the circuit won't accept any more data, return without looking
@@ -1994,7 +2010,8 @@ static int ewma_enabled = 0;
/** Adjust the global cell scale factor based on <b>options</b> */
void
-cell_ewma_set_scale_factor(or_options_t *options, networkstatus_t *consensus)
+cell_ewma_set_scale_factor(const or_options_t *options,
+ const networkstatus_t *consensus)
{
int32_t halflife_ms;
double halflife;
@@ -2245,7 +2262,7 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn,
edge->edge_blocked_on_circ = block;
}
- if (!conn->read_event) {
+ if (!conn->read_event && !HAS_BUFFEREVENT(conn)) {
/* This connection is a placeholder for something; probably a DNS
* request. It can't actually stop or start reading.*/
continue;
@@ -2320,13 +2337,13 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
/* Calculate the exact time that this cell has spent in the queue. */
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
- struct timeval now;
+ struct timeval tvnow;
uint32_t flushed;
uint32_t cell_waiting_time;
insertion_time_queue_t *it_queue = queue->insertion_times;
- tor_gettimeofday_cached(&now);
- flushed = (uint32_t)((now.tv_sec % SECONDS_IN_A_DAY) * 100L +
- (uint32_t)now.tv_usec / (uint32_t)10000L);
+ tor_gettimeofday_cached(&tvnow);
+ flushed = (uint32_t)((tvnow.tv_sec % SECONDS_IN_A_DAY) * 100L +
+ (uint32_t)tvnow.tv_usec / (uint32_t)10000L);
if (!it_queue || !it_queue->first) {
log_info(LD_GENERAL, "Cannot determine insertion time of cell. "
"Looks like the CellStatistics option was "
@@ -2446,7 +2463,7 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
make_circuit_active_on_conn(circ, orconn);
}
- if (! buf_datalen(orconn->_base.outbuf)) {
+ if (! connection_get_outbuf_len(TO_CONN(orconn))) {
/* There is no data at all waiting to be sent on the outbuf. Add a
* cell, so that we can notice when it gets flushed, flushed_some can
* get called, and we can start putting more data onto the buffer then.
diff --git a/src/or/relay.h b/src/or/relay.h
index f64752da5..7fce8edca 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -60,8 +60,8 @@ const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
const uint8_t *payload,
int payload_len);
unsigned cell_ewma_get_tick(void);
-void cell_ewma_set_scale_factor(or_options_t *options,
- networkstatus_t *consensus);
+void cell_ewma_set_scale_factor(const or_options_t *options,
+ const networkstatus_t *consensus);
void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn);
void tor_gettimeofday_cache_clear(void);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 77e11c2a0..b618d0fe4 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -16,16 +16,28 @@
#include "connection_edge.h"
#include "directory.h"
#include "main.h"
+#include "nodelist.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rephist.h"
+#include "router.h"
#include "routerlist.h"
static extend_info_t *rend_client_get_random_intro_impl(
const rend_cache_entry_t *rend_query,
const int strict, const int warnings);
+/** Purge all potentially remotely-detectable state held in the hidden
+ * service client code. Called on SIGNAL NEWNYM. */
+void
+rend_client_purge_state(void)
+{
+ rend_cache_purge();
+ rend_client_cancel_descriptor_fetches();
+ rend_client_purge_last_hid_serv_requests();
+}
+
/** Called when we've established a circuit to an introduction point:
* send the introduction request. */
void
@@ -90,12 +102,13 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ)
if (circ->remaining_relay_early_cells) {
log_info(LD_REND,
"Re-extending circ %d, this time to %s.",
- circ->_base.n_circ_id, extend_info->nickname);
+ circ->_base.n_circ_id,
+ safe_str_client(extend_info_describe(extend_info)));
result = circuit_extend_to_new_exit(circ, extend_info);
} else {
log_info(LD_REND,
"Building a new introduction circuit, this time to %s.",
- extend_info->nickname);
+ safe_str_client(extend_info_describe(extend_info)));
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING,
extend_info,
@@ -132,6 +145,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
tor_assert(rendcirc->rend_data);
tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address,
rendcirc->rend_data->onion_address));
+ tor_assert(!(introcirc->build_state->onehop_tunnel));
+ tor_assert(!(rendcirc->build_state->onehop_tunnel));
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
&entry) < 1) {
@@ -168,7 +183,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
"have a v2 rend desc with %d intro points. "
"Trying a different intro point...",
safe_str_client(introcirc->rend_data->onion_address),
- introcirc->build_state->chosen_exit->nickname,
+ safe_str_client(extend_info_describe(
+ introcirc->build_state->chosen_exit)),
smartlist_len(entry->parsed->intro_nodes));
if (rend_client_reextend_intro_circuit(introcirc)) {
@@ -275,6 +291,10 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
/* Now, we wait for an ACK or NAK on this circuit. */
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
+ /* Set timestamp_dirty, because circuit_expire_building expects it
+ * to specify when a circuit entered the _C_INTRODUCE_ACK_WAIT
+ * state. */
+ introcirc->_base.timestamp_dirty = time(NULL);
return 0;
perm_err:
@@ -317,6 +337,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
}
tor_assert(circ->build_state->chosen_exit);
+ tor_assert(!(circ->build_state->onehop_tunnel));
tor_assert(circ->rend_data);
if (request_len == 0) {
@@ -328,7 +349,12 @@ rend_client_introduction_acked(origin_circuit_t *circ,
rendcirc = circuit_get_by_rend_query_and_purpose(
circ->rend_data->onion_address, CIRCUIT_PURPOSE_C_REND_READY);
if (rendcirc) { /* remember the ack */
+ tor_assert(!(rendcirc->build_state->onehop_tunnel));
rendcirc->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
+ /* Set timestamp_dirty, because circuit_expire_building expects
+ * it to specify when a circuit entered the
+ * _C_REND_READY_INTRO_ACKED state. */
+ rendcirc->_base.timestamp_dirty = time(NULL);
} else {
log_info(LD_REND,"...Found no rend circ. Dropping on the floor.");
}
@@ -343,8 +369,8 @@ rend_client_introduction_acked(origin_circuit_t *circ,
* If none remain, refetch the service descriptor.
*/
log_info(LD_REND, "Got nack for %s from %s...",
- safe_str_client(circ->rend_data->onion_address),
- circ->build_state->chosen_exit->nickname);
+ safe_str_client(circ->rend_data->onion_address),
+ safe_str_client(extend_info_describe(circ->build_state->chosen_exit)));
if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
circ->rend_data) > 0) {
/* There are introduction points left. Re-extend the circuit to
@@ -366,7 +392,17 @@ rend_client_introduction_acked(origin_circuit_t *circ,
* certain queries; keys are strings consisting of base32-encoded
* hidden service directory identities and base32-encoded descriptor IDs;
* values are pointers to timestamps of the last requests. */
-static strmap_t *last_hid_serv_requests = NULL;
+static strmap_t *last_hid_serv_requests_ = NULL;
+
+/** Returns last_hid_serv_requests_, initializing it to a new strmap if
+ * necessary. */
+static strmap_t *
+get_last_hid_serv_requests(void)
+{
+ if (!last_hid_serv_requests_)
+ last_hid_serv_requests_ = strmap_new();
+ return last_hid_serv_requests_;
+}
/** Look up the last request time to hidden service directory <b>hs_dir</b>
* for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
@@ -380,6 +416,7 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir,
char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t *last_request_ptr;
+ strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
hs_dir->identity_digest, DIGEST_LEN);
tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
@@ -401,12 +438,11 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir,
* it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD
* seconds any more. */
static void
-directory_clean_last_hid_serv_requests(void)
+directory_clean_last_hid_serv_requests(time_t now)
{
strmap_iter_t *iter;
- time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
- if (!last_hid_serv_requests)
- last_hid_serv_requests = strmap_new();
+ time_t cutoff = now - REND_HID_SERV_DIR_REQUERY_PERIOD;
+ strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
for (iter = strmap_iter_init(last_hid_serv_requests);
!strmap_iter_done(iter); ) {
const char *key;
@@ -423,6 +459,26 @@ directory_clean_last_hid_serv_requests(void)
}
}
+/** Purge the history of request times to hidden service directories,
+ * so that future lookups of an HS descriptor will not fail because we
+ * accessed all of the HSDir relays responsible for the descriptor
+ * recently. */
+void
+rend_client_purge_last_hid_serv_requests(void)
+{
+ /* Don't create the table if it doesn't exist yet (and it may very
+ * well not exist if the user hasn't accessed any HSes)... */
+ strmap_t *old_last_hid_serv_requests = last_hid_serv_requests_;
+ /* ... and let get_last_hid_serv_requests re-create it for us if
+ * necessary. */
+ last_hid_serv_requests_ = NULL;
+
+ if (old_last_hid_serv_requests != NULL) {
+ log_info(LD_REND, "Purging client last-HS-desc-request-time table");
+ strmap_free(old_last_hid_serv_requests, _tor_free);
+ }
+}
+
/** Determine the responsible hidden service directories for <b>desc_id</b>
* and fetch the descriptor belonging to that ID from one of them. Only
* send a request to hidden service directories that we did not try within
@@ -449,12 +505,14 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
/* Only select those hidden service directories to which we did not send
* a request recently and for which we have a router descriptor here. */
- directory_clean_last_hid_serv_requests(); /* Clean request history first. */
+
+ /* Clean request history first. */
+ directory_clean_last_hid_serv_requests(now);
SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) +
REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
- !router_get_by_digest(dir->identity_digest))
+ !router_get_by_id_digest(dir->identity_digest))
SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
});
@@ -497,12 +555,12 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
log_info(LD_REND, "Sending fetch request for v2 descriptor for "
"service '%s' with descriptor ID '%s', auth type %d, "
"and descriptor cookie '%s' to hidden service "
- "directory '%s' on port %d.",
+ "directory %s",
rend_query->onion_address, desc_id_base32,
rend_query->auth_type,
(rend_query->auth_type == REND_NO_AUTH ? "[none]" :
- escaped_safe_str_client(descriptor_cookie_base64)),
- hs_dir->nickname, hs_dir->dir_port);
+ escaped_safe_str_client(descriptor_cookie_base64)),
+ routerstatus_describe(hs_dir));
return 1;
}
@@ -674,6 +732,9 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request,
log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
"rendezvous.");
circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY;
+ /* Set timestamp_dirty, because circuit_expire_building expects it
+ * to specify when a circuit entered the _C_REND_READY state. */
+ circ->_base.timestamp_dirty = time(NULL);
/* XXXX023 This is a pretty brute-force approach. It'd be better to
* attach only the connections that are waiting on this circuit, rather
* than trying to attach them all. See comments bug 743. */
@@ -846,8 +907,7 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
int i;
rend_intro_point_t *intro;
- routerinfo_t *router;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *usable_nodes;
int n_excluded = 0;
@@ -873,18 +933,19 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
intro = smartlist_get(usable_nodes, i);
/* Do we need to look up the router or is the extend info complete? */
if (!intro->extend_info->onion_key) {
+ const node_t *node;
if (tor_digest_is_zero(intro->extend_info->identity_digest))
- router = router_get_by_hexdigest(intro->extend_info->nickname);
+ node = node_get_by_hex_id(intro->extend_info->nickname);
else
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node) {
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
intro->extend_info->nickname);
smartlist_del(usable_nodes, i);
goto again;
}
extend_info_free(intro->extend_info);
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
}
/* Check if we should refuse to talk to this router. */
if (options->ExcludeNodes && strict &&
@@ -953,7 +1014,8 @@ rend_service_authorization_free_all(void)
* service and add it to the local map of hidden service authorizations.
* Return 0 for success and -1 for failure. */
int
-rend_parse_service_authorization(or_options_t *options, int validate_only)
+rend_parse_service_authorization(const or_options_t *options,
+ int validate_only)
{
config_line_t *line;
int res = -1;
diff --git a/src/or/rendclient.h b/src/or/rendclient.h
index 6910c1a97..1893fd952 100644
--- a/src/or/rendclient.h
+++ b/src/or/rendclient.h
@@ -12,6 +12,8 @@
#ifndef _TOR_RENDCLIENT_H
#define _TOR_RENDCLIENT_H
+void rend_client_purge_state(void);
+
void rend_client_introcirc_has_opened(origin_circuit_t *circ);
void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
int rend_client_introduction_acked(origin_circuit_t *circ,
@@ -19,6 +21,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
size_t request_len);
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
void rend_client_cancel_descriptor_fetches(void);
+void rend_client_purge_last_hid_serv_requests(void);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const rend_data_t *rend_query);
int rend_client_rendezvous_acked(origin_circuit_t *circ,
@@ -34,7 +37,7 @@ int rend_client_any_intro_points_usable(const rend_cache_entry_t *entry);
int rend_client_send_introduction(origin_circuit_t *introcirc,
origin_circuit_t *rendcirc);
-int rend_parse_service_authorization(or_options_t *options,
+int rend_parse_service_authorization(const or_options_t *options,
int validate_only);
rend_service_authorization_t *rend_client_lookup_service_authorization(
const char *onion_address);
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 4d4a90f61..94bb00221 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -814,14 +814,13 @@ rend_cache_free_all(void)
/** Removes all old entries from the service descriptor cache.
*/
void
-rend_cache_clean(void)
+rend_cache_clean(time_t now)
{
strmap_iter_t *iter;
const char *key;
void *val;
rend_cache_entry_t *ent;
- time_t cutoff;
- cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
+ time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) {
strmap_iter_get(iter, &key, &val);
ent = (rend_cache_entry_t*)val;
@@ -839,18 +838,20 @@ rend_cache_clean(void)
void
rend_cache_purge(void)
{
- if (rend_cache)
+ if (rend_cache) {
+ log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache");
strmap_free(rend_cache, _rend_cache_entry_free);
+ }
rend_cache = strmap_new();
}
/** Remove all old v2 descriptors and those for which this hidden service
* directory is not responsible for any more. */
void
-rend_cache_clean_v2_descs_as_dir(void)
+rend_cache_clean_v2_descs_as_dir(time_t now)
{
digestmap_iter_t *iter;
- time_t cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
+ time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
for (iter = digestmap_iter_init(rend_cache_v2_dir);
!digestmap_iter_done(iter); ) {
const char *key;
@@ -982,15 +983,10 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
tor_assert(rend_cache_v2_dir);
if (base32_decode(desc_id_digest, DIGEST_LEN,
desc_id, REND_DESC_ID_V2_LEN_BASE32) < 0) {
- log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
- safe_str(desc_id));
- return -1;
- }
- /* Determine if we are responsible. */
- if (hid_serv_responsible_for_desc_id(desc_id_digest) < 0) {
- log_info(LD_REND, "Could not answer fetch request for v2 descriptor; "
- "either we are no hidden service directory, or we are "
- "not responsible for the requested ID.");
+ log_fn(LOG_PROTOCOL_WARN, LD_REND,
+ "Rejecting v2 rendezvous descriptor request -- descriptor ID "
+ "contains illegal characters: %s",
+ safe_str(desc_id));
return -1;
}
/* Lookup descriptor and return. */
@@ -1044,6 +1040,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
log_warn(LD_REND, "Received service descriptor for service ID %s; "
"expected descriptor for service ID %s.",
query, safe_str(service_id));
+ rend_service_descriptor_free(parsed);
return -2;
}
now = time(NULL);
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index c51039f1f..0d64466db 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -34,8 +34,8 @@ void rend_encoded_v2_service_descriptor_free(
void rend_intro_point_free(rend_intro_point_t *intro);
void rend_cache_init(void);
-void rend_cache_clean(void);
-void rend_cache_clean_v2_descs_as_dir(void);
+void rend_cache_clean(time_t now);
+void rend_cache_clean_v2_descs_as_dir(time_t now);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_valid_service_id(const char *query);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 35e8b9057..4413ae9d8 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -14,6 +14,7 @@
#include "config.h"
#include "directory.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendservice.h"
@@ -181,6 +182,31 @@ rend_add_service(rend_service_t *service)
log_warn(LD_CONFIG, "Hidden service with no ports configured; ignoring.");
rend_service_free(service);
} else {
+ int dupe = 0;
+ /* XXX This duplicate check has two problems:
+ *
+ * a) It's O(n^2), but the same comment from the bottom of
+ * rend_config_services() should apply.
+ *
+ * b) We only compare directory paths as strings, so we can't
+ * detect two distinct paths that specify the same directory
+ * (which can arise from symlinks, case-insensitivity, bind
+ * mounts, etc.).
+ *
+ * It also can't detect that two separate Tor instances are trying
+ * to use the same HiddenServiceDir; for that, we would need a
+ * lock file. But this is enough to detect a simple mistake that
+ * at least one person has actually made.
+ */
+ SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
+ dupe = dupe ||
+ !strcmp(ptr->directory, service->directory));
+ if (dupe) {
+ log_warn(LD_REND, "Another hidden service is already configured for "
+ "directory %s, ignoring.", service->directory);
+ rend_service_free(service);
+ return;
+ }
smartlist_add(rend_service_list, service);
log_debug(LD_REND,"Configuring service with directory \"%s\"",
service->directory);
@@ -266,7 +292,7 @@ parse_port_config(const char *string)
* normal, but don't actually change the configured services.)
*/
int
-rend_config_services(or_options_t *options, int validate_only)
+rend_config_services(const or_options_t *options, int validate_only)
{
config_line_t *line;
rend_service_t *service = NULL;
@@ -474,7 +500,8 @@ rend_config_services(or_options_t *options, int validate_only)
if (keep_it)
continue;
log_info(LD_REND, "Closing intro point %s for service %s.",
- safe_str_client(oc->build_state->chosen_exit->nickname),
+ safe_str_client(extend_info_describe(
+ oc->build_state->chosen_exit)),
oc->rend_data->onion_address);
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
/* XXXX Is there another reason we should use here? */
@@ -543,7 +570,7 @@ rend_service_load_keys(void)
s->directory);
/* Check/create directory */
- if (check_private_dir(s->directory, CPD_CREATE) < 0)
+ if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0)
return -1;
/* Load key */
@@ -876,8 +903,9 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
time_t now = time(NULL);
char diffie_hellman_hash[DIGEST_LEN];
time_t *access_time;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
@@ -1005,7 +1033,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
} else {
char *rp_nickname;
size_t nickname_field_len;
- routerinfo_t *router;
+ const node_t *node;
int version;
if (*buf == 1) {
rp_nickname = buf+1;
@@ -1032,8 +1060,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
len -= nickname_field_len;
len -= rp_nickname - buf; /* also remove header space used by version, if
* any */
- router = router_get_by_nickname(rp_nickname, 0);
- if (!router) {
+ node = node_get_by_nickname(rp_nickname, 0);
+ if (!node) {
log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
escaped_safe_str_client(rp_nickname));
/* XXXX Add a no-such-router reason? */
@@ -1041,7 +1069,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
goto err;
}
- extend_info = extend_info_from_router(router);
+ extend_info = extend_info_from_node(node);
}
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -1146,7 +1174,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
if (!launched) { /* give up */
log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
"point %s for service %s.",
- escaped_safe_str_client(extend_info->nickname),
+ safe_str_client(extend_info_describe(extend_info)),
serviceid);
reason = END_CIRC_REASON_CONNECTFAILED;
goto err;
@@ -1154,7 +1182,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
log_info(LD_REND,
"Accepted intro; launching circuit to %s "
"(cookie %s) for service %s.",
- escaped_safe_str_client(extend_info->nickname),
+ safe_str_client(extend_info_describe(extend_info)),
hexcookie, serviceid);
tor_assert(launched->build_state);
/* Fill in the circuit's state. */
@@ -1206,7 +1234,8 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
"Attempt to build circuit to %s for rendezvous has failed "
"too many times or expired; giving up.",
oldcirc->build_state ?
- oldcirc->build_state->chosen_exit->nickname : "*unknown*");
+ safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
+ : "*unknown*");
return;
}
@@ -1220,7 +1249,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
}
log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
- oldstate->chosen_exit->nickname);
+ safe_str(extend_info_describe(oldstate->chosen_exit)));
newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
oldstate->chosen_exit,
@@ -1228,7 +1257,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
if (!newcirc) {
log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
- oldstate->chosen_exit->nickname);
+ safe_str(extend_info_describe(oldstate->chosen_exit)));
return;
}
newstate = newcirc->build_state;
@@ -1252,7 +1281,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
log_info(LD_REND,
"Launching circuit to introduction point %s for service %s",
- escaped_safe_str_client(intro->extend_info->nickname),
+ safe_str_client(extend_info_describe(intro->extend_info)),
service->service_id);
rep_hist_note_used_internal(time(NULL), 1, 0);
@@ -1265,7 +1294,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
if (!launched) {
log_info(LD_REND,
"Can't launch circuit to establish introduction at %s.",
- escaped_safe_str_client(intro->extend_info->nickname));
+ safe_str_client(extend_info_describe(intro->extend_info)));
return -1;
}
@@ -1331,6 +1360,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
crypto_pk_env_t *intro_key;
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->cpath);
tor_assert(circuit->rend_data);
@@ -1349,7 +1379,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
/* If we already have enough introduction circuits for this service,
* redefine this one as a general circuit or close it, depending. */
if (count_established_intro_points(serviceid) > NUM_INTRO_POINTS) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ExcludeNodes) {
/* XXXX in some future version, we can test whether the transition is
allowed or not given the actual nodes in the circuit. But for now,
@@ -1473,6 +1503,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
hop = circuit->build_state->pending_final_cpath;
tor_assert(hop);
@@ -1606,11 +1637,11 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
hs_dir->identity_digest))
/* Don't upload descriptor if we succeeded in doing so last time. */
continue;
- if (!router_get_by_digest(hs_dir->identity_digest)) {
+ if (!router_get_by_id_digest(hs_dir->identity_digest)) {
log_info(LD_REND, "Not sending publish request for v2 descriptor to "
- "hidden service directory '%s'; we don't have its "
+ "hidden service directory %s; we don't have its "
"router descriptor. Queuing for later upload.",
- hs_dir->nickname);
+ safe_str_client(routerstatus_describe(hs_dir)));
failed_upload = -1;
continue;
}
@@ -1783,19 +1814,19 @@ void
rend_services_introduce(void)
{
int i,j,r;
- routerinfo_t *router;
+ const node_t *node;
rend_service_t *service;
rend_intro_point_t *intro;
int changed, prev_intro_nodes;
- smartlist_t *intro_routers;
+ smartlist_t *intro_nodes;
time_t now;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
- intro_routers = smartlist_create();
+ intro_nodes = smartlist_create();
now = time(NULL);
for (i=0; i < smartlist_len(rend_service_list); ++i) {
- smartlist_clear(intro_routers);
+ smartlist_clear(intro_nodes);
service = smartlist_get(rend_service_list, i);
tor_assert(service);
@@ -1815,10 +1846,11 @@ rend_services_introduce(void)
service. */
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router || !find_intro_circuit(intro, service->pk_digest)) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node || !find_intro_circuit(intro, service->pk_digest)) {
log_info(LD_REND,"Giving up on %s as intro point for %s.",
- intro->extend_info->nickname, service->service_id);
+ safe_str_client(extend_info_describe(intro->extend_info)),
+ safe_str_client(service->service_id));
if (service->desc) {
SMARTLIST_FOREACH(service->desc->intro_nodes, rend_intro_point_t *,
dintro, {
@@ -1835,8 +1867,8 @@ rend_services_introduce(void)
smartlist_del(service->intro_nodes,j--);
changed = 1;
}
- if (router)
- smartlist_add(intro_routers, router);
+ if (node)
+ smartlist_add(intro_nodes, (void*)node);
}
/* We have enough intro points, and the intro points we thought we had were
@@ -1865,26 +1897,27 @@ rend_services_introduce(void)
#define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
- router_crn_flags_t flags = CRN_NEED_UPTIME;
+ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
flags |= CRN_ALLOW_INVALID;
- router = router_choose_random_node(intro_routers,
- options->ExcludeNodes, flags);
- if (!router) {
+ node = router_choose_random_node(intro_nodes,
+ options->ExcludeNodes, flags);
+ if (!node) {
log_warn(LD_REND,
"Could only establish %d introduction points for %s.",
smartlist_len(service->intro_nodes), service->service_id);
break;
}
changed = 1;
- smartlist_add(intro_routers, router);
+ smartlist_add(intro_nodes, (void*)node);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
- router->nickname, service->service_id);
+ safe_str_client(node_describe(node)),
+ safe_str_client(service->service_id));
}
/* If there's no need to launch new circuits, stop here. */
@@ -1897,11 +1930,12 @@ rend_services_introduce(void)
r = rend_service_launch_establish_intro(service, intro);
if (r<0) {
log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
- intro->extend_info->nickname, service->service_id);
+ safe_str_client(extend_info_describe(intro->extend_info)),
+ safe_str_client(service->service_id));
}
}
}
- smartlist_free(intro_routers);
+ smartlist_free(intro_nodes);
}
/** Regenerate and upload rendezvous service descriptors for all
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index 70389afe9..8a2994c4c 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -13,7 +13,7 @@
#define _TOR_RENDSERVICE_H
int num_rend_services(void);
-int rend_config_services(or_options_t *options, int validate_only);
+int rend_config_services(const or_options_t *options, int validate_only);
int rend_service_load_keys(void);
void rend_services_introduce(void);
void rend_consider_services_upload(time_t now);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 8cddd2b5e..cd74f1b72 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -7,7 +7,7 @@
* \brief Basic history and "reputation" functionality to remember
* which servers have worked in the past, how much bandwidth we've
* been using, which ports we tend to want, and so on; further,
- * exit port statistics and cell statistics.
+ * exit port statistics, cell statistics, and connection statistics.
**/
#include "or.h"
@@ -15,6 +15,7 @@
#include "circuituse.h"
#include "config.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
@@ -634,6 +635,7 @@ rep_hist_dump_stats(time_t now, int severity)
digestmap_iter_t *orhist_it;
const char *name1, *name2, *digest1, *digest2;
char hexdigest1[HEX_DIGEST_LEN+1];
+ char hexdigest2[HEX_DIGEST_LEN+1];
or_history_t *or_history;
link_history_t *link_history;
void *or_history_p, *link_history_p;
@@ -642,7 +644,7 @@ rep_hist_dump_stats(time_t now, int severity)
size_t len;
int ret;
unsigned long upt, downt;
- routerinfo_t *r;
+ const node_t *node;
rep_history_clean(now - get_options()->RephistTrackTime);
@@ -656,8 +658,8 @@ rep_hist_dump_stats(time_t now, int severity)
digestmap_iter_get(orhist_it, &digest1, &or_history_p);
or_history = (or_history_t*) or_history_p;
- if ((r = router_get_by_digest(digest1)))
- name1 = r->nickname;
+ if ((node = node_get_by_id(digest1)) && node_get_nickname(node))
+ name1 = node_get_nickname(node);
else
name1 = "(unknown)";
base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
@@ -687,14 +689,17 @@ rep_hist_dump_stats(time_t now, int severity)
lhist_it = digestmap_iter_next(or_history->link_history_map,
lhist_it)) {
digestmap_iter_get(lhist_it, &digest2, &link_history_p);
- if ((r = router_get_by_digest(digest2)))
- name2 = r->nickname;
+ if ((node = node_get_by_id(digest2)) && node_get_nickname(node))
+ name2 = node_get_nickname(node);
else
name2 = "(unknown)";
link_history = (link_history_t*) link_history_p;
- ret = tor_snprintf(buffer+len, 2048-len, "%s(%ld/%ld); ", name2,
+ base16_encode(hexdigest2, sizeof(hexdigest2), digest2, DIGEST_LEN);
+ ret = tor_snprintf(buffer+len, 2048-len, "%s [%s](%ld/%ld); ",
+ name2,
+ hexdigest2,
link_history->n_extend_ok,
link_history->n_extend_ok+link_history->n_extend_fail);
if (ret<0)
@@ -819,7 +824,7 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down)
base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN);
if (missing_means_down && hist->start_of_run &&
- !router_get_by_digest(digest)) {
+ !router_get_by_id_digest(digest)) {
/* We think this relay is running, but it's not listed in our
* routerlist. Somehow it fell out without telling us it went
* down. Complain and also correct it. */
@@ -934,28 +939,32 @@ rep_hist_get_router_stability_doc(time_t now)
}
DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
- routerinfo_t *ri;
+ const node_t *node;
char dbuf[BASE64_DIGEST_LEN+1];
char header_buf[512];
char *info;
digest_to_base64(dbuf, id);
- ri = router_get_by_digest(id);
- if (ri) {
- char *ip = tor_dup_ip(ri->addr);
+ node = node_get_by_id(id);
+ if (node) {
+ char ip[INET_NTOA_BUF_LEN+1];
char tbuf[ISO_TIME_LEN+1];
- format_iso_time(tbuf, ri->cache_info.published_on);
+ time_t published = node_get_published_on(node);
+ node_get_address_string(node,ip,sizeof(ip));
+ if (published > 0)
+ format_iso_time(tbuf, published);
+ else
+ strlcpy(tbuf, "???", sizeof(tbuf));
tor_snprintf(header_buf, sizeof(header_buf),
"router %s %s %s\n"
"published %s\n"
"relevant-flags %s%s%s\n"
"declared-uptime %ld\n",
- dbuf, ri->nickname, ip,
+ dbuf, node_get_nickname(node), ip,
tbuf,
- ri->is_running ? "Running " : "",
- ri->is_valid ? "Valid " : "",
- ri->is_hibernating ? "Hibernating " : "",
- ri->uptime);
- tor_free(ip);
+ node->is_running ? "Running " : "",
+ node->is_valid ? "Valid " : "",
+ node->ri && node->ri->is_hibernating ? "Hibernating " : "",
+ node_get_declared_uptime(node));
} else {
tor_snprintf(header_buf, sizeof(header_buf),
"router %s {no descriptor}\n", dbuf);
@@ -1470,7 +1479,7 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b)
{
char *cp = buf;
int i, n;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
uint64_t cutoff;
if (b->num_maxes_set <= b->next_max_idx) {
@@ -1766,10 +1775,13 @@ rep_hist_load_state(or_state_t *state, char **err)
/*********************************************************************/
+typedef struct predicted_port_t {
+ uint16_t port;
+ time_t time;
+} predicted_port_t;
+
/** A list of port numbers that have been used recently. */
static smartlist_t *predicted_ports_list=NULL;
-/** The corresponding most recently used time for each port. */
-static smartlist_t *predicted_ports_times=NULL;
/** We just got an application request for a connection with
* port <b>port</b>. Remember it for the future, so we can keep
@@ -1778,14 +1790,11 @@ static smartlist_t *predicted_ports_times=NULL;
static void
add_predicted_port(time_t now, uint16_t port)
{
- /* XXXX we could just use uintptr_t here, I think. -NM */
- uint16_t *tmp_port = tor_malloc(sizeof(uint16_t));
- time_t *tmp_time = tor_malloc(sizeof(time_t));
- *tmp_port = port;
- *tmp_time = now;
- rephist_total_alloc += sizeof(uint16_t) + sizeof(time_t);
- smartlist_add(predicted_ports_list, tmp_port);
- smartlist_add(predicted_ports_times, tmp_time);
+ predicted_port_t *pp = tor_malloc(sizeof(predicted_port_t));
+ pp->port = port;
+ pp->time = now;
+ rephist_total_alloc += sizeof(*pp);
+ smartlist_add(predicted_ports_list, pp);
}
/** Initialize whatever memory and structs are needed for predicting
@@ -1796,7 +1805,6 @@ static void
predicted_ports_init(void)
{
predicted_ports_list = smartlist_create();
- predicted_ports_times = smartlist_create();
add_predicted_port(time(NULL), 80); /* add one to kickstart us */
}
@@ -1806,12 +1814,11 @@ predicted_ports_init(void)
static void
predicted_ports_free(void)
{
- rephist_total_alloc -= smartlist_len(predicted_ports_list)*sizeof(uint16_t);
- SMARTLIST_FOREACH(predicted_ports_list, char *, cp, tor_free(cp));
+ rephist_total_alloc -=
+ smartlist_len(predicted_ports_list)*sizeof(predicted_port_t);
+ SMARTLIST_FOREACH(predicted_ports_list, predicted_port_t *,
+ pp, tor_free(pp));
smartlist_free(predicted_ports_list);
- rephist_total_alloc -= smartlist_len(predicted_ports_times)*sizeof(time_t);
- SMARTLIST_FOREACH(predicted_ports_times, char *, cp, tor_free(cp));
- smartlist_free(predicted_ports_times);
}
/** Remember that <b>port</b> has been asked for as of time <b>now</b>.
@@ -1821,24 +1828,17 @@ predicted_ports_free(void)
void
rep_hist_note_used_port(time_t now, uint16_t port)
{
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
-
tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
if (!port) /* record nothing */
return;
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_port == port) {
- *tmp_time = now;
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (pp->port == port) {
+ pp->time = now;
return;
}
- }
+ } SMARTLIST_FOREACH_END(pp);
/* it's not there yet; we need to add it */
add_predicted_port(now, port);
}
@@ -1847,36 +1847,28 @@ rep_hist_note_used_port(time_t now, uint16_t port)
* we'll want to make connections to the same port in the future. */
#define PREDICTED_CIRCS_RELEVANCE_TIME (60*60)
-/** Return a pointer to the list of port numbers that
+/** Return a newly allocated pointer to a list of uint16_t * for ports that
* are likely to be asked for in the near future.
- *
- * The caller promises not to mess with it.
*/
smartlist_t *
rep_hist_get_predicted_ports(time_t now)
{
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
-
+ smartlist_t *out = smartlist_create();
tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
/* clean out obsolete entries */
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- log_debug(LD_CIRC, "Expiring predicted port %d", *tmp_port);
- smartlist_del(predicted_ports_list, i);
- smartlist_del(predicted_ports_times, i);
- rephist_total_alloc -= sizeof(uint16_t)+sizeof(time_t);
- tor_free(tmp_port);
- tor_free(tmp_time);
- i--;
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (pp->time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
+ log_debug(LD_CIRC, "Expiring predicted port %d", pp->port);
+
+ rephist_total_alloc -= sizeof(predicted_port_t);
+ tor_free(pp);
+ SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
+ } else {
+ smartlist_add(out, tor_memdup(&pp->port, sizeof(uint16_t)));
}
- }
- return predicted_ports_list;
+ } SMARTLIST_FOREACH_END(pp);
+ return out;
}
/** The user asked us to do a resolve. Rather than keeping track of
@@ -2112,7 +2104,9 @@ rep_hist_exit_stats_term(void)
tor_free(exit_streams);
}
-/** Helper for qsort: compare two ints. */
+/** Helper for qsort: compare two ints. Does not handle overflow properly,
+ * but works fine for sorting an array of port numbers, which is what we use
+ * it for. */
static int
_compare_int(const void *x, const void *y)
{
@@ -2303,7 +2297,7 @@ rep_hist_exit_stats_write(time_t now)
/* Try to write to disk. */
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE) < 0) {
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
log_warn(LD_HIST, "Unable to create stats/ directory!");
goto done;
}
@@ -2387,8 +2381,8 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
return;
if (!circuits_for_buffer_stats)
circuits_for_buffer_stats = smartlist_create();
- start_of_interval = circ->timestamp_created.tv_sec >
- start_of_buffer_stats_interval ?
+ start_of_interval = (circ->timestamp_created.tv_sec >
+ start_of_buffer_stats_interval) ?
circ->timestamp_created.tv_sec :
start_of_buffer_stats_interval;
interval_length = (int) (end_of_interval - start_of_interval);
@@ -2397,8 +2391,7 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
stat = tor_malloc_zero(sizeof(circ_buffer_stats_t));
stat->processed_cells = orcirc->processed_cells;
/* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */
- stat->mean_num_cells_in_queue = interval_length == 0 ? 0.0 :
- (double) orcirc->total_cell_waiting_time /
+ stat->mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time /
(double) interval_length / 1000.0 / 2.0;
stat->mean_time_cells_in_queue =
(double) orcirc->total_cell_waiting_time /
@@ -2448,8 +2441,8 @@ rep_hist_buffer_stats_write(time_t now)
int processed_cells[SHARES], circs_in_share[SHARES],
number_of_circuits, i;
double queued_cells[SHARES], time_in_queue[SHARES];
- smartlist_t *str_build = smartlist_create();
- char *str = NULL, *buf=NULL;
+ smartlist_t *str_build = NULL;
+ char *str = NULL, *buf = NULL;
circuit_t *circ;
if (!start_of_buffer_stats_interval)
@@ -2457,6 +2450,8 @@ rep_hist_buffer_stats_write(time_t now)
if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
goto done; /* Not ready to write */
+ str_build = smartlist_create();
+
/* add current circuits to stats */
for (circ = _circuit_get_global_list(); circ; circ = circ->next)
rep_hist_buffer_stats_add_circ(circ, now);
@@ -2492,7 +2487,7 @@ rep_hist_buffer_stats_write(time_t now)
smartlist_clear(circuits_for_buffer_stats);
/* write to file */
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE) < 0)
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
goto done;
filename = get_datadir_fname2("stats", "buffer-stats");
out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
@@ -2557,6 +2552,227 @@ rep_hist_buffer_stats_write(time_t now)
return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
}
+/*** Connection statistics ***/
+
+/** Start of the current connection stats interval or 0 if we're not
+ * collecting connection statistics. */
+static time_t start_of_conn_stats_interval;
+
+/** Initialize connection stats. */
+void
+rep_hist_conn_stats_init(time_t now)
+{
+ start_of_conn_stats_interval = now;
+}
+
+/* Count connections that we read and wrote less than these many bytes
+ * from/to as below threshold. */
+#define BIDI_THRESHOLD 20480
+
+/* Count connections that we read or wrote at least this factor as many
+ * bytes from/to than we wrote or read to/from as mostly reading or
+ * writing. */
+#define BIDI_FACTOR 10
+
+/* Interval length in seconds for considering read and written bytes for
+ * connection stats. */
+#define BIDI_INTERVAL 10
+
+/* Start of next BIDI_INTERVAL second interval. */
+static time_t bidi_next_interval = 0;
+
+/* Number of connections that we read and wrote less than BIDI_THRESHOLD
+ * bytes from/to in BIDI_INTERVAL seconds. */
+static uint32_t below_threshold = 0;
+
+/* Number of connections that we read at least BIDI_FACTOR times more
+ * bytes from than we wrote to in BIDI_INTERVAL seconds. */
+static uint32_t mostly_read = 0;
+
+/* Number of connections that we wrote at least BIDI_FACTOR times more
+ * bytes to than we read from in BIDI_INTERVAL seconds. */
+static uint32_t mostly_written = 0;
+
+/* Number of connections that we read and wrote at least BIDI_THRESHOLD
+ * bytes from/to, but not BIDI_FACTOR times more in either direction in
+ * BIDI_INTERVAL seconds. */
+static uint32_t both_read_and_written = 0;
+
+/* Entry in a map from connection ID to the number of read and written
+ * bytes on this connection in a BIDI_INTERVAL second interval. */
+typedef struct bidi_map_entry_t {
+ HT_ENTRY(bidi_map_entry_t) node;
+ uint64_t conn_id; /**< Connection ID */
+ size_t read; /**< Number of read bytes */
+ size_t written; /**< Number of written bytes */
+} bidi_map_entry_t;
+
+/** Map of OR connections together with the number of read and written
+ * bytes in the current BIDI_INTERVAL second interval. */
+static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map =
+ HT_INITIALIZER();
+
+static int
+bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b)
+{
+ return a->conn_id == b->conn_id;
+}
+
+static unsigned
+bidi_map_ent_hash(const bidi_map_entry_t *entry)
+{
+ return (unsigned) entry->conn_id;
+}
+
+HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq);
+HT_GENERATE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq, 0.6, malloc, realloc, free);
+
+static void
+bidi_map_free(void)
+{
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ HT_CLEAR(bidimap, &bidi_map);
+}
+
+/** Reset counters for conn statistics. */
+void
+rep_hist_reset_conn_stats(time_t now)
+{
+ start_of_conn_stats_interval = now;
+ below_threshold = 0;
+ mostly_read = 0;
+ mostly_written = 0;
+ both_read_and_written = 0;
+ bidi_map_free();
+}
+
+/** Stop collecting connection stats in a way that we can re-start doing
+ * so in rep_hist_conn_stats_init(). */
+void
+rep_hist_conn_stats_term(void)
+{
+ rep_hist_reset_conn_stats(0);
+}
+
+/** We read <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
+ * connection <b>conn_id</b> in second <b>when</b>. If this is the first
+ * observation in a new interval, sum up the last observations. Add bytes
+ * for this connection. */
+void
+rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when)
+{
+ if (!start_of_conn_stats_interval)
+ return;
+ /* Initialize */
+ if (bidi_next_interval == 0)
+ bidi_next_interval = when + BIDI_INTERVAL;
+ /* Sum up last period's statistics */
+ if (when >= bidi_next_interval) {
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ if (ent->read + ent->written < BIDI_THRESHOLD)
+ below_threshold++;
+ else if (ent->read >= ent->written * BIDI_FACTOR)
+ mostly_read++;
+ else if (ent->written >= ent->read * BIDI_FACTOR)
+ mostly_written++;
+ else
+ both_read_and_written++;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ while (when >= bidi_next_interval)
+ bidi_next_interval += BIDI_INTERVAL;
+ log_info(LD_GENERAL, "%d below threshold, %d mostly read, "
+ "%d mostly written, %d both read and written.",
+ below_threshold, mostly_read, mostly_written,
+ both_read_and_written);
+ }
+ /* Add this connection's bytes. */
+ if (num_read > 0 || num_written > 0) {
+ bidi_map_entry_t *entry, lookup;
+ lookup.conn_id = conn_id;
+ entry = HT_FIND(bidimap, &bidi_map, &lookup);
+ if (entry) {
+ entry->written += num_written;
+ entry->read += num_read;
+ } else {
+ entry = tor_malloc_zero(sizeof(bidi_map_entry_t));
+ entry->conn_id = conn_id;
+ entry->written = num_written;
+ entry->read = num_read;
+ HT_INSERT(bidimap, &bidi_map, entry);
+ }
+ }
+}
+
+/** Return a newly allocated string containing the connection statistics
+ * until <b>now</b>, or NULL if we're not collecting conn stats. */
+char *
+rep_hist_format_conn_stats(time_t now)
+{
+ char *result, written[ISO_TIME_LEN+1];
+
+ if (!start_of_conn_stats_interval)
+ return NULL; /* Not initialized. */
+
+ format_iso_time(written, now);
+ tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n",
+ written,
+ (unsigned) (now - start_of_conn_stats_interval),
+ below_threshold,
+ mostly_read,
+ mostly_written,
+ both_read_and_written);
+ return result;
+}
+
+/** If 24 hours have passed since the beginning of the current conn stats
+ * period, write conn stats to $DATADIR/stats/conn-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write conn stats or 0 if we never want to write. */
+time_t
+rep_hist_conn_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_conn_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write */
+
+ /* Generate history string. */
+ str = rep_hist_format_conn_stats(now);
+
+ /* Reset counters. */
+ rep_hist_reset_conn_stats(now);
+
+ /* Try to write to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
+ goto done;
+ }
+ filename = get_datadir_fname2("stats", "conn-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write conn stats to disk!");
+
+ done:
+ tor_free(str);
+ tor_free(filename);
+ tor_free(statsdir);
+ return start_of_conn_stats_interval + WRITE_STATS_INTERVAL;
+}
+
/** Free all storage held by the OR/link history caches, by the
* bandwidth history arrays, by the port history, or by statistics . */
void
@@ -2571,6 +2787,8 @@ rep_hist_free_all(void)
tor_free(exit_streams);
built_last_stability_doc_at = 0;
predicted_ports_free();
+ bidi_map_free();
+
if (circuits_for_buffer_stats) {
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, s,
tor_free(s));
diff --git a/src/or/rephist.h b/src/or/rephist.h
index b06a39ed5..5748748a8 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -78,5 +78,13 @@ void rep_hist_buffer_stats_add_circ(circuit_t *circ,
time_t rep_hist_buffer_stats_write(time_t now);
void rep_hist_buffer_stats_term(void);
+void rep_hist_conn_stats_init(time_t now);
+void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when);
+void rep_hist_reset_conn_stats(time_t now);
+char *rep_hist_format_conn_stats(time_t now);
+time_t rep_hist_conn_stats_write(time_t now);
+void rep_hist_conn_stats_term(void);
+
#endif
diff --git a/src/or/router.c b/src/or/router.c
index f6728aac9..eaad57bb9 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -7,6 +7,7 @@
#define ROUTER_PRIVATE
#include "or.h"
+#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
#include "config.h"
@@ -19,6 +20,7 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "relay.h"
#include "rephist.h"
@@ -154,8 +156,8 @@ assert_identity_keys_ok(void)
} else {
/* assert that we have set the client and server keys to be unequal */
if (server_identitykey)
- tor_assert(0!=crypto_pk_cmp_keys(client_identitykey,
- server_identitykey));
+ tor_assert(0!=crypto_pk_cmp_keys(client_identitykey,
+ server_identitykey));
}
}
@@ -498,8 +500,8 @@ init_keys(void)
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
char *cp;
- or_options_t *options = get_options();
- authority_type_t type;
+ const or_options_t *options = get_options();
+ dirinfo_type_t type;
time_t now = time(NULL);
trusted_dir_server_t *ds;
int v3_digest_set = 0;
@@ -538,12 +540,12 @@ init_keys(void)
return 0;
}
/* Make sure DataDirectory exists, and is private. */
- if (check_private_dir(options->DataDirectory, CPD_CREATE)) {
+ if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) {
return -1;
}
/* Check the key directory. */
keydir = get_datadir_fname("keys");
- if (check_private_dir(keydir, CPD_CREATE)) {
+ if (check_private_dir(keydir, CPD_CREATE, options->User)) {
tor_free(keydir);
return -1;
}
@@ -700,16 +702,17 @@ init_keys(void)
}
/* 6b. [authdirserver only] add own key to approved directories. */
crypto_pk_get_digest(get_server_identity_key(), digest);
- type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) |
- (options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) |
- (options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) |
- (options->BridgeAuthoritativeDir ? BRIDGE_AUTHORITY : NO_AUTHORITY) |
- (options->HSAuthoritativeDir ? HIDSERV_AUTHORITY : NO_AUTHORITY));
+ type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
+ (options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
+ (options->V3AuthoritativeDir ?
+ (V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
+ (options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) |
+ (options->HSAuthoritativeDir ? HIDSERV_DIRINFO : NO_DIRINFO));
ds = router_get_trusteddirserver_by_digest(digest);
if (!ds) {
ds = add_trusted_dir_server(options->Nickname, NULL,
- router_get_advertised_dir_port(options),
+ router_get_advertised_dir_port(options, 0),
router_get_advertised_or_port(options),
digest,
v3_digest,
@@ -726,7 +729,7 @@ init_keys(void)
type, ds->type);
ds->type = type;
}
- if (v3_digest_set && (ds->type & V3_AUTHORITY) &&
+ if (v3_digest_set && (ds->type & V3_DIRINFO) &&
tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
log_warn(LD_DIR, "V3 identity key does not match identity declared in "
"DirServer line. Adjusting.");
@@ -765,7 +768,7 @@ router_reset_reachability(void)
int
check_whether_orport_reachable(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return options->AssumeReachable ||
can_reach_or_port;
}
@@ -774,7 +777,7 @@ check_whether_orport_reachable(void)
int
check_whether_dirport_reachable(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return !options->DirPort ||
options->AssumeReachable ||
we_are_hibernating() ||
@@ -789,7 +792,7 @@ check_whether_dirport_reachable(void)
* a DirPort.
*/
static int
-decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
+decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
{
static int advertising=1; /* start out assuming we will advertise */
int new_choice=1;
@@ -807,6 +810,8 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
return 0;
if (!check_whether_dirport_reachable())
return 0;
+ if (!router_get_advertised_dir_port(options, dir_port))
+ return 0;
/* Section two: reasons to publish or not publish that the user
* might find surprising. These are generally config options that
@@ -852,14 +857,14 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
void
consider_testing_reachability(int test_or, int test_dir)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
int orport_reachable = check_whether_orport_reachable();
tor_addr_t addr;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!me)
return;
- if (routerset_contains_router(options->ExcludeNodes, me) &&
+ if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
options->StrictNodes) {
/* If we've excluded ourself, and StrictNodes is set, we can't test
* ourself. */
@@ -879,11 +884,14 @@ consider_testing_reachability(int test_or, int test_dir)
}
if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
+ extend_info_t *ei;
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port);
- circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
- CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ ei = extend_info_from_router(me);
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ extend_info_free(ei);
}
tor_addr_from_ipv4h(&addr, me->addr);
@@ -906,11 +914,11 @@ consider_testing_reachability(int test_or, int test_dir)
void
router_orport_found_reachable(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_or_port && me) {
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
- get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
+ get_options()->_PublishServerDescriptor != NO_DIRINFO ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty("ORPort found reachable");
@@ -924,7 +932,7 @@ router_orport_found_reachable(void)
void
router_dirport_found_reachable(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_dir_port && me) {
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.");
@@ -970,7 +978,7 @@ router_perform_bandwidth_test(int num_circs, time_t now)
* directory server.
*/
int
-authdir_mode(or_options_t *options)
+authdir_mode(const or_options_t *options)
{
return options->AuthoritativeDir != 0;
}
@@ -978,7 +986,7 @@ authdir_mode(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v1(or_options_t *options)
+authdir_mode_v1(const or_options_t *options)
{
return authdir_mode(options) && options->V1AuthoritativeDir != 0;
}
@@ -986,7 +994,7 @@ authdir_mode_v1(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v2(or_options_t *options)
+authdir_mode_v2(const or_options_t *options)
{
return authdir_mode(options) && options->V2AuthoritativeDir != 0;
}
@@ -994,13 +1002,13 @@ authdir_mode_v2(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v3(or_options_t *options)
+authdir_mode_v3(const or_options_t *options)
{
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
/** Return true iff we are a v1, v2, or v3 directory authority. */
int
-authdir_mode_any_main(or_options_t *options)
+authdir_mode_any_main(const or_options_t *options)
{
return options->V1AuthoritativeDir ||
options->V2AuthoritativeDir ||
@@ -1009,7 +1017,7 @@ authdir_mode_any_main(or_options_t *options)
/** Return true if we believe ourselves to be any kind of
* authoritative directory beyond just a hidserv authority. */
int
-authdir_mode_any_nonhidserv(or_options_t *options)
+authdir_mode_any_nonhidserv(const or_options_t *options)
{
return options->BridgeAuthoritativeDir ||
authdir_mode_any_main(options);
@@ -1018,7 +1026,7 @@ authdir_mode_any_nonhidserv(or_options_t *options)
* authoritative about receiving and serving descriptors of type
* <b>purpose</b> its dirport. Use -1 for "any purpose". */
int
-authdir_mode_handles_descs(or_options_t *options, int purpose)
+authdir_mode_handles_descs(const or_options_t *options, int purpose)
{
if (purpose < 0)
return authdir_mode_any_nonhidserv(options);
@@ -1033,7 +1041,7 @@ authdir_mode_handles_descs(or_options_t *options, int purpose)
* publishes its own network statuses.
*/
int
-authdir_mode_publishes_statuses(or_options_t *options)
+authdir_mode_publishes_statuses(const or_options_t *options)
{
if (authdir_mode_bridge(options))
return 0;
@@ -1043,7 +1051,7 @@ authdir_mode_publishes_statuses(or_options_t *options)
* tests reachability of the descriptors it learns about.
*/
int
-authdir_mode_tests_reachability(or_options_t *options)
+authdir_mode_tests_reachability(const or_options_t *options)
{
return authdir_mode_handles_descs(options, -1);
}
@@ -1051,7 +1059,7 @@ authdir_mode_tests_reachability(or_options_t *options)
* directory server.
*/
int
-authdir_mode_bridge(or_options_t *options)
+authdir_mode_bridge(const or_options_t *options)
{
return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
}
@@ -1059,7 +1067,7 @@ authdir_mode_bridge(or_options_t *options)
/** Return true iff we are trying to be a server.
*/
int
-server_mode(or_options_t *options)
+server_mode(const or_options_t *options)
{
if (options->ClientOnly) return 0;
return (options->ORPort != 0 || options->ORListenAddress);
@@ -1068,7 +1076,7 @@ server_mode(or_options_t *options)
/** Return true iff we are trying to be a non-bridge server.
*/
int
-public_server_mode(or_options_t *options)
+public_server_mode(const or_options_t *options)
{
if (!server_mode(options)) return 0;
return (!options->BridgeRelay);
@@ -1078,10 +1086,10 @@ public_server_mode(or_options_t *options)
* in the consensus mean that we don't want to allow exits from circuits
* we got from addresses not known to be servers. */
int
-should_refuse_unknown_exits(or_options_t *options)
+should_refuse_unknown_exits(const or_options_t *options)
{
- if (options->RefuseUnknownExits_ != -1) {
- return options->RefuseUnknownExits_;
+ if (options->RefuseUnknownExits != -1) {
+ return options->RefuseUnknownExits;
} else {
return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1);
}
@@ -1110,7 +1118,7 @@ set_server_advertised(int s)
/** Return true iff we are trying to be a socks proxy. */
int
-proxy_mode(or_options_t *options)
+proxy_mode(const or_options_t *options)
{
return (options->SocksPort != 0 ||
options->TransPort != 0 ||
@@ -1131,16 +1139,18 @@ proxy_mode(or_options_t *options)
static int
decide_if_publishable_server(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ClientOnly)
return 0;
- if (options->_PublishServerDescriptor == NO_AUTHORITY)
+ if (options->_PublishServerDescriptor == NO_DIRINFO)
return 0;
if (!server_mode(options))
return 0;
if (authdir_mode(options))
return 1;
+ if (!router_get_advertised_or_port(options))
+ return 0;
return check_whether_orport_reachable();
}
@@ -1174,7 +1184,7 @@ consider_publishable_server(int force)
* the one configured in the ORPort option, or the one we actually bound to
* if ORPort is "auto". */
uint16_t
-router_get_advertised_or_port(or_options_t *options)
+router_get_advertised_or_port(const or_options_t *options)
{
if (options->ORPort == CFG_AUTO_PORT) {
connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER);
@@ -1185,12 +1195,16 @@ router_get_advertised_or_port(or_options_t *options)
return options->ORPort;
}
-/** Return the port that we should advertise as our DirPort; this is either
- * the one configured in the DirPort option, or the one we actually bound to
- * if DirPort is "auto". */
+/** Return the port that we should advertise as our DirPort;
+ * this is one of three possibilities:
+ * The one that is passed as <b>dirport</b> if the DirPort option is 0, or
+ * the one configured in the DirPort option,
+ * or the one we actually bound to if DirPort is "auto". */
uint16_t
-router_get_advertised_dir_port(or_options_t *options)
+router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
{
+ if (!options->DirPort)
+ return dirport;
if (options->DirPort == CFG_AUTO_PORT) {
connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER);
if (c)
@@ -1221,11 +1235,11 @@ static int desc_needs_upload = 0;
void
router_upload_dir_desc_to_dirservers(int force)
{
- routerinfo_t *ri;
+ const routerinfo_t *ri;
extrainfo_t *ei;
char *msg;
size_t desc_len, extra_len = 0, total_len;
- authority_type_t auth = get_options()->_PublishServerDescriptor;
+ dirinfo_type_t auth = get_options()->_PublishServerDescriptor;
ri = router_get_my_routerinfo();
if (!ri) {
@@ -1233,7 +1247,7 @@ router_upload_dir_desc_to_dirservers(int force)
return;
}
ei = router_get_my_extrainfo();
- if (auth == NO_AUTHORITY)
+ if (auth == NO_DIRINFO)
return;
if (!force && !desc_needs_upload)
return;
@@ -1254,7 +1268,7 @@ router_upload_dir_desc_to_dirservers(int force)
msg[desc_len+extra_len] = 0;
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
- (auth & BRIDGE_AUTHORITY) ?
+ (auth & BRIDGE_DIRINFO) ?
ROUTER_PURPOSE_BRIDGE :
ROUTER_PURPOSE_GENERAL,
auth, msg, desc_len, extra_len);
@@ -1319,7 +1333,7 @@ router_extrainfo_digest_is_me(const char *digest)
/** A wrapper around router_digest_is_me(). */
int
-router_is_me(routerinfo_t *router)
+router_is_me(const routerinfo_t *router)
{
return router_digest_is_me(router->cache_info.identity_digest);
}
@@ -1338,7 +1352,7 @@ router_fingerprint_is_me(const char *fp)
/** Return a routerinfo for this OR, rebuilding a fresh one if
* necessary. Return NULL on error, or if called on an OP. */
-routerinfo_t *
+const routerinfo_t *
router_get_my_routerinfo(void)
{
if (!server_mode(get_options()))
@@ -1388,10 +1402,8 @@ static int router_guess_address_from_dir_headers(uint32_t *guess);
* dirserver headers. Place the answer in *<b>addr</b> and return
* 0 on success, else return -1 if we have no guess. */
int
-router_pick_published_address(or_options_t *options, uint32_t *addr)
+router_pick_published_address(const or_options_t *options, uint32_t *addr)
{
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
log_info(LD_CONFIG, "Could not determine our address locally. "
"Checking if directory headers provide any hints.");
@@ -1401,9 +1413,7 @@ router_pick_published_address(or_options_t *options, uint32_t *addr)
return -1;
}
}
- a.s_addr = htonl(*addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_CONFIG,"Success: chose address '%s'.", buf);
+ log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
return 0;
}
@@ -1419,12 +1429,13 @@ router_rebuild_descriptor(int force)
uint32_t addr;
char platform[256];
int hibernating = we_are_hibernating();
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (desc_clean_since && !force)
return 0;
- if (router_pick_published_address(options, &addr) < 0) {
+ if (router_pick_published_address(options, &addr) < 0 ||
+ router_get_advertised_or_port(options) == 0) {
/* Stop trying to rebuild our descriptor every second. We'll
* learn that it's time to try again when ip_address_changed()
* marks it dirty. */
@@ -1440,7 +1451,7 @@ router_rebuild_descriptor(int force)
ri->nickname = tor_strdup(options->Nickname);
ri->addr = addr;
ri->or_port = router_get_advertised_or_port(options);
- ri->dir_port = router_get_advertised_dir_port(options);
+ ri->dir_port = router_get_advertised_dir_port(options, 0);
ri->cache_info.published_on = time(NULL);
ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
* main thread */
@@ -1472,13 +1483,12 @@ router_rebuild_descriptor(int force)
ri->policy_is_reject_star =
policy_is_reject_star(ri->exit_policy);
- if (desc_routerinfo) { /* inherit values */
- ri->is_valid = desc_routerinfo->is_valid;
- ri->is_running = desc_routerinfo->is_running;
- ri->is_named = desc_routerinfo->is_named;
- }
+#if 0
+ /* XXXX NM NM I belive this is safe to remove */
if (authdir_mode(options))
ri->is_valid = ri->is_named = 1; /* believe in yourself */
+#endif
+
if (options->MyFamily) {
smartlist_t *family;
if (!warned_nonexistent_family)
@@ -1487,13 +1497,12 @@ router_rebuild_descriptor(int force)
ri->declared_family = smartlist_create();
smartlist_split_string(family, options->MyFamily, ",",
SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH(family, char *, name,
- {
- routerinfo_t *member;
+ SMARTLIST_FOREACH_BEGIN(family, char *, name) {
+ const node_t *member;
if (!strcasecmp(name, options->Nickname))
- member = ri;
+ goto skip; /* Don't list ourself, that's redundant */
else
- member = router_get_by_nickname(name, 1);
+ member = node_get_by_nickname(name, 1);
if (!member) {
int is_legal = is_legal_nickname_or_hexdigest(name);
if (!smartlist_string_isin(warned_nonexistent_family, name) &&
@@ -1513,19 +1522,21 @@ router_rebuild_descriptor(int force)
smartlist_add(ri->declared_family, name);
name = NULL;
}
- } else if (router_is_me(member)) {
+ } else if (router_digest_is_me(member->identity)) {
/* Don't list ourself in our own family; that's redundant */
+ /* XXX shouldn't be possible */
} else {
char *fp = tor_malloc(HEX_DIGEST_LEN+2);
fp[0] = '$';
base16_encode(fp+1,HEX_DIGEST_LEN+1,
- member->cache_info.identity_digest, DIGEST_LEN);
+ member->identity, DIGEST_LEN);
smartlist_add(ri->declared_family, fp);
if (smartlist_string_isin(warned_nonexistent_family, name))
smartlist_string_remove(warned_nonexistent_family, name);
}
+ skip:
tor_free(name);
- });
+ } SMARTLIST_FOREACH_END(name);
/* remove duplicates from the list */
smartlist_sort_strings(ri->declared_family);
@@ -1586,8 +1597,6 @@ router_rebuild_descriptor(int force)
strlen(ri->cache_info.signed_descriptor_body),
ri->cache_info.signed_descriptor_digest);
- routerinfo_set_country(ri);
-
if (ei) {
tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
}
@@ -1682,7 +1691,7 @@ void
check_descriptor_ipaddress_changed(time_t now)
{
uint32_t prev, cur;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
(void) now;
if (!desc_routerinfo)
@@ -1714,7 +1723,7 @@ router_new_address_suggestion(const char *suggestion,
{
uint32_t addr, cur = 0;
struct in_addr in;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* first, learn what the IP address actually is */
if (!tor_inet_aton(suggestion, &in)) {
@@ -1813,7 +1822,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
int result=0;
addr_policy_t *tmpe;
char *family_line;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* Make sure the identity key matches the one in the routerinfo. */
if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
@@ -2055,7 +2064,7 @@ int
extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
crypto_pk_env_t *ident_key)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char identity[HEX_DIGEST_LEN+1];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
@@ -2079,6 +2088,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
tor_free(bandwidth_usage);
smartlist_add(chunks, pre);
+ if (geoip_is_loaded()) {
+ char *chunk=NULL;
+ tor_asprintf(&chunk, "geoip-db-digest %s\n", geoip_db_digest());
+ smartlist_add(chunks, chunk);
+ }
+
if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
if (options->DirReqStatistics &&
@@ -2101,6 +2116,11 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
"exit-stats-end", now, &contents) > 0) {
smartlist_add(chunks, contents);
}
+ if (options->ConnDirectionStatistics &&
+ load_stats_file("stats"PATH_SEPARATOR"conn-stats",
+ "conn-bi-direct", now, &contents) > 0) {
+ smartlist_add(chunks, contents);
+ }
}
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
@@ -2229,6 +2249,186 @@ is_legal_hexdigest(const char *s)
strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN);
}
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of a node with identity digest
+ * <b>id_digest</b>, named-status <b>is_named</b>, nickname <b>nickname</b>,
+ * and address <b>addr</b> or <b>addr32h</b>.
+ *
+ * The <b>nickname</b> and <b>addr</b> fields are optional and may be set to
+ * NULL. The <b>addr32h</b> field is optional and may be set to 0.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+format_node_description(char *buf,
+ const char *id_digest,
+ int is_named,
+ const char *nickname,
+ const tor_addr_t *addr,
+ uint32_t addr32h)
+{
+ char *cp;
+
+ if (!buf)
+ return "<NULL BUFFER>";
+
+ buf[0] = '$';
+ base16_encode(buf+1, HEX_DIGEST_LEN+1, id_digest, DIGEST_LEN);
+ cp = buf+1+HEX_DIGEST_LEN;
+ if (nickname) {
+ buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+ strlcpy(buf+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+ cp += strlen(cp);
+ }
+ if (addr32h || addr) {
+ memcpy(cp, " at ", 4);
+ cp += 4;
+ if (addr) {
+ tor_addr_to_str(cp, addr, TOR_ADDR_BUF_LEN, 0);
+ } else {
+ struct in_addr in;
+ in.s_addr = htonl(addr32h);
+ tor_inet_ntoa(&in, cp, INET_NTOA_BUF_LEN);
+ }
+ }
+ return buf;
+}
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of <b>ri</b>.
+ *
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+router_get_description(char *buf, const routerinfo_t *ri)
+{
+ if (!ri)
+ return "<null>";
+ return format_node_description(buf,
+ ri->cache_info.identity_digest,
+ router_is_named(ri),
+ ri->nickname,
+ NULL,
+ ri->addr);
+}
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of <b>node</b>.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+node_get_description(char *buf, const node_t *node)
+{
+ const char *nickname = NULL;
+ uint32_t addr32h = 0;
+ int is_named = 0;
+
+ if (!node)
+ return "<null>";
+
+ if (node->rs) {
+ nickname = node->rs->nickname;
+ is_named = node->rs->is_named;
+ addr32h = node->rs->addr;
+ } else if (node->ri) {
+ nickname = node->ri->nickname;
+ addr32h = node->ri->addr;
+ }
+
+ return format_node_description(buf,
+ node->identity,
+ is_named,
+ nickname,
+ NULL,
+ addr32h);
+}
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of <b>rs</b>.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+routerstatus_get_description(char *buf, const routerstatus_t *rs)
+{
+ if (!rs)
+ return "<null>";
+ return format_node_description(buf,
+ rs->identity_digest,
+ rs->is_named,
+ rs->nickname,
+ NULL,
+ rs->addr);
+}
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of <b>ei</b>.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+extend_info_get_description(char *buf, const extend_info_t *ei)
+{
+ if (!ei)
+ return "<null>";
+ return format_node_description(buf,
+ ei->identity_digest,
+ 0,
+ ei->nickname,
+ &ei->addr,
+ 0);
+}
+
+/** Return a human-readable description of the routerinfo_t <b>ri</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+router_describe(const routerinfo_t *ri)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ return router_get_description(buf, ri);
+}
+
+/** Return a human-readable description of the node_t <b>node</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+node_describe(const node_t *node)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ return node_get_description(buf, node);
+}
+
+/** Return a human-readable description of the routerstatus_t <b>rs</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+routerstatus_describe(const routerstatus_t *rs)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ return routerstatus_get_description(buf, rs);
+}
+
+/** Return a human-readable description of the extend_info_t <b>ri</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+extend_info_describe(const extend_info_t *ei)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ return extend_info_get_description(buf, ei);
+}
+
/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
* verbose representation of the identity of <b>router</b>. The format is:
* A dollar sign.
@@ -2239,10 +2439,15 @@ is_legal_hexdigest(const char *s)
void
router_get_verbose_nickname(char *buf, const routerinfo_t *router)
{
+ const char *good_digest = networkstatus_get_router_digest_by_nickname(
+ router->nickname);
+ int is_named = good_digest && tor_memeq(good_digest,
+ router->cache_info.identity_digest,
+ DIGEST_LEN);
buf[0] = '$';
base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
+ buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}
diff --git a/src/or/router.h b/src/or/router.h
index 95c0a34e2..f6d3c1233 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -39,26 +39,27 @@ void router_orport_found_reachable(void);
void router_dirport_found_reachable(void);
void router_perform_bandwidth_test(int num_circs, time_t now);
-int authdir_mode(or_options_t *options);
-int authdir_mode_v1(or_options_t *options);
-int authdir_mode_v2(or_options_t *options);
-int authdir_mode_v3(or_options_t *options);
-int authdir_mode_any_main(or_options_t *options);
-int authdir_mode_any_nonhidserv(or_options_t *options);
-int authdir_mode_handles_descs(or_options_t *options, int purpose);
-int authdir_mode_publishes_statuses(or_options_t *options);
-int authdir_mode_tests_reachability(or_options_t *options);
-int authdir_mode_bridge(or_options_t *options);
+int authdir_mode(const or_options_t *options);
+int authdir_mode_v1(const or_options_t *options);
+int authdir_mode_v2(const or_options_t *options);
+int authdir_mode_v3(const or_options_t *options);
+int authdir_mode_any_main(const or_options_t *options);
+int authdir_mode_any_nonhidserv(const or_options_t *options);
+int authdir_mode_handles_descs(const or_options_t *options, int purpose);
+int authdir_mode_publishes_statuses(const or_options_t *options);
+int authdir_mode_tests_reachability(const or_options_t *options);
+int authdir_mode_bridge(const or_options_t *options);
-uint16_t router_get_advertised_or_port(or_options_t *options);
-uint16_t router_get_advertised_dir_port(or_options_t *options);
+uint16_t router_get_advertised_or_port(const or_options_t *options);
+uint16_t router_get_advertised_dir_port(const or_options_t *options,
+ uint16_t dirport);
-int server_mode(or_options_t *options);
-int public_server_mode(or_options_t *options);
+int server_mode(const or_options_t *options);
+int public_server_mode(const or_options_t *options);
int advertised_server_mode(void);
-int proxy_mode(or_options_t *options);
+int proxy_mode(const or_options_t *options);
void consider_publishable_server(int force);
-int should_refuse_unknown_exits(or_options_t *options);
+int should_refuse_unknown_exits(const or_options_t *options);
void router_upload_dir_desc_to_dirservers(int force);
void mark_my_descriptor_dirty_if_older_than(time_t when);
@@ -69,14 +70,14 @@ void router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn);
int router_compare_to_my_exit_policy(edge_connection_t *conn);
int router_my_exit_policy_is_reject_star(void);
-routerinfo_t *router_get_my_routerinfo(void);
+const routerinfo_t *router_get_my_routerinfo(void);
extrainfo_t *router_get_my_extrainfo(void);
const char *router_get_my_descriptor(void);
int router_digest_is_me(const char *digest);
int router_extrainfo_digest_is_me(const char *digest);
-int router_is_me(routerinfo_t *router);
+int router_is_me(const routerinfo_t *router);
int router_fingerprint_is_me(const char *fp);
-int router_pick_published_address(or_options_t *options, uint32_t *addr);
+int router_pick_published_address(const or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);
@@ -85,6 +86,30 @@ int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo,
int is_legal_nickname(const char *s);
int is_legal_nickname_or_hexdigest(const char *s);
int is_legal_hexdigest(const char *s);
+
+/**
+ * Longest allowed output of format_node_description, plus 1 character for
+ * NUL. This allows space for:
+ * "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx at"
+ * " [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]"
+ * plus a terminating NUL.
+ */
+#define NODE_DESC_BUF_LEN (MAX_VERBOSE_NICKNAME_LEN+4+TOR_ADDR_BUF_LEN)
+const char *format_node_description(char *buf,
+ const char *id_digest,
+ int is_named,
+ const char *nickname,
+ const tor_addr_t *addr,
+ uint32_t addr32h);
+const char *router_get_description(char *buf, const routerinfo_t *ri);
+const char *node_get_description(char *buf, const node_t *node);
+const char *routerstatus_get_description(char *buf, const routerstatus_t *rs);
+const char *extend_info_get_description(char *buf, const extend_info_t *ei);
+const char *router_describe(const routerinfo_t *ri);
+const char *node_describe(const node_t *node);
+const char *routerstatus_describe(const routerstatus_t *ri);
+const char *extend_info_describe(const extend_info_t *ei);
+
void router_get_verbose_nickname(char *buf, const routerinfo_t *router);
void routerstatus_get_verbose_nickname(char *buf,
const routerstatus_t *router);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index a3d9b78ee..15f643cf7 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -22,7 +22,9 @@
#include "geoip.h"
#include "hibernate.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "rendcommon.h"
@@ -37,22 +39,25 @@
/****************************************************************************/
/* static function prototypes */
-static routerstatus_t *router_pick_directory_server_impl(
- authority_type_t auth, int flags);
-static routerstatus_t *router_pick_trusteddirserver_impl(
- authority_type_t auth, int flags, int *n_busy_out);
+static const routerstatus_t *router_pick_directory_server_impl(
+ dirinfo_type_t auth, int flags);
+static const routerstatus_t *router_pick_trusteddirserver_impl(
+ dirinfo_type_t auth, int flags, int *n_busy_out);
static void mark_all_trusteddirservers_up(void);
-static int router_nickname_matches(routerinfo_t *router, const char *nickname);
+static int router_nickname_matches(const routerinfo_t *router,
+ const char *nickname);
+static int node_nickname_matches(const node_t *router,
+ const char *nickname);
static void trusted_dir_server_free(trusted_dir_server_t *ds);
-static void launch_router_descriptor_downloads(smartlist_t *downloadable,
- routerstatus_t *source,
- time_t now);
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static void update_router_have_minimum_dir_info(void);
-static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc,
- int with_annotations);
+static const char *signed_descriptor_get_body_impl(
+ const signed_descriptor_t *desc,
+ int with_annotations);
static void list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix);
+static void launch_dummy_descriptor_download_as_needed(time_t now,
+ const or_options_t *options);
DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t)
DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t)
@@ -94,7 +99,7 @@ static smartlist_t *warned_nicknames = NULL;
/** The last time we tried to download any routerdesc, or 0 for "never". We
* use this to rate-limit download attempts when the number of routerdescs to
* download is low. */
-static time_t last_routerdesc_download_attempted = 0;
+static time_t last_descriptor_download_attempted = 0;
/** When we last computed the weights to use for bandwidths on directory
* requests, what were the total weighted bandwidth, and our share of that
@@ -106,7 +111,7 @@ static uint64_t sl_last_total_weighted_bw = 0,
/** Return the number of directory authorities whose type matches some bit set
* in <b>type</b> */
int
-get_n_authorities(authority_type_t type)
+get_n_authorities(dirinfo_type_t type)
{
int n = 0;
if (!trusted_dir_servers)
@@ -117,7 +122,7 @@ get_n_authorities(authority_type_t type)
return n;
}
-#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY)
+#define get_n_v2_authorities() get_n_authorities(V2_DIRINFO)
/** Helper: Return the cert_list_t for an authority whose authority ID is
* <b>id_digest</b>, allocating a new list if necessary. */
@@ -312,6 +317,7 @@ trusted_dirs_remove_old_certs(void)
time_t now = time(NULL);
#define DEAD_CERT_LIFETIME (2*24*60*60)
#define OLD_CERT_LIFETIME (7*24*60*60)
+#define CERT_EXPIRY_SKEW (60*60)
if (!trusted_dir_certs)
return;
@@ -514,7 +520,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
}
SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) {
int found = 0;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
continue;
@@ -600,7 +606,7 @@ router_should_rebuild_store(desc_store_t *store)
/** Return the desc_store_t in <b>rl</b> that should be used to store
* <b>sd</b>. */
static INLINE desc_store_t *
-desc_get_store(routerlist_t *rl, signed_descriptor_t *sd)
+desc_get_store(routerlist_t *rl, const signed_descriptor_t *sd)
{
if (sd->is_extrainfo)
return &rl->extrainfo_store;
@@ -926,10 +932,10 @@ router_get_trusted_dir_servers(void)
* Don't pick an authority if any non-authority is viable; try to avoid using
* servers that have returned 503 recently.
*/
-routerstatus_t *
-router_pick_directory_server(authority_type_t type, int flags)
+const routerstatus_t *
+router_pick_directory_server(dirinfo_type_t type, int flags)
{
- routerstatus_t *choice;
+ const routerstatus_t *choice;
if (get_options()->PreferTunneledDirConns)
flags |= _PDS_PREFER_TUNNELED_DIR_CONNS;
@@ -958,8 +964,8 @@ int
router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out)
{
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *rs;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *rs;
const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL;
*v2_share_out = *v3_share_out = 0.0;
if (!me)
@@ -972,7 +978,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
/* XXXX This is a bit of a kludge */
if (rs->is_v2_dir) {
sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V2_AUTHORITY, pds_flags);
+ router_pick_directory_server(V2_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v2_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@@ -981,7 +987,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
if (rs->version_supports_v3_dir) {
sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V3_AUTHORITY, pds_flags);
+ router_pick_directory_server(V3_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v3_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@@ -1022,7 +1028,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
{
if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) &&
- (ds->type & V3_AUTHORITY))
+ (ds->type & V3_DIRINFO))
return ds;
});
@@ -1032,10 +1038,10 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
/** Try to find a running trusted dirserver. Flags are as for
* router_pick_directory_server.
*/
-routerstatus_t *
-router_pick_trusteddirserver(authority_type_t type, int flags)
+const routerstatus_t *
+router_pick_trusteddirserver(dirinfo_type_t type, int flags)
{
- routerstatus_t *choice;
+ const routerstatus_t *choice;
int busy = 0;
if (get_options()->PreferTunneledDirConns)
flags |= _PDS_PREFER_TUNNELED_DIR_CONNS;
@@ -1047,7 +1053,8 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
/* If the reason that we got no server is that servers are "busy",
* we must be excluding good servers because we already have serverdesc
* fetches with them. Do not mark down servers up because of this. */
- tor_assert((flags & PDS_NO_EXISTING_SERVERDESC_FETCH));
+ tor_assert((flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH)));
return NULL;
}
@@ -1067,11 +1074,11 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
* If the _PDS_PREFER_TUNNELED_DIR_CONNS flag is set, prefer directory servers
* that we can use with BEGINDIR.
*/
-static routerstatus_t *
-router_pick_directory_server_impl(authority_type_t type, int flags)
+static const routerstatus_t *
+router_pick_directory_server_impl(dirinfo_type_t type, int flags)
{
- or_options_t *options = get_options();
- routerstatus_t *result;
+ const or_options_t *options = get_options();
+ const node_t *result;
smartlist_t *direct, *tunnel;
smartlist_t *trusted_direct, *trusted_tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
@@ -1095,54 +1102,64 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
overloaded_tunnel = smartlist_create();
/* Find all the running dirservers we know about. */
- SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *,
- status) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
int is_trusted;
- int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
+ int is_overloaded;
tor_addr_t addr;
- if (!status->is_running || !status->dir_port || !status->is_valid)
+ const routerstatus_t *status = node->rs;
+ const country_t country = node->country;
+ if (!status)
continue;
- if (status->is_bad_directory)
+
+ if (!node->is_running || !status->dir_port || !node->is_valid)
+ continue;
+ if (node->is_bad_directory)
continue;
- if (requireother && router_digest_is_me(status->identity_digest))
+ if (requireother && router_digest_is_me(node->identity))
continue;
- if (type & V3_AUTHORITY) {
+ if (type & V3_DIRINFO) {
if (!(status->version_supports_v3_dir ||
- router_digest_is_trusted_dir_type(status->identity_digest,
- V3_AUTHORITY)))
+ router_digest_is_trusted_dir_type(node->identity,
+ V3_DIRINFO)))
continue;
}
- is_trusted = router_digest_is_trusted_dir(status->identity_digest);
- if ((type & V2_AUTHORITY) && !(status->is_v2_dir || is_trusted))
+ is_trusted = router_digest_is_trusted_dir(node->identity);
+ if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted))
+ continue;
+ if ((type & EXTRAINFO_DIRINFO) &&
+ !router_supports_extrainfo(node->identity, 0))
continue;
- if ((type & EXTRAINFO_CACHE) &&
- !router_supports_extrainfo(status->identity_digest, 0))
+ if ((type & MICRODESC_DIRINFO) && !is_trusted &&
+ !node->rs->version_supports_microdesc_cache)
continue;
if (try_excluding && options->ExcludeNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
+ routerset_contains_routerstatus(options->ExcludeNodes, status,
+ country)) {
++n_excluded;
continue;
}
/* XXXX IP6 proposal 118 */
- tor_addr_from_ipv4h(&addr, status->addr);
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+
+ is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
if (prefer_tunnel &&
status->version_supports_begindir &&
(!fascistfirewall ||
fascist_firewall_allows_address_or(&addr, status->or_port)))
smartlist_add(is_trusted ? trusted_tunnel :
- is_overloaded ? overloaded_tunnel : tunnel, status);
+ is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
else if (!fascistfirewall ||
fascist_firewall_allows_address_dir(&addr, status->dir_port))
smartlist_add(is_trusted ? trusted_direct :
- is_overloaded ? overloaded_direct : direct, status);
- } SMARTLIST_FOREACH_END(status);
+ is_overloaded ? overloaded_direct : direct, (void*)node);
+ } SMARTLIST_FOREACH_END(node);
if (smartlist_len(tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_tunnel,
+ result = node_sl_choose_by_bandwidth(overloaded_tunnel,
WEIGHT_FOR_DIR);
} else if (smartlist_len(trusted_tunnel)) {
/* FFFF We don't distinguish between trusteds and overloaded trusteds
@@ -1151,10 +1168,10 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
* is a feature, but it could easily be a bug. -RD */
result = smartlist_choose(trusted_tunnel);
} else if (smartlist_len(direct)) {
- result = routerstatus_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_direct)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_direct,
- WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(overloaded_direct,
+ WEIGHT_FOR_DIR);
} else {
result = smartlist_choose(trusted_direct);
}
@@ -1173,26 +1190,27 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
goto retry_without_exclude;
}
- return result;
+ return result ? result->rs : NULL;
}
/** Choose randomly from among the trusted dirservers that are up. Flags
* are as for router_pick_directory_server_impl().
*/
-static routerstatus_t *
-router_pick_trusteddirserver_impl(authority_type_t type, int flags,
+static const routerstatus_t *
+router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags,
int *n_busy_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *direct, *tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *result;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *result;
time_t now = time(NULL);
const int requireother = ! (flags & PDS_ALLOW_SELF);
const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
const int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS);
const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH);
+ const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH);
int n_busy = 0;
int try_excluding = 1, n_excluded = 0;
@@ -1214,14 +1232,14 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
if (!d->is_running) continue;
if ((type & d->type) == 0)
continue;
- if ((type & EXTRAINFO_CACHE) &&
+ if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(d->digest, 1))
continue;
if (requireother && me && router_digest_is_me(d->digest))
continue;
if (try_excluding && options->ExcludeNodes &&
routerset_contains_routerstatus(options->ExcludeNodes,
- &d->fake_status)) {
+ &d->fake_status, -1)) {
++n_excluded;
continue;
}
@@ -1240,6 +1258,13 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
continue;
}
}
+ if (no_microdesc_fetching) {
+ if (connection_get_by_type_addr_port_purpose(
+ CONN_TYPE_DIR, &addr, d->dir_port, DIR_PURPOSE_FETCH_MICRODESC)) {
+ ++n_busy;
+ continue;
+ }
+ }
if (prefer_tunnel &&
d->or_port &&
@@ -1287,22 +1312,18 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
static void
mark_all_trusteddirservers_up(void)
{
- if (routerlist) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- if (router_digest_is_trusted_dir(router->cache_info.identity_digest) &&
- router->dir_port > 0) {
- router->is_running = 1;
- });
- }
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, {
+ if (router_digest_is_trusted_dir(node->identity))
+ node->is_running = 1;
+ });
if (trusted_dir_servers) {
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
{
routerstatus_t *rs;
dir->is_running = 1;
download_status_reset(&dir->v2_ns_dl_status);
- rs = router_get_consensus_status_by_id(dir->digest);
- if (rs && !rs->is_running) {
- rs->is_running = 1;
+ rs = router_get_mutable_consensus_status_by_id(dir->digest);
+ if (rs) {
rs->last_dir_503_at = 0;
control_event_networkstatus_changed_single(rs);
}
@@ -1326,25 +1347,14 @@ router_reset_status_download_failures(void)
mark_all_trusteddirservers_up();
}
-/** Return true iff router1 and router2 have the same /16 network. */
+/** Return true iff router1 and router2 have similar enough network addresses
+ * that we should treat them as being in the same family */
static INLINE int
-routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2)
+addrs_in_same_network_family(const tor_addr_t *a1,
+ const tor_addr_t *a2)
{
- return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000);
-}
-
-/** Look through the routerlist and identify routers that
- * advertise the same /16 network address as <b>router</b>.
- * Add each of them to <b>sl</b>.
- */
-static void
-routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router)
-{
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
- {
- if (router != r && routers_in_same_network_family(router, r))
- smartlist_add(sl, r);
- });
+ /* XXXX MOVE ? */
+ return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC);
}
/** Add all the family of <b>router</b> to the smartlist <b>sl</b>.
@@ -1352,122 +1362,132 @@ routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router)
* or pick more than one relay from a family for our entry guard list.
*/
void
-routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
+nodelist_add_node_family(smartlist_t *sl, const node_t *node)
{
- routerinfo_t *r;
- config_line_t *cl;
- or_options_t *options = get_options();
+ /* XXXX MOVE */
+ const smartlist_t *all_nodes = nodelist_get_list();
+ const smartlist_t *declared_family;
+ const or_options_t *options = get_options();
- /* First, add any routers with similar network addresses. */
- if (options->EnforceDistinctSubnets)
- routerlist_add_network_family(sl, router);
+ tor_assert(node);
- if (router->declared_family) {
- /* Add every r such that router declares familyness with r, and r
+ declared_family = node_get_declared_family(node);
+
+ /* First, add any nodes with similar network addresses. */
+ if (options->EnforceDistinctSubnets) {
+ tor_addr_t node_addr;
+ node_get_addr(node, &node_addr);
+
+ SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) {
+ tor_addr_t a;
+ node_get_addr(node2, &a);
+ if (addrs_in_same_network_family(&a, &node_addr))
+ smartlist_add(sl, (void*)node2);
+ } SMARTLIST_FOREACH_END(node2);
+ }
+
+ /* Now, add all nodes in the declared_family of this node, if they
+ * also declare this node to be in their family. */
+ if (declared_family) {
+ /* Add every r such that router declares familyness with node, and node
* declares familyhood with router. */
- SMARTLIST_FOREACH(router->declared_family, const char *, n,
- {
- if (!(r = router_get_by_nickname(n, 0)))
- continue;
- if (!r->declared_family)
- continue;
- SMARTLIST_FOREACH(r->declared_family, const char *, n2,
- {
- if (router_nickname_matches(router, n2))
- smartlist_add(sl, r);
- });
- });
+ SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) {
+ const node_t *node2;
+ const smartlist_t *family2;
+ if (!(node2 = node_get_by_nickname(name, 0)))
+ continue;
+ if (!(family2 = node_get_declared_family(node2)))
+ continue;
+ SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) {
+ if (node_nickname_matches(node, name2)) {
+ smartlist_add(sl, (void*)node2);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(name2);
+ } SMARTLIST_FOREACH_END(name);
}
/* If the user declared any families locally, honor those too. */
- for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (router_nickname_is_in_list(router, cl->value)) {
- add_nickname_list_to_smartlist(sl, cl->value, 0);
- }
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
+ if (routerset_contains_node(rs, node)) {
+ routerset_get_all_nodes(sl, rs, NULL, 0);
+ }
+ });
+ }
+}
+
+/** Given a <b>router</b>, add every node_t in its family to <b>sl</b>.
+ *
+ * Note the type mismatch: This function takes a routerinfo, but adds nodes
+ * to the smartlist!
+ */
+static void
+routerlist_add_nodes_in_family(smartlist_t *sl, const routerinfo_t *router)
+{
+ /* XXXX MOVE ? */
+ node_t fake_node;
+ const node_t *node = node_get_by_id(router->cache_info.identity_digest);;
+ if (node == NULL) {
+ memset(&fake_node, 0, sizeof(fake_node));
+ fake_node.ri = (routerinfo_t *)router;
+ memcpy(fake_node.identity, router->cache_info.identity_digest, DIGEST_LEN);
+ node = &fake_node;
}
+ nodelist_add_node_family(sl, node);
}
-/** Return true iff r is named by some nickname in <b>lst</b>. */
+/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */
static INLINE int
-router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r)
+node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node)
{
+ /* XXXX MOVE */
if (!lst) return 0;
- SMARTLIST_FOREACH(lst, const char *, name,
- if (router_nickname_matches(r, name))
- return 1;);
+ SMARTLIST_FOREACH(lst, const char *, name, {
+ if (node_nickname_matches(node, name))
+ return 1;
+ });
return 0;
}
/** Return true iff r1 and r2 are in the same family, but not the same
* router. */
int
-routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2)
+nodes_in_same_family(const node_t *node1, const node_t *node2)
{
- or_options_t *options = get_options();
- config_line_t *cl;
-
- if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2))
- return 1;
-
- if (router_in_nickname_smartlist(r1->declared_family, r2) &&
- router_in_nickname_smartlist(r2->declared_family, r1))
- return 1;
+ /* XXXX MOVE */
+ const or_options_t *options = get_options();
- for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (router_nickname_is_in_list(r1, cl->value) &&
- router_nickname_is_in_list(r2, cl->value))
+ /* Are they in the same family because of their addresses? */
+ if (options->EnforceDistinctSubnets) {
+ tor_addr_t a1, a2;
+ node_get_addr(node1, &a1);
+ node_get_addr(node2, &a2);
+ if (addrs_in_same_network_family(&a1, &a2))
return 1;
}
- return 0;
-}
-
-/** Given a (possibly NULL) comma-and-whitespace separated list of nicknames,
- * see which nicknames in <b>list</b> name routers in our routerlist, and add
- * the routerinfos for those routers to <b>sl</b>. If <b>must_be_running</b>,
- * only include routers that we think are running.
- * Warn if any non-Named routers are specified by nickname.
- */
-void
-add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running)
-{
- routerinfo_t *router;
- smartlist_t *nickname_list;
- int have_dir_info = router_have_minimum_dir_info();
- if (!list)
- return; /* nothing to do */
- tor_assert(sl);
-
- nickname_list = smartlist_create();
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
+ /* Are they in the same family because the agree they are? */
+ {
+ const smartlist_t *f1, *f2;
+ f1 = node_get_declared_family(node1);
+ f2 = node_get_declared_family(node2);
+ if (f1 && f2 &&
+ node_in_nickname_smartlist(f1, node2) &&
+ node_in_nickname_smartlist(f2, node1))
+ return 1;
+ }
- smartlist_split_string(nickname_list, list, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ /* Are they in the same option because the user says they are? */
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
+ if (routerset_contains_node(rs, node1) &&
+ routerset_contains_node(rs, node2))
+ return 1;
+ });
+ }
- SMARTLIST_FOREACH(nickname_list, const char *, nick, {
- int warned;
- if (!is_legal_nickname_or_hexdigest(nick)) {
- log_warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick);
- continue;
- }
- router = router_get_by_nickname(nick, 1);
- warned = smartlist_string_isin(warned_nicknames, nick);
- if (router) {
- if (!must_be_running || router->is_running) {
- smartlist_add(sl,router);
- }
- } else if (!router_get_consensus_status_by_nickname(nick,1)) {
- if (!warned) {
- log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG,
- "Nickname list includes '%s' which isn't a known router.",nick);
- smartlist_add(warned_nicknames, tor_strdup(nick));
- }
- }
- });
- SMARTLIST_FOREACH(nickname_list, char *, nick, tor_free(nick));
- smartlist_free(nickname_list);
+ return 0;
}
/** Return 1 iff any member of the (possibly NULL) comma-separated list
@@ -1475,7 +1495,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
* return 0.
*/
int
-router_nickname_is_in_list(routerinfo_t *router, const char *list)
+router_nickname_is_in_list(const routerinfo_t *router, const char *list)
{
smartlist_t *nickname_list;
int v = 0;
@@ -1494,34 +1514,32 @@ router_nickname_is_in_list(routerinfo_t *router, const char *list)
return v;
}
-/** Add every suitable router from our routerlist to <b>sl</b>, so that
+/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
static void
-router_add_running_routers_to_smartlist(smartlist_t *sl, int allow_invalid,
- int need_uptime, int need_capacity,
- int need_guard)
-{
- if (!routerlist)
- return;
+router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
+ int need_uptime, int need_capacity,
+ int need_guard, int need_desc)
+{ /* XXXX MOVE */
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (!node->is_running ||
+ (!node->is_valid && !allow_invalid))
+ continue;
+ if (need_desc && !(node->ri || (node->rs && node->md)))
+ continue;
+ if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL)
+ continue;
+ if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
+ continue;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- router->purpose == ROUTER_PURPOSE_GENERAL &&
- (router->is_valid || allow_invalid) &&
- !router_is_unreliable(router, need_uptime,
- need_capacity, need_guard)) {
- /* If it's running, and it's suitable according to the
- * other flags we had in mind */
- smartlist_add(sl, router);
- }
- });
+ smartlist_add(sl, (void *)node);
+ } SMARTLIST_FOREACH_END(node);
}
/** Look through the routerlist until we find a router that has my key.
Return it. */
-routerinfo_t *
+const routerinfo_t *
routerlist_find_my_routerinfo(void)
{
if (!routerlist)
@@ -1541,13 +1559,13 @@ routerlist_find_my_routerinfo(void)
* Don't exit enclave to excluded relays -- it wouldn't actually
* hurt anything, but this way there are fewer confused users.
*/
-routerinfo_t *
+const node_t *
router_find_exact_exit_enclave(const char *address, uint16_t port)
-{
+{/*XXXX MOVE*/
uint32_t addr;
struct in_addr in;
tor_addr_t a;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!tor_inet_aton(address, &in))
return NULL; /* it's not an IP already */
@@ -1555,14 +1573,13 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
tor_addr_from_ipv4h(&a, addr);
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->addr == addr &&
- router->is_running &&
- compare_tor_addr_to_addr_policy(&a, port, router->exit_policy) ==
+ SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, {
+ if (node_get_addr_ipv4h(node) == addr &&
+ node->is_running &&
+ compare_tor_addr_to_node_policy(&a, port, node) ==
ADDR_POLICY_ACCEPTED &&
- !routerset_contains_router(options->_ExcludeExitNodesUnion, router))
- return router;
+ !routerset_contains_node(options->_ExcludeExitNodesUnion, node))
+ return node;
});
return NULL;
}
@@ -1574,14 +1591,14 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
* If <b>need_guard</b>, we require that the router is a possible entry guard.
*/
int
-router_is_unreliable(routerinfo_t *router, int need_uptime,
- int need_capacity, int need_guard)
+node_is_unreliable(const node_t *node, int need_uptime,
+ int need_capacity, int need_guard)
{
- if (need_uptime && !router->is_stable)
+ if (need_uptime && !node->is_stable)
return 1;
- if (need_capacity && !router->is_fast)
+ if (need_capacity && !node->is_fast)
return 1;
- if (need_guard && !router->is_possible_guard)
+ if (need_guard && !node->is_possible_guard)
return 1;
return 0;
}
@@ -1589,7 +1606,7 @@ router_is_unreliable(routerinfo_t *router, int need_uptime,
/** Return the smaller of the router's configured BandwidthRate
* and its advertised capacity. */
uint32_t
-router_get_advertised_bandwidth(routerinfo_t *router)
+router_get_advertised_bandwidth(const routerinfo_t *router)
{
if (router->bandwidthcapacity < router->bandwidthrate)
return router->bandwidthcapacity;
@@ -1603,7 +1620,7 @@ router_get_advertised_bandwidth(routerinfo_t *router)
/** Return the smaller of the router's configured BandwidthRate
* and its advertised capacity, capped by max-believe-bw. */
uint32_t
-router_get_advertised_bandwidth_capped(routerinfo_t *router)
+router_get_advertised_bandwidth_capped(const routerinfo_t *router)
{
uint32_t result = router->bandwidthcapacity;
if (result > router->bandwidthrate)
@@ -1645,13 +1662,10 @@ kb_to_bytes(uint32_t bw)
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random element of smartlist <b>sl</b> of nodes, weighted by
* the advertised bandwidth of each element using the consensus
* bandwidth weights.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1661,10 +1675,9 @@ kb_to_bytes(uint32_t bw)
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
- bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
int64_t weight_scale;
int64_t rand_bw;
@@ -1758,15 +1771,14 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
bandwidths = tor_malloc_zero(sizeof(double)*smartlist_len(sl));
// Cycle through smartlist and total the bandwidth.
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0, is_me = 0;
double weight = 1;
- if (statuses) {
- routerstatus_t *status = smartlist_get(sl, i);
- is_exit = status->is_exit && !status->is_bad_exit;
- is_guard = status->is_possible_guard;
- is_dir = (status->dir_port != 0);
- if (!status->has_bandwidth) {
+ is_exit = node->is_exit && ! node->is_bad_exit;
+ is_guard = node->is_possible_guard;
+ is_dir = node_is_dir(node);
+ if (node->rs) {
+ if (!node->rs->has_bandwidth) {
tor_free(bandwidths);
/* This should never happen, unless all the authorites downgrade
* to 0.2.0 or rogue routerstatuses get inserted into our consensus. */
@@ -1775,26 +1787,17 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
"old router selection algorithm.");
return NULL;
}
- this_bw = kb_to_bytes(status->bandwidth);
- if (router_digest_is_me(status->identity_digest))
- is_me = 1;
+ this_bw = kb_to_bytes(node->rs->bandwidth);
+ } else if (node->ri) {
+ /* bridge or other descriptor not in our consensus */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
+ have_unknown = 1;
} else {
- routerstatus_t *rs;
- routerinfo_t *router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- is_exit = router->is_exit && !router->is_bad_exit;
- is_guard = router->is_possible_guard;
- is_dir = (router->dir_port != 0);
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else { /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
- have_unknown = 1;
- }
- if (router_digest_is_me(router->cache_info.identity_digest))
- is_me = 1;
+ /* We can't use this one. */
+ continue;
}
+ is_me = router_digest_is_me(node->identity);
+
if (is_guard && is_exit) {
weight = (is_dir ? Wdb*Wd : Wd);
} else if (is_guard) {
@@ -1805,11 +1808,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
weight = (is_dir ? Wmb*Wm : Wm);
}
- bandwidths[i] = weight*this_bw;
+ bandwidths[node_sl_idx] = weight*this_bw;
weighted_bw += weight*this_bw;
if (is_me)
sl_last_weighted_bw_of_me = weight*this_bw;
- }
+ } SMARTLIST_FOREACH_END(node);
/* XXXX023 this is a kludge to expose these values. */
sl_last_total_weighted_bw = weighted_bw;
@@ -1857,12 +1860,9 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random node_t element of smartlist <b>sl</b>, weighted by
* the advertised bandwidth of each element.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1872,13 +1872,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
- unsigned int i;
- routerinfo_t *router;
- routerstatus_t *status=NULL;
+ unsigned i;
int32_t *bandwidths;
int is_exit;
int is_guard;
@@ -1919,49 +1917,34 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
guard_bits = bitarray_init_zero(smartlist_len(sl));
/* Iterate over all the routerinfo_t or routerstatus_t, and */
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
/* first, learn what bandwidth we think i has */
int is_known = 1;
int32_t flags = 0;
uint32_t this_bw = 0;
- if (statuses) {
- status = smartlist_get(sl, i);
- if (router_digest_is_me(status->identity_digest))
- me_idx = i;
- router = router_get_by_digest(status->identity_digest);
- is_exit = status->is_exit;
- is_guard = status->is_possible_guard;
- if (status->has_bandwidth) {
- this_bw = kb_to_bytes(status->bandwidth);
+ i = node_sl_idx;
+
+ if (router_digest_is_me(node->identity))
+ me_idx = node_sl_idx;
+
+ is_exit = node->is_exit;
+ is_guard = node->is_possible_guard;
+ if (node->rs) {
+ if (node->rs->has_bandwidth) {
+ this_bw = kb_to_bytes(node->rs->bandwidth);
} else { /* guess */
/* XXX023 once consensuses always list bandwidths, we can take
* this guessing business out. -RD */
is_known = 0;
- flags = status->is_fast ? 1 : 0;
+ flags = node->rs->is_fast ? 1 : 0;
flags |= is_exit ? 2 : 0;
flags |= is_guard ? 4 : 0;
}
- } else {
- routerstatus_t *rs;
- router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- if (router_digest_is_me(router->cache_info.identity_digest))
- me_idx = i;
- is_exit = router->is_exit;
- is_guard = router->is_possible_guard;
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else if (rs) { /* guess; don't trust the descriptor */
- /* XXX023 once consensuses always list bandwidths, we can take
- * this guessing business out. -RD */
- is_known = 0;
- flags = router->is_fast ? 1 : 0;
- flags |= is_exit ? 2 : 0;
- flags |= is_guard ? 4 : 0;
- } else /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
+ } else if (node->ri) {
+ /* Must be a bridge if we're willing to use it */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
}
+
if (is_exit)
bitarray_set(exit_bits, i);
if (is_guard)
@@ -1981,9 +1964,9 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
total_nonexit_bw += this_bw;
} else {
++n_unknown;
- bandwidths[i] = -flags;
+ bandwidths[node_sl_idx] = -flags;
}
- }
+ } SMARTLIST_FOREACH_END(node);
/* Now, fill in the unknown values. */
if (n_unknown) {
@@ -2125,40 +2108,23 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
return smartlist_get(sl, i);
}
-/** Choose a random element of router list <b>sl</b>, weighted by
- * the advertised bandwidth of each router.
- */
-routerinfo_t *
-routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- routerinfo_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 0))) {
- return ret;
- } else {
- return smartlist_choose_by_bandwidth(sl, rule, 0);
- }
-}
-
/** Choose a random element of status list <b>sl</b>, weighted by
- * the advertised bandwidth of each status.
- */
-routerstatus_t *
-routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- /* We are choosing neither exit nor guard here. Weight accordingly. */
- routerstatus_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 1))) {
+ * the advertised bandwidth of each node */
+const node_t *
+node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
+{ /*XXXX MOVE */
+ const node_t *ret;
+ if ((ret = smartlist_choose_node_by_bandwidth_weights(sl, rule))) {
return ret;
} else {
- return smartlist_choose_by_bandwidth(sl, rule, 1);
+ return smartlist_choose_node_by_bandwidth(sl, rule);
}
}
-/** Return a random running router from the routerlist. Never
- * pick a node whose routerinfo is in
- * <b>excludedsmartlist</b>, or whose routerinfo matches <b>excludedset</b>,
+/** Return a random running node from the nodelist. Never
+ * pick a node that is in
+ * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>,
* even if they are the only nodes available.
* If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than
* a minimum uptime, return one of those.
@@ -2170,21 +2136,26 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
* If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if
* picking an exit node, otherwise we weight bandwidths for picking a relay
* node (that is, possibly discounting exit nodes).
+ * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that
+ * have a routerinfo or microdescriptor -- that is, enough info to be
+ * used to build a circuit.
*/
-routerinfo_t *
+const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
routerset_t *excludedset,
router_crn_flags_t flags)
-{
+{ /* XXXX MOVE */
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
+ const int need_desc = (flags & CRN_NEED_DESC) != 0;
smartlist_t *sl=smartlist_create(),
- *excludednodes=smartlist_create();
- routerinfo_t *choice = NULL, *r;
+ *excludednodes=smartlist_create();
+ const node_t *choice = NULL;
+ const routerinfo_t *r;
bandwidth_weight_rule_t rule;
tor_assert(!(weight_for_exit && need_guard));
@@ -2194,29 +2165,30 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
/* Exclude relays that allow single hop exit circuits, if the user
* wants to (such relays might be risky) */
if (get_options()->ExcludeSingleHopRelays) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- if (r->allow_single_hop_exits) {
- smartlist_add(excludednodes, r);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ if (node_allows_single_hop_exits(node)) {
+ smartlist_add(excludednodes, node);
});
}
if ((r = routerlist_find_my_routerinfo())) {
- smartlist_add(excludednodes, r);
- routerlist_add_family(excludednodes, r);
+ const node_t *me = node_get_by_id(r->cache_info.identity_digest);
+ if (me)
+ smartlist_add(excludednodes, (void *)me);
+ routerlist_add_nodes_in_family(excludednodes, r);
}
- router_add_running_routers_to_smartlist(sl, allow_invalid,
- need_uptime, need_capacity,
- need_guard);
+ router_add_running_nodes_to_smartlist(sl, allow_invalid,
+ need_uptime, need_capacity,
+ need_guard, need_desc);
smartlist_subtract(sl,excludednodes);
if (excludedsmartlist)
smartlist_subtract(sl,excludedsmartlist);
if (excludedset)
- routerset_subtract_routers(sl,excludedset);
+ routerset_subtract_nodes(sl,excludedset);
// Always weight by bandwidth
- choice = routerlist_sl_choose_by_bandwidth(sl, rule);
+ choice = node_sl_choose_by_bandwidth(sl, rule);
smartlist_free(sl);
if (!choice && (need_uptime || need_capacity || need_guard)) {
@@ -2239,35 +2211,90 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
return choice;
}
-/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
- * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
- * (which is optionally prefixed with a single dollar sign). Return false if
- * <b>hexdigest</b> is malformed, or it doesn't match. */
-static INLINE int
-hex_digest_matches(const char *hexdigest, const char *identity_digest,
- const char *nickname, int is_named)
+/** Helper: given an extended nickname in <b>hexdigest</b> try to decode it.
+ * Return 0 on success, -1 on failure. Store the result into the
+ * DIGEST_LEN-byte buffer at <b>digest_out</b>, the single character at
+ * <b>nickname_qualifier_char_out</b>, and the MAXNICKNAME_LEN+1-byte buffer
+ * at <b>nickname_out</b>.
+ *
+ * The recognized format is:
+ * HexName = Dollar? HexDigest NamePart?
+ * Dollar = '?'
+ * HexDigest = HexChar*20
+ * HexChar = 'a'..'f' | 'A'..'F' | '0'..'9'
+ * NamePart = QualChar Name
+ * QualChar = '=' | '~'
+ * Name = NameChar*(1..MAX_NICKNAME_LEN)
+ * NameChar = Any ASCII alphanumeric character
+ */
+int
+hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_char_out,
+ char *nickname_out)
{
- char digest[DIGEST_LEN];
size_t len;
+
tor_assert(hexdigest);
if (hexdigest[0] == '$')
++hexdigest;
len = strlen(hexdigest);
- if (len < HEX_DIGEST_LEN)
+ if (len < HEX_DIGEST_LEN) {
+ return -1;
+ } else if (len > HEX_DIGEST_LEN && (hexdigest[HEX_DIGEST_LEN] == '=' ||
+ hexdigest[HEX_DIGEST_LEN] == '~') &&
+ len <= HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN) {
+ *nickname_qualifier_char_out = hexdigest[HEX_DIGEST_LEN];
+ strlcpy(nickname_out, hexdigest+HEX_DIGEST_LEN+1 , MAX_NICKNAME_LEN+1);
+ } else if (len == HEX_DIGEST_LEN) {
+ ;
+ } else {
+ return -1;
+ }
+
+ if (base16_decode(digest_out, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
+ return -1;
+ return 0;
+}
+
+/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
+ * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
+ * (which is optionally prefixed with a single dollar sign). Return false if
+ * <b>hexdigest</b> is malformed, or it doesn't match. */
+static int
+hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
+ const char *nickname, int is_named)
+{
+ char digest[DIGEST_LEN];
+ char nn_char='\0';
+ char nn_buf[MAX_NICKNAME_LEN+1];
+
+ if (hex_digest_nickname_decode(hexdigest, digest, &nn_char, nn_buf) == -1)
return 0;
- else if (len > HEX_DIGEST_LEN &&
- (hexdigest[HEX_DIGEST_LEN] == '=' ||
- hexdigest[HEX_DIGEST_LEN] == '~')) {
- if (strcasecmp(hexdigest+HEX_DIGEST_LEN+1, nickname))
+
+ if (nn_char == '=' || nn_char == '~') {
+ if (!nickname)
return 0;
- if (hexdigest[HEX_DIGEST_LEN] == '=' && !is_named)
+ if (strcasecmp(nn_buf, nickname))
+ return 0;
+ if (nn_char == '=' && !is_named)
return 0;
}
- if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
- return 0;
- return (tor_memeq(digest, identity_digest, DIGEST_LEN));
+ return tor_memeq(digest, identity_digest, DIGEST_LEN);
+}
+
+/* Return true iff <b>router</b> is listed as named in the current
+ * consensus. */
+int
+router_is_named(const routerinfo_t *router)
+{
+ const char *digest =
+ networkstatus_get_router_digest_by_nickname(router->nickname);
+
+ return (digest &&
+ tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN));
}
/** Return true iff the digest of <b>router</b>'s identity key,
@@ -2275,10 +2302,12 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest,
* optionally prefixed with a single dollar sign). Return false if
* <b>hexdigest</b> is malformed, or it doesn't match. */
static INLINE int
-router_hex_digest_matches(routerinfo_t *router, const char *hexdigest)
+router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest)
{
- return hex_digest_matches(hexdigest, router->cache_info.identity_digest,
- router->nickname, router->is_named);
+ return hex_digest_nickname_matches(hexdigest,
+ router->cache_info.identity_digest,
+ router->nickname,
+ router_is_named(router));
}
/** Return true if <b>router</b>'s nickname matches <b>nickname</b>
@@ -2286,20 +2315,43 @@ router_hex_digest_matches(routerinfo_t *router, const char *hexdigest)
* matches a hexadecimal value stored in <b>nickname</b>. Return
* false otherwise. */
static int
-router_nickname_matches(routerinfo_t *router, const char *nickname)
+router_nickname_matches(const routerinfo_t *router, const char *nickname)
{
if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname))
return 1;
return router_hex_digest_matches(router, nickname);
}
+/** Return true if <b>node</b>'s nickname matches <b>nickname</b>
+ * (case-insensitive), or if <b>node's</b> identity key digest
+ * matches a hexadecimal value stored in <b>nickname</b>. Return
+ * false otherwise. */
+static int
+node_nickname_matches(const node_t *node, const char *nickname)
+{
+ const char *n = node_get_nickname(node);
+ if (n && nickname[0]!='$' && !strcasecmp(n, nickname))
+ return 1;
+ return hex_digest_nickname_matches(nickname,
+ node->identity,
+ n,
+ node_is_named(node));
+}
+
/** Return the router in our routerlist whose (case-insensitive)
* nickname or (case-sensitive) hexadecimal key digest is
* <b>nickname</b>. Return NULL if no such router is known.
*/
-routerinfo_t *
+const routerinfo_t *
router_get_by_nickname(const char *nickname, int warn_if_unnamed)
{
+#if 1
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->ri;
+ else
+ return NULL;
+#else
int maybedigest;
char digest[DIGEST_LEN];
routerinfo_t *best_match=NULL;
@@ -2345,15 +2397,14 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
if (warn_if_unnamed && n_matches > 1) {
smartlist_t *fps = smartlist_create();
int any_unwarned = 0;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
+ SMARTLIST_FOREACH_BEGIN(routerlist->routers, routerinfo_t *, router) {
routerstatus_t *rs;
char *desc;
size_t dlen;
char fp[HEX_DIGEST_LEN+1];
if (strcasecmp(router->nickname, nickname))
continue;
- rs = router_get_consensus_status_by_id(
+ rs = router_get_mutable_consensus_status_by_id(
router->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
rs->name_lookup_warned = 1;
@@ -2366,7 +2417,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d",
fp, router->address, router->or_port);
smartlist_add(fps, desc);
- });
+ } SMARTLIST_FOREACH_END(router);
if (any_unwarned) {
char *alternatives = smartlist_join_strings(fps, "; ",0,NULL);
log_warn(LD_CONFIG,
@@ -2379,7 +2430,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
smartlist_free(fps);
} else if (warn_if_unnamed) {
- routerstatus_t *rs = router_get_consensus_status_by_id(
+ routerstatus_t *rs = router_get_mutable_consensus_status_by_id(
best_match->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
char fp[HEX_DIGEST_LEN+1];
@@ -2395,27 +2446,15 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
}
return best_match;
}
-
return NULL;
-}
-
-/** Try to find a routerinfo for <b>digest</b>. If we don't have one,
- * return 1. If we do, ask tor_version_as_new_as() for the answer.
- */
-int
-router_digest_version_as_new_as(const char *digest, const char *cutoff)
-{
- routerinfo_t *router = router_get_by_digest(digest);
- if (!router)
- return 1;
- return tor_version_as_new_as(router->platform, cutoff);
+#endif
}
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero, any authority is okay. */
int
-router_digest_is_trusted_dir_type(const char *digest, authority_type_t type)
+router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
{
if (!trusted_dir_servers)
return 0;
@@ -2459,44 +2498,20 @@ hexdigest_to_digest(const char *hexdigest, char *digest)
/** Return the router in our routerlist whose hexadecimal key digest
* is <b>hexdigest</b>. Return NULL if no such router is known. */
-routerinfo_t *
+const routerinfo_t *
router_get_by_hexdigest(const char *hexdigest)
{
- char digest[DIGEST_LEN];
- size_t len;
- routerinfo_t *ri;
-
- tor_assert(hexdigest);
- if (!routerlist)
- return NULL;
- if (hexdigest[0]=='$')
- ++hexdigest;
- len = strlen(hexdigest);
- if (hexdigest_to_digest(hexdigest, digest) < 0)
+ if (is_legal_nickname(hexdigest))
return NULL;
- ri = router_get_by_digest(digest);
-
- if (ri && len > HEX_DIGEST_LEN) {
- if (hexdigest[HEX_DIGEST_LEN] == '=') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1) ||
- !ri->is_named)
- return NULL;
- } else if (hexdigest[HEX_DIGEST_LEN] == '~') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1))
- return NULL;
- } else {
- return NULL;
- }
- }
-
- return ri;
+ /* It's not a legal nickname, so it must be a hexdigest or nothing. */
+ return router_get_by_nickname(hexdigest, 1);
}
-/** Return the router in our routerlist whose 20-byte key digest
- * is <b>digest</b>. Return NULL if no such router is known. */
+/** As router_get_by_id_digest,but return a pointer that you're allowed to
+ * modify */
routerinfo_t *
-router_get_by_digest(const char *digest)
+router_get_mutable_by_digest(const char *digest)
{
tor_assert(digest);
@@ -2507,6 +2522,14 @@ router_get_by_digest(const char *digest)
return rimap_get(routerlist->identity_map, digest);
}
+/** Return the router in our routerlist whose 20-byte key digest
+ * is <b>digest</b>. Return NULL if no such router is known. */
+const routerinfo_t *
+router_get_by_id_digest(const char *digest)
+{
+ return router_get_mutable_by_digest(digest);
+}
+
/** Return the router in our routerlist whose 20-byte descriptor
* is <b>digest</b>. Return NULL if no such router is known. */
signed_descriptor_t *
@@ -2557,7 +2580,7 @@ extrainfo_get_by_descriptor_digest(const char *digest)
* The caller must not free the string returned.
*/
static const char *
-signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+signed_descriptor_get_body_impl(const signed_descriptor_t *desc,
int with_annotations)
{
const char *r = NULL;
@@ -2606,7 +2629,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc,
* The caller must not free the string returned.
*/
const char *
-signed_descriptor_get_body(signed_descriptor_t *desc)
+signed_descriptor_get_body(const signed_descriptor_t *desc)
{
return signed_descriptor_get_body_impl(desc, 0);
}
@@ -2614,7 +2637,7 @@ signed_descriptor_get_body(signed_descriptor_t *desc)
/** As signed_descriptor_get_body(), but points to the beginning of the
* annotations section rather than the beginning of the descriptor. */
const char *
-signed_descriptor_get_annotations(signed_descriptor_t *desc)
+signed_descriptor_get_annotations(const signed_descriptor_t *desc)
{
return signed_descriptor_get_body_impl(desc, 1);
}
@@ -2667,7 +2690,6 @@ routerinfo_free(routerinfo_t *router)
}
addr_policy_list_free(router->exit_policy);
- /* XXXX Remove if this turns out to affect performance. */
memset(router, 77, sizeof(routerinfo_t));
tor_free(router);
@@ -2682,7 +2704,6 @@ extrainfo_free(extrainfo_t *extrainfo)
tor_free(extrainfo->cache_info.signed_descriptor_body);
tor_free(extrainfo->pending_sig);
- /* XXXX remove this if it turns out to slow us down. */
memset(extrainfo, 88, sizeof(extrainfo_t)); /* debug bad memory usage */
tor_free(extrainfo);
}
@@ -2696,7 +2717,6 @@ signed_descriptor_free(signed_descriptor_t *sd)
tor_free(sd->signed_descriptor_body);
- /* XXXX remove this once more bugs go away. */
memset(sd, 99, sizeof(signed_descriptor_t)); /* Debug bad mem usage */
tor_free(sd);
}
@@ -2802,8 +2822,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
routerinfo_t *ri_old;
signed_descriptor_t *sd_old;
{
- /* XXXX Remove if this slows us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri);
}
tor_assert(ri->cache_info.routerlist_index == -1);
@@ -2825,6 +2844,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
&ri->cache_info);
smartlist_add(rl->routers, ri);
ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1;
+ nodelist_add_routerinfo(ri);
router_dir_info_changed();
#ifdef DEBUG_ROUTERLIST
routerlist_assert_ok(rl);
@@ -2845,7 +2865,6 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
extrainfo_t *ei_tmp;
{
- /* XXXX remove this code if it slows us down. */
extrainfo_t *ei_generated = router_get_my_extrainfo();
tor_assert(ei_generated != ei);
}
@@ -2891,8 +2910,7 @@ static void
routerlist_insert_old(routerlist_t *rl, routerinfo_t *ri)
{
{
- /* XXXX remove this code if it slows us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri);
}
tor_assert(ri->cache_info.routerlist_index == -1);
@@ -2932,6 +2950,8 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, time_t now)
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri);
+ nodelist_remove_routerinfo(ri);
+
/* make sure the rephist module knows that it's not running */
rep_hist_note_router_unreachable(ri->cache_info.identity_digest, now);
@@ -3043,8 +3063,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
routerinfo_t *ri_tmp;
extrainfo_t *ei_tmp;
{
- /* XXXX Remove this if it turns out to slow us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri_new);
}
tor_assert(ri_old != ri_new);
@@ -3054,6 +3073,9 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri_old);
+ nodelist_remove_routerinfo(ri_old);
+ nodelist_add_routerinfo(ri_new);
+
router_dir_info_changed();
if (idx >= 0) {
smartlist_set(rl->routers, idx, ri_new);
@@ -3200,28 +3222,25 @@ routerlist_reset_warnings(void)
void
router_set_status(const char *digest, int up)
{
- routerinfo_t *router;
- routerstatus_t *status;
+ node_t *node;
tor_assert(digest);
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
if (tor_memeq(d->digest, digest, DIGEST_LEN))
d->is_running = up);
- router = router_get_by_digest(digest);
- if (router) {
- log_debug(LD_DIR,"Marking router '%s/%s' as %s.",
- router->nickname, router->address, up ? "up" : "down");
- if (!up && router_is_me(router) && !we_are_hibernating())
+ node = node_get_mutable_by_id(digest);
+ if (node) {
+#if 0
+ log_debug(LD_DIR,"Marking router %s as %s.",
+ node_describe(node), up ? "up" : "down");
+#endif
+ if (!up && node_is_me(node) && !we_are_hibernating())
log_warn(LD_NET, "We just marked ourself as down. Are your external "
"addresses reachable?");
- router->is_running = up;
- }
- status = router_get_consensus_status_by_id(digest);
- if (status && status->is_running != up) {
- status->is_running = up;
- control_event_networkstatus_changed_single(status);
+ node->is_running = up;
}
+
router_dir_info_changed();
}
@@ -3250,7 +3269,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
int from_cache, int from_fetch)
{
const char *id_digest;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authdir = authdir_mode_handles_descs(options, router->purpose);
int authdir_believes_valid = 0;
routerinfo_t *old_router;
@@ -3265,7 +3284,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
id_digest = router->cache_info.identity_digest;
- old_router = router_get_by_digest(id_digest);
+ old_router = router_get_mutable_by_digest(id_digest);
/* Make sure that we haven't already got this exact descriptor. */
if (sdmap_get(routerlist->desc_digest_map,
@@ -3283,11 +3302,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
router->purpose == ROUTER_PURPOSE_BRIDGE &&
!was_bridge) {
log_info(LD_DIR, "Replacing non-bridge descriptor with bridge "
- "descriptor for router '%s'", router->nickname);
+ "descriptor for router %s",
+ router_describe(router));
} else {
log_info(LD_DIR,
- "Dropping descriptor that we already have for router '%s'",
- router->nickname);
+ "Dropping descriptor that we already have for router %s",
+ router_describe(router));
*msg = "Router descriptor was not new.";
routerinfo_free(router);
return ROUTER_WAS_NOT_NEW;
@@ -3296,12 +3316,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (authdir) {
if (authdir_wants_to_reject_router(router, msg,
- !from_cache && !from_fetch)) {
+ !from_cache && !from_fetch,
+ &authdir_believes_valid)) {
tor_assert(*msg);
routerinfo_free(router);
return ROUTER_AUTHDIR_REJECTS;
}
- authdir_believes_valid = router->is_valid;
} else if (from_fetch) {
/* Only check the descriptor digest against the network statuses when
* we are receiving in response to a fetch. */
@@ -3311,8 +3331,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* We asked for it, so some networkstatus must have listed it when we
* did. Save it if we're a cache in case somebody else asks for it. */
log_info(LD_DIR,
- "Received a no-longer-recognized descriptor for router '%s'",
- router->nickname);
+ "Received a no-longer-recognized descriptor for router %s",
+ router_describe(router));
*msg = "Router descriptor is not referenced by any network-status.";
/* Only journal this desc if we'll be serving it. */
@@ -3328,14 +3348,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
routerstatus_t *rs =
- networkstatus_v2_find_entry(ns, id_digest);
+ networkstatus_v2_find_mutable_entry(ns, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN))
rs->need_to_mirror = 0;
});
if (consensus) {
- routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest);
+ routerstatus_t *rs = networkstatus_vote_find_mutable_entry(
+ consensus, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN)) {
@@ -3363,8 +3384,9 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (router->purpose == ROUTER_PURPOSE_BRIDGE && from_cache &&
!authdir_mode_bridge(options) &&
!routerinfo_is_a_configured_bridge(router)) {
- log_info(LD_DIR, "Dropping bridge descriptor for '%s' because we have "
- "no bridge configured at that address.", router->nickname);
+ log_info(LD_DIR, "Dropping bridge descriptor for %s because we have "
+ "no bridge configured at that address.",
+ safe_str_client(router_describe(router)));
*msg = "Router descriptor was not a configured bridge.";
routerinfo_free(router);
return ROUTER_WAS_NOT_WANTED;
@@ -3375,8 +3397,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (!in_consensus && (router->cache_info.published_on <=
old_router->cache_info.published_on)) {
/* Same key, but old. This one is not listed in the consensus. */
- log_debug(LD_DIR, "Not-new descriptor for router '%s'",
- router->nickname);
+ log_debug(LD_DIR, "Not-new descriptor for router %s",
+ router_describe(router));
/* Only journal this desc if we'll be serving it. */
if (!from_cache && should_cache_old_descriptors())
signed_desc_append_to_journal(&router->cache_info,
@@ -3386,9 +3408,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
return ROUTER_WAS_NOT_NEW;
} else {
/* Same key, and either new, or listed in the consensus. */
- log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]",
- router->nickname, old_router->nickname,
- hex_str(id_digest,DIGEST_LEN));
+ log_debug(LD_DIR, "Replacing entry for router %s",
+ router_describe(router));
if (routers_have_same_or_addr(router, old_router)) {
/* these carry over when the address and orport are unchanged. */
router->last_reachable = old_router->last_reachable;
@@ -3664,8 +3685,8 @@ routerlist_remove_old_routers(void)
/* Too old: remove it. (If we're a cache, just move it into
* old_routers.) */
log_info(LD_DIR,
- "Forgetting obsolete (too old) routerinfo for router '%s'",
- router->nickname);
+ "Forgetting obsolete (too old) routerinfo for router %s",
+ router_describe(router));
routerlist_remove(routerlist, router, 1, now);
i--;
}
@@ -3949,7 +3970,7 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
static int
signed_desc_digest_is_recognized(signed_descriptor_t *desc)
{
- routerstatus_t *rs;
+ const routerstatus_t *rs;
networkstatus_t *consensus = networkstatus_get_latest_consensus();
int caches = directory_caches_dir_info(get_options());
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
@@ -3973,6 +3994,16 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
return 0;
}
+/** Update downloads for router descriptors and/or microdescriptors as
+ * appropriate. */
+void
+update_all_descriptor_downloads(time_t now)
+{
+ update_router_descriptor_downloads(now);
+ update_microdesc_downloads(now);
+ launch_dummy_descriptor_download_as_needed(now, get_options());
+}
+
/** Clear all our timeouts for fetching v2 and v3 directory stuff, and then
* give it all a try again. */
void
@@ -3981,34 +4012,34 @@ routerlist_retry_directory_downloads(time_t now)
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
update_networkstatus_downloads(now);
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
}
-/** Return 1 if all running sufficiently-stable routers will reject
+/** Return 1 if all running sufficiently-stable routers we can use will reject
* addr:port, return 0 if any might accept it. */
int
-router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime)
-{
+router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+ int need_uptime)
+{ /* XXXX MOVE */
addr_policy_result_t r;
- if (!routerlist) return 1;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- !router_is_unreliable(router, need_uptime, 0, 0)) {
- r = compare_addr_to_addr_policy(addr, port, router->exit_policy);
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (node->is_running &&
+ !node_is_unreliable(node, need_uptime, 0, 0)) {
+
+ r = compare_addr_to_node_policy(addr, port, node);
+
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 0; /* this one could be ok. good enough. */
}
- });
+ } SMARTLIST_FOREACH_END(node);
return 1; /* all will reject. */
}
/** Return true iff <b>router</b> does not permit exit streams.
*/
int
-router_exit_policy_rejects_all(routerinfo_t *router)
+router_exit_policy_rejects_all(const routerinfo_t *router)
{
return router->policy_is_reject_star;
}
@@ -4021,7 +4052,7 @@ trusted_dir_server_t *
add_trusted_dir_server(const char *nickname, const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
- authority_type_t type)
+ dirinfo_type_t type)
{
trusted_dir_server_t *ent;
uint32_t a;
@@ -4056,7 +4087,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
ent->is_running = 1;
ent->type = type;
memcpy(ent->digest, digest, DIGEST_LEN);
- if (v3_auth_digest && (type & V3_AUTHORITY))
+ if (v3_auth_digest && (type & V3_DIRINFO))
memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@@ -4135,7 +4166,7 @@ int
any_trusted_dir_is_v1_authority(void)
{
if (trusted_dir_servers)
- return get_n_authorities(V1_AUTHORITY) > 0;
+ return get_n_authorities(V1_DIRINFO) > 0;
return 0;
}
@@ -4143,7 +4174,9 @@ any_trusted_dir_is_v1_authority(void)
/** For every current directory connection whose purpose is <b>purpose</b>,
* and where the resource being downloaded begins with <b>prefix</b>, split
* rest of the resource into base16 fingerprints, decode them, and set the
- * corresponding elements of <b>result</b> to a nonzero value. */
+ * corresponding elements of <b>result</b> to a nonzero value.
+ * DOCDOC purpose==microdesc
+ */
static void
list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix)
@@ -4151,20 +4184,23 @@ list_pending_downloads(digestmap_t *result,
const size_t p_len = strlen(prefix);
smartlist_t *tmp = smartlist_create();
smartlist_t *conns = get_connection_array();
+ int flags = DSR_HEX;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC)
+ flags = DSR_DIGEST256|DSR_BASE64;
tor_assert(result);
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
conn->purpose == purpose &&
!conn->marked_for_close) {
const char *resource = TO_DIR_CONN(conn)->requested_resource;
if (!strcmpstart(resource, prefix))
dir_split_resource_into_fingerprints(resource + p_len,
- tmp, NULL, DSR_HEX);
+ tmp, NULL, flags);
}
- });
+ } SMARTLIST_FOREACH_END(conn);
+
SMARTLIST_FOREACH(tmp, char *, d,
{
digestmap_set(result, d, (void*)1);
@@ -4184,13 +4220,21 @@ list_pending_descriptor_downloads(digestmap_t *result, int extrainfo)
list_pending_downloads(result, purpose, "d/");
}
-/** Launch downloads for all the descriptors whose digests are listed
- * as digests[i] for lo <= i < hi. (Lo and hi may be out of range.)
- * If <b>source</b> is given, download from <b>source</b>; otherwise,
- * download from an appropriate random directory server.
+/** DOCDOC */
+/*XXXX NM should use digest256, if one comes into being. */
+void
+list_pending_microdesc_downloads(digestmap_t *result)
+{
+ list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/");
+}
+
+/** Launch downloads for all the descriptors whose digests or digests256
+ * are listed as digests[i] for lo <= i < hi. (Lo and hi may be out of
+ * range.) If <b>source</b> is given, download from <b>source</b>;
+ * otherwise, download from an appropriate random directory server.
*/
static void
-initiate_descriptor_downloads(routerstatus_t *source,
+initiate_descriptor_downloads(const routerstatus_t *source,
int purpose,
smartlist_t *digests,
int lo, int hi, int pds_flags)
@@ -4198,6 +4242,20 @@ initiate_descriptor_downloads(routerstatus_t *source,
int i, n = hi-lo;
char *resource, *cp;
size_t r_len;
+
+ int digest_len = DIGEST_LEN, enc_digest_len = HEX_DIGEST_LEN;
+ char sep = '+';
+ int b64_256 = 0;
+
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ /* Microdescriptors are downloaded by "-"-separated base64-encoded
+ * 256-bit digests. */
+ digest_len = DIGEST256_LEN;
+ enc_digest_len = BASE64_DIGEST256_LEN;
+ sep = '-';
+ b64_256 = 1;
+ }
+
if (n <= 0)
return;
if (lo < 0)
@@ -4205,15 +4263,19 @@ initiate_descriptor_downloads(routerstatus_t *source,
if (hi > smartlist_len(digests))
hi = smartlist_len(digests);
- r_len = 8 + (HEX_DIGEST_LEN+1)*n;
+ r_len = 8 + (enc_digest_len+1)*n;
cp = resource = tor_malloc(r_len);
memcpy(cp, "d/", 2);
cp += 2;
for (i = lo; i < hi; ++i) {
- base16_encode(cp, r_len-(cp-resource),
- smartlist_get(digests,i), DIGEST_LEN);
- cp += HEX_DIGEST_LEN;
- *cp++ = '+';
+ if (b64_256) {
+ digest256_to_base64(cp, smartlist_get(digests, i));
+ } else {
+ base16_encode(cp, r_len-(cp-resource),
+ smartlist_get(digests,i), digest_len);
+ }
+ cp += enc_digest_len;
+ *cp++ = sep;
}
memcpy(cp-1, ".z", 3);
@@ -4234,9 +4296,10 @@ initiate_descriptor_downloads(routerstatus_t *source,
* running, or otherwise not a descriptor that we would make any
* use of even if we had it. Else return 1. */
static INLINE int
-client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
+client_would_use_router(const routerstatus_t *rs, time_t now,
+ const or_options_t *options)
{
- if (!rs->is_running && !options->FetchUselessDescriptors) {
+ if (!rs->is_flagged_running && !options->FetchUselessDescriptors) {
/* If we had this router descriptor, we wouldn't even bother using it.
* But, if we want to have a complete list, fetch it anyway. */
return 0;
@@ -4260,6 +4323,7 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
* So use 96 because it's a nice number.
*/
#define MAX_DL_PER_REQUEST 96
+#define MAX_MICRODESC_DL_PER_REQUEST 92
/** Don't split our requests so finely that we are requesting fewer than
* this number per server. */
#define MIN_DL_PER_REQUEST 4
@@ -4274,35 +4338,49 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
* them until they have more, or until this amount of time has passed. */
#define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
-/** Given a list of router descriptor digests in <b>downloadable</b>, decide
- * whether to delay fetching until we have more. If we don't want to delay,
- * launch one or more requests to the appropriate directory authorities. */
-static void
-launch_router_descriptor_downloads(smartlist_t *downloadable,
- routerstatus_t *source, time_t now)
+/** Given a <b>purpose</b> (FETCH_MICRODESC or FETCH_SERVERDESC) and a list of
+ * router descriptor digests or microdescriptor digest256s in
+ * <b>downloadable</b>, decide whether to delay fetching until we have more.
+ * If we don't want to delay, launch one or more requests to the appropriate
+ * directory authorities.
+ */
+void
+launch_descriptor_downloads(int purpose,
+ smartlist_t *downloadable,
+ const routerstatus_t *source, time_t now)
{
int should_delay = 0, n_downloadable;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ const char *descname;
+
+ tor_assert(purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
+ purpose == DIR_PURPOSE_FETCH_MICRODESC);
+
+ descname = (purpose == DIR_PURPOSE_FETCH_SERVERDESC) ?
+ "routerdesc" : "microdesc";
n_downloadable = smartlist_len(downloadable);
if (!directory_fetches_dir_info_early(options)) {
if (n_downloadable >= MAX_DL_TO_DELAY) {
log_debug(LD_DIR,
- "There are enough downloadable routerdescs to launch requests.");
+ "There are enough downloadable %ss to launch requests.",
+ descname);
should_delay = 0;
} else {
- should_delay = (last_routerdesc_download_attempted +
+ should_delay = (last_descriptor_download_attempted +
MAX_CLIENT_INTERVAL_WITHOUT_REQUEST) > now;
if (!should_delay && n_downloadable) {
- if (last_routerdesc_download_attempted) {
+ if (last_descriptor_download_attempted) {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we've "
+ "There are not many downloadable %ss, but we've "
"been waiting long enough (%d seconds). Downloading.",
- (int)(now-last_routerdesc_download_attempted));
+ descname,
+ (int)(now-last_descriptor_download_attempted));
} else {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we haven't "
- "tried downloading descriptors recently. Downloading.");
+ "There are not many downloadable %ss, but we haven't "
+ "tried downloading descriptors recently. Downloading.",
+ descname);
}
}
}
@@ -4329,12 +4407,19 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
* update_router_descriptor_downloads() later on, once the connections
* have succeeded or failed.
*/
- pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH;
+ pds_flags |= (purpose == DIR_PURPOSE_FETCH_MICRODESC) ?
+ PDS_NO_EXISTING_MICRODESC_FETCH :
+ PDS_NO_EXISTING_SERVERDESC_FETCH;
}
n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS);
- if (n_per_request > MAX_DL_PER_REQUEST)
- n_per_request = MAX_DL_PER_REQUEST;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ if (n_per_request > MAX_MICRODESC_DL_PER_REQUEST)
+ n_per_request = MAX_MICRODESC_DL_PER_REQUEST;
+ } else {
+ if (n_per_request > MAX_DL_PER_REQUEST)
+ n_per_request = MAX_DL_PER_REQUEST;
+ }
if (n_per_request < MIN_DL_PER_REQUEST)
n_per_request = MIN_DL_PER_REQUEST;
@@ -4349,11 +4434,11 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
req_plural, n_downloadable, rtr_plural, n_per_request);
smartlist_sort_digests(downloadable);
for (i=0; i < n_downloadable; i += n_per_request) {
- initiate_descriptor_downloads(source, DIR_PURPOSE_FETCH_SERVERDESC,
+ initiate_descriptor_downloads(source, purpose,
downloadable, i, i+n_per_request,
pds_flags);
}
- last_routerdesc_download_attempted = now;
+ last_descriptor_download_attempted = now;
}
}
@@ -4369,7 +4454,7 @@ update_router_descriptor_cache_downloads_v2(time_t now)
digestmap_t *map; /* Which descs are in progress, or assigned? */
int i, j, n;
int n_download;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
if (! directory_fetches_dir_info_early(options)) {
@@ -4511,7 +4596,7 @@ void
update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *map = NULL;
smartlist_t *no_longer_old = smartlist_create();
smartlist_t *downloadable = smartlist_create();
@@ -4539,15 +4624,14 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
map = digestmap_new();
list_pending_descriptor_downloads(map, 0);
- SMARTLIST_FOREACH(consensus->routerstatus_list, void *, rsp,
- {
+ SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) {
routerstatus_t *rs =
is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp;
signed_descriptor_t *sd;
if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) {
- routerinfo_t *ri;
+ const routerinfo_t *ri;
++n_have;
- if (!(ri = router_get_by_digest(rs->identity_digest)) ||
+ if (!(ri = router_get_by_id_digest(rs->identity_digest)) ||
tor_memneq(ri->cache_info.signed_descriptor_digest,
sd->signed_descriptor_digest, DIGEST_LEN)) {
/* We have a descriptor with this digest, but either there is no
@@ -4580,17 +4664,19 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
if (is_vote && source) {
char time_bufnew[ISO_TIME_LEN+1];
char time_bufold[ISO_TIME_LEN+1];
- routerinfo_t *oldrouter = router_get_by_digest(rs->identity_digest);
+ const routerinfo_t *oldrouter;
+ oldrouter = router_get_by_id_digest(rs->identity_digest);
format_iso_time(time_bufnew, rs->published_on);
if (oldrouter)
format_iso_time(time_bufold, oldrouter->cache_info.published_on);
log_info(LD_DIR, "Learned about %s (%s vs %s) from %s's vote (%s)",
- rs->nickname, time_bufnew,
+ routerstatus_describe(rs),
+ time_bufnew,
oldrouter ? time_bufold : "none",
source->nickname, oldrouter ? "known" : "unknown");
}
smartlist_add(downloadable, rs->descriptor_digest);
- });
+ } SMARTLIST_FOREACH_END(rsp);
if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)
&& smartlist_len(no_longer_old)) {
@@ -4622,7 +4708,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters,
n_would_reject, n_wouldnt_use, n_inprogress);
- launch_router_descriptor_downloads(downloadable, source, now);
+ launch_descriptor_downloads(DIR_PURPOSE_FETCH_SERVERDESC,
+ downloadable, source, now);
digestmap_free(map, NULL);
done:
@@ -4636,27 +4723,20 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
* do this only when we aren't seeing incoming data. see bug 652. */
#define DUMMY_DOWNLOAD_INTERVAL (20*60)
-/** Launch downloads for router status as needed. */
-void
-update_router_descriptor_downloads(time_t now)
+/** As needed, launch a dummy router descriptor fetch to see if our
+ * address has changed. */
+static void
+launch_dummy_descriptor_download_as_needed(time_t now,
+ const or_options_t *options)
{
- or_options_t *options = get_options();
static time_t last_dummy_download = 0;
- if (should_delay_dir_fetches(options))
- return;
- if (directory_fetches_dir_info_early(options)) {
- update_router_descriptor_cache_downloads_v2(now);
- }
- update_consensus_router_descriptor_downloads(now, 0,
- networkstatus_get_reasonably_live_consensus(now));
-
/* XXXX023 we could be smarter here; see notes on bug 652. */
/* If we're a server that doesn't have a configured address, we rely on
* directory fetches to learn when our address changes. So if we haven't
* tried to get any routerdescs in a long time, try a dummy fetch now. */
if (!options->Address &&
server_mode(options) &&
- last_routerdesc_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
+ last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) {
last_dummy_download = now;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
@@ -4665,11 +4745,28 @@ update_router_descriptor_downloads(time_t now)
}
}
+/** Launch downloads for router status as needed. */
+void
+update_router_descriptor_downloads(time_t now)
+{
+ const or_options_t *options = get_options();
+ if (should_delay_dir_fetches(options))
+ return;
+ if (!we_fetch_router_descriptors(options))
+ return;
+ if (directory_fetches_dir_info_early(options)) {
+ update_router_descriptor_cache_downloads_v2(now);
+ }
+
+ update_consensus_router_descriptor_downloads(now, 0,
+ networkstatus_get_reasonably_live_consensus(now, FLAV_NS));
+}
+
/** Launch extrainfo downloads as needed. */
void
update_extrainfo_downloads(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
routerlist_t *rl;
smartlist_t *wanted;
digestmap_t *pending;
@@ -4697,7 +4794,7 @@ update_extrainfo_downloads(time_t now)
sd = &((routerinfo_t*)smartlist_get(lst, i))->cache_info;
if (sd->is_extrainfo)
continue; /* This should never happen. */
- if (old_routers && !router_get_by_digest(sd->identity_digest))
+ if (old_routers && !router_get_by_id_digest(sd->identity_digest))
continue; /* Couldn't check the signature if we got it. */
if (sd->extrainfo_is_bogus)
continue;
@@ -4791,23 +4888,31 @@ get_dir_info_status_string(void)
static void
count_usable_descriptors(int *num_present, int *num_usable,
const networkstatus_t *consensus,
- or_options_t *options, time_t now,
+ const or_options_t *options, time_t now,
routerset_t *in_set)
{
+ const int md = (consensus->flavor == FLAV_MICRODESC);
*num_present = 0, *num_usable=0;
- SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
- {
- if (in_set && ! routerset_contains_routerstatus(in_set, rs))
+ SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
+ {
+ if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
continue;
if (client_would_use_router(rs, now, options)) {
+ const char * const digest = rs->descriptor_digest;
+ int present;
++*num_usable; /* the consensus says we want it. */
- if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
+ if (md)
+ present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest);
+ else
+ present = NULL != router_get_by_descriptor_digest(digest);
+ if (present) {
/* we have the descriptor listed in the consensus. */
++*num_present;
}
}
- });
+ }
+ SMARTLIST_FOREACH_END(rs);
log_debug(LD_DIR, "%d usable, %d present.", *num_usable, *num_present);
}
@@ -4821,7 +4926,7 @@ count_loading_descriptors_progress(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now);
+ networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
double fraction;
if (!consensus)
@@ -4849,16 +4954,16 @@ update_router_have_minimum_dir_info(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
int res;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now);
+ networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
if (!consensus) {
if (!networkstatus_get_latest_consensus())
- strlcpy(dir_info_status, "We have no network-status consensus.",
+ strlcpy(dir_info_status, "We have no usable consensus.",
sizeof(dir_info_status));
else
- strlcpy(dir_info_status, "We have no recent network-status consensus.",
+ strlcpy(dir_info_status, "We have no recent usable consensus.",
sizeof(dir_info_status));
res = 0;
goto done;
@@ -4937,7 +5042,7 @@ void
router_reset_descriptor_download_failures(void)
{
networkstatus_reset_download_failures();
- last_routerdesc_download_attempted = 0;
+ last_descriptor_download_attempted = 0;
if (!routerlist)
return;
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
@@ -4961,7 +5066,7 @@ router_reset_descriptor_download_failures(void)
* would not cause a recent (post 0.1.1.6) dirserver to republish.
*/
int
-router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
+router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
{
time_t r1pub, r2pub;
long time_difference;
@@ -4969,7 +5074,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
/* r1 should be the one that was published first. */
if (r1->cache_info.published_on > r2->cache_info.published_on) {
- routerinfo_t *ri_tmp = r2;
+ const routerinfo_t *ri_tmp = r2;
r2 = r1;
r1 = ri_tmp;
}
@@ -4988,7 +5093,6 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
(r1->contact_info && r2->contact_info &&
strcasecmp(r1->contact_info, r2->contact_info)) ||
r1->is_hibernating != r2->is_hibernating ||
- r1->has_old_dnsworkers != r2->has_old_dnsworkers ||
cmp_addr_policies(r1->exit_policy, r2->exit_policy))
return 0;
if ((r1->declared_family == NULL) != (r2->declared_family == NULL))
@@ -5043,7 +5147,8 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
* incompatibility (if any).
**/
int
-routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
+routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
+ extrainfo_t *ei,
signed_descriptor_t *sd,
const char **msg)
{
@@ -5051,7 +5156,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
tor_assert(ri);
tor_assert(ei);
if (!sd)
- sd = &ri->cache_info;
+ sd = (signed_descriptor_t*)&ri->cache_info;
if (ei->bad_sig) {
if (msg) *msg = "Extrainfo signature was bad, or signed with wrong key.";
@@ -5116,7 +5221,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
/** Assert that the internal representation of <b>rl</b> is
* self-consistent. */
void
-routerlist_assert_ok(routerlist_t *rl)
+routerlist_assert_ok(const routerlist_t *rl)
{
routerinfo_t *r2;
signed_descriptor_t *sd2;
@@ -5206,7 +5311,7 @@ routerlist_assert_ok(routerlist_t *rl)
* If <b>router</b> is NULL, it just frees its internal memory and returns.
*/
const char *
-esc_router_info(routerinfo_t *router)
+esc_router_info(const routerinfo_t *router)
{
static char *info=NULL;
char *esc_contact, *esc_platform;
@@ -5308,38 +5413,6 @@ routerset_get_countryname(const char *c)
return country;
}
-#if 0
-/** Add the GeoIP database's integer index (+1) of a valid two-character
- * country code to the routerset's <b>countries</b> bitarray. Return the
- * integer index if the country code is valid, -1 otherwise.*/
-static int
-routerset_add_country(const char *c)
-{
- char country[3];
- country_t cc;
-
- /* XXXX: Country codes must be of the form \{[a-z\?]{2}\} but this accepts
- \{[.]{2}\}. Do we need to be strict? -RH */
- /* Nope; if the country code is bad, we'll get 0 when we look it up. */
-
- if (!geoip_is_loaded()) {
- log(LOG_WARN, LD_CONFIG, "GeoIP database not loaded: Cannot add country"
- "entry %s, ignoring.", c);
- return -1;
- }
-
- memcpy(country, c+1, 2);
- country[2] = '\0';
- tor_strlower(country);
-
- if ((cc=geoip_get_country(country))==-1) {
- log(LOG_WARN, LD_CONFIG, "Country code '%s' is not valid, ignoring.",
- country);
- }
- return cc;
-}
-#endif
-
/** Update the routerset's <b>countries</b> bitarray_t. Called whenever
* the GeoIP database is reloaded.
*/
@@ -5428,7 +5501,7 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
void
refresh_all_country_info(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->EntryNodes)
routerset_refresh_countries(options->EntryNodes);
@@ -5441,7 +5514,7 @@ refresh_all_country_info(void)
if (options->_ExcludeExitNodesUnion)
routerset_refresh_countries(options->_ExcludeExitNodesUnion);
- routerlist_refresh_countries();
+ nodelist_refresh_countries();
}
/** Add all members of the set <b>source</b> to <b>target</b>. */
@@ -5491,11 +5564,10 @@ routerset_is_empty(const routerset_t *set)
static int
routerset_contains(const routerset_t *set, const tor_addr_t *addr,
uint16_t orport,
- const char *nickname, const char *id_digest, int is_named,
+ const char *nickname, const char *id_digest,
country_t country)
{
if (!set || !set->list) return 0;
- (void) is_named; /* not supported */
if (nickname && strmap_get_lc(set->names, nickname))
return 4;
if (id_digest && digestmap_get(set->digests, id_digest))
@@ -5523,13 +5595,14 @@ routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
ei->port,
ei->nickname,
ei->identity_digest,
- -1, /*is_named*/
-1 /*country*/);
}
-/** Return true iff <b>ri</b> is in <b>set</b>. */
+/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_router(const routerset_t *set, routerinfo_t *ri)
+routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -5538,13 +5611,15 @@ routerset_contains_router(const routerset_t *set, routerinfo_t *ri)
ri->or_port,
ri->nickname,
ri->cache_info.identity_digest,
- ri->is_named,
- ri->country);
+ country);
}
-/** Return true iff <b>rs</b> is in <b>set</b>. */
+/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs)
+routerset_contains_routerstatus(const routerset_t *set,
+ const routerstatus_t *rs,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, rs->addr);
@@ -5553,50 +5628,59 @@ routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs)
rs->or_port,
rs->nickname,
rs->identity_digest,
- rs->is_named,
- -1);
+ country);
+}
+
+/** Return true iff <b>node</b> is in <b>set</b>. */
+int
+routerset_contains_node(const routerset_t *set, const node_t *node)
+{
+ if (node->rs)
+ return routerset_contains_routerstatus(set, node->rs, node->country);
+ else if (node->ri)
+ return routerset_contains_router(set, node->ri, node->country);
+ else
+ return 0;
}
-/** Add every known routerinfo_t that is a member of <b>routerset</b> to
+/** Add every known node_t that is a member of <b>routerset</b> to
* <b>out</b>, but never add any that are part of <b>excludeset</b>.
* If <b>running_only</b>, only add the running ones. */
void
-routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset, int running_only)
-{
+routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ const routerset_t *excludeset, int running_only)
+{ /* XXXX MOVE */
tor_assert(out);
if (!routerset || !routerset->list)
return;
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
- if (routerset_is_list(routerset)) {
+ if (routerset_is_list(routerset)) {
/* No routers are specified by type; all are given by name or digest.
* we can do a lookup in O(len(routerset)). */
SMARTLIST_FOREACH(routerset->list, const char *, name, {
- routerinfo_t *router = router_get_by_nickname(name, 1);
- if (router) {
- if (!running_only || router->is_running)
- if (!routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ const node_t *node = node_get_by_nickname(name, 1);
+ if (node) {
+ if (!running_only || node->is_running)
+ if (!routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
}
});
} else {
/* We need to iterate over the routerlist to get all the ones of the
* right kind. */
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
- if (running_only && !router->is_running)
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (running_only && !node->is_running)
continue;
- if (routerset_contains_router(routerset, router) &&
- !routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ if (routerset_contains_node(routerset, node) &&
+ !routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
});
}
}
#if 0
-/** Add to <b>target</b> every routerinfo_t from <b>source</b> except:
+/** Add to <b>target</b> every node_t from <b>source</b> except:
*
* 1) Don't add it if <b>include</b> is non-empty and the relay isn't in
* <b>include</b>; and
@@ -5605,40 +5689,40 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
* 3) If <b>running_only</b>, don't add non-running routers.
*/
void
-routersets_get_disjunction(smartlist_t *target,
+routersets_get_node_disjunction(smartlist_t *target,
const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only)
{
- SMARTLIST_FOREACH(source, routerinfo_t *, router, {
+ SMARTLIST_FOREACH(source, const node_t *, node, {
int include_result;
- if (running_only && !router->is_running)
+ if (running_only && !node->is_running)
continue;
if (!routerset_is_empty(include))
- include_result = routerset_contains_router(include, router);
+ include_result = routerset_contains_node(include, node);
else
include_result = 1;
if (include_result) {
- int exclude_result = routerset_contains_router(exclude, router);
+ int exclude_result = routerset_contains_node(exclude, node);
if (include_result >= exclude_result)
- smartlist_add(target, router);
+ smartlist_add(target, (void*)node);
}
});
}
#endif
-/** Remove every routerinfo_t from <b>lst</b> that is in <b>routerset</b>. */
+/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */
void
-routerset_subtract_routers(smartlist_t *lst, const routerset_t *routerset)
-{
+routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset)
+{ /*XXXX MOVE ? */
tor_assert(lst);
if (!routerset)
return;
- SMARTLIST_FOREACH(lst, routerinfo_t *, r, {
- if (routerset_contains_router(routerset, r)) {
+ SMARTLIST_FOREACH(lst, const node_t *, node, {
+ if (routerset_contains_node(routerset, node)) {
//log_debug(LD_DIR, "Subtracting %s",r->nickname);
- SMARTLIST_DEL_CURRENT(lst, r);
+ SMARTLIST_DEL_CURRENT(lst, node);
}
});
}
@@ -5704,18 +5788,23 @@ routerset_free(routerset_t *routerset)
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
-routerinfo_set_country(routerinfo_t *ri)
+node_set_country(node_t *node)
{
- ri->country = geoip_get_country_by_ip(ri->addr);
+ if (node->rs)
+ node->country = geoip_get_country_by_ip(node->rs->addr);
+ else if (node->ri)
+ node->country = geoip_get_country_by_ip(node->ri->addr);
+ else
+ node->country = -1;
}
/** Set the country code of all routers in the routerlist. */
void
-routerlist_refresh_countries(void)
+nodelist_refresh_countries(void) /* MOVE */
{
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
- routerinfo_set_country(ri));
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node,
+ node_set_country(node));
}
/** Determine the routers that are responsible for <b>id</b> (binary) and
@@ -5758,7 +5847,7 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
int
hid_serv_acting_as_directory(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
if (!get_options()->HidServDirectoryV2) {
@@ -5774,7 +5863,7 @@ hid_serv_acting_as_directory(void)
int
hid_serv_responsible_for_desc_id(const char *query)
{
- routerinfo_t *me;
+ const routerinfo_t *me;
routerstatus_t *last_rs;
const char *my_id, *last_id;
int result;
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index fec18705b..3a8af6fd9 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -11,7 +11,7 @@
#ifndef _TOR_ROUTERLIST_H
#define _TOR_ROUTERLIST_H
-int get_n_authorities(authority_type_t type);
+int get_n_authorities(dirinfo_type_t type);
int trusted_dirs_reload_certs(void);
int trusted_dirs_load_certs_from_string(const char *contents, int from_store,
int flush);
@@ -27,53 +27,51 @@ int router_reload_router_list(void);
int authority_cert_dl_looks_uncertain(const char *id_digest);
smartlist_t *router_get_trusted_dir_servers(void);
-routerstatus_t *router_pick_directory_server(authority_type_t type, int flags);
+const routerstatus_t *router_pick_directory_server(dirinfo_type_t type,
+ int flags);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
-routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags);
+const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type,
+ int flags);
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
-void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
-int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2);
+void routerlist_add_family(smartlist_t *sl, const routerinfo_t *router);
int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
-void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running);
-int router_nickname_is_in_list(routerinfo_t *router, const char *list);
-routerinfo_t *routerlist_find_my_routerinfo(void);
-routerinfo_t *router_find_exact_exit_enclave(const char *address,
+int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
+const routerinfo_t *routerlist_find_my_routerinfo(void);
+const node_t *router_find_exact_exit_enclave(const char *address,
uint16_t port);
-int router_is_unreliable(routerinfo_t *router, int need_uptime,
+int node_is_unreliable(const node_t *router, int need_uptime,
int need_capacity, int need_guard);
-uint32_t router_get_advertised_bandwidth(routerinfo_t *router);
-uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
-routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
-routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
+const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule);
-routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
+const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
struct routerset_t *excludedset,
router_crn_flags_t flags);
-routerinfo_t *router_get_by_nickname(const char *nickname,
+const routerinfo_t *router_get_by_nickname(const char *nickname,
int warn_if_unnamed);
-int router_digest_version_as_new_as(const char *digest, const char *cutoff);
+int router_is_named(const routerinfo_t *router);
int router_digest_is_trusted_dir_type(const char *digest,
- authority_type_t type);
+ dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \
- router_digest_is_trusted_dir_type((d), NO_AUTHORITY)
+ router_digest_is_trusted_dir_type((d), NO_DIRINFO)
int router_addr_is_trusted_dir(uint32_t addr);
int hexdigest_to_digest(const char *hexdigest, char *digest);
-routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
-routerinfo_t *router_get_by_digest(const char *digest);
+const routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
+const routerinfo_t *router_get_by_id_digest(const char *digest);
+routerinfo_t *router_get_mutable_by_digest(const char *digest);
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
-const char *signed_descriptor_get_body(signed_descriptor_t *desc);
-const char *signed_descriptor_get_annotations(signed_descriptor_t *desc);
+const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
+const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
routerlist_t *router_get_routerlist(void);
void routerinfo_free(routerinfo_t *router);
void extrainfo_free(extrainfo_t *extrainfo);
@@ -132,63 +130,71 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
int descriptor_digests);
void routerlist_retry_directory_downloads(time_t now);
-int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime);
-int router_exit_policy_rejects_all(routerinfo_t *router);
+int router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+ int need_uptime);
+
+int router_exit_policy_rejects_all(const routerinfo_t *router);
trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
- authority_type_t type);
+ dirinfo_type_t type);
void authority_cert_free(authority_cert_t *cert);
void clear_trusted_dir_servers(void);
int any_trusted_dir_is_v1_authority(void);
void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus);
void update_router_descriptor_downloads(time_t now);
+void update_all_descriptor_downloads(time_t now);
void update_extrainfo_downloads(time_t now);
int router_have_minimum_dir_info(void);
void router_dir_info_changed(void);
const char *get_dir_info_status_string(void);
int count_loading_descriptors_progress(void);
void router_reset_descriptor_download_failures(void);
-int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2);
-int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
+int router_differences_are_cosmetic(const routerinfo_t *r1,
+ const routerinfo_t *r2);
+int routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
+ extrainfo_t *ei,
signed_descriptor_t *sd,
const char **msg);
-void routerlist_assert_ok(routerlist_t *rl);
-const char *esc_router_info(routerinfo_t *router);
+void routerlist_assert_ok(const routerlist_t *rl);
+const char *esc_router_info(const routerinfo_t *router);
void routers_sort_by_identity(smartlist_t *routers);
routerset_t *routerset_new(void);
+void routerset_refresh_countries(routerset_t *rs);
int routerset_parse(routerset_t *target, const char *s,
const char *description);
void routerset_union(routerset_t *target, const routerset_t *source);
int routerset_is_list(const routerset_t *set);
int routerset_needs_geoip(const routerset_t *set);
int routerset_is_empty(const routerset_t *set);
-int routerset_contains_router(const routerset_t *set, routerinfo_t *ri);
+int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country);
int routerset_contains_routerstatus(const routerset_t *set,
- routerstatus_t *rs);
+ const routerstatus_t *rs,
+ country_t country);
int routerset_contains_extendinfo(const routerset_t *set,
const extend_info_t *ei);
-void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset,
- int running_only);
+
+int routerset_contains_node(const routerset_t *set, const node_t *node);
+void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ const routerset_t *excludeset,
+ int running_only);
#if 0
-void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
+void routersets_get_node_disjunction(smartlist_t *target,
+ const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only);
#endif
-void routerset_subtract_routers(smartlist_t *out,
+void routerset_subtract_nodes(smartlist_t *out,
const routerset_t *routerset);
+
char *routerset_to_string(const routerset_t *routerset);
-void routerset_refresh_countries(routerset_t *target);
int routerset_equal(const routerset_t *old, const routerset_t *new);
void routerset_free(routerset_t *routerset);
-void routerinfo_set_country(routerinfo_t *ri);
-void routerlist_refresh_countries(void);
void refresh_all_country_info(void);
int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
@@ -196,5 +202,16 @@ int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
int hid_serv_acting_as_directory(void);
int hid_serv_responsible_for_desc_id(const char *id);
+void list_pending_microdesc_downloads(digestmap_t *result);
+void launch_descriptor_downloads(int purpose,
+ smartlist_t *downloadable,
+ const routerstatus_t *source,
+ time_t now);
+
+int hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_out,
+ char *nickname_out);
+
#endif
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index ce98a47b6..d1b2cd0fb 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -70,7 +70,6 @@ typedef enum {
K_V,
K_W,
K_M,
- K_EVENTDNS,
K_EXTRA_INFO,
K_EXTRA_INFO_DIGEST,
K_CACHES_EXTRA_INFO,
@@ -287,7 +286,6 @@ static token_rule_t routerdesc_token_table[] = {
T01("family", K_FAMILY, ARGS, NO_OBJ ),
T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
- T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
@@ -1210,7 +1208,8 @@ router_parse_list_from_string(const char **s, const char *eos,
prepend_annotations);
if (router) {
log_debug(LD_DIR, "Read router '%s', purpose '%s'",
- router->nickname, router_purpose_to_string(router->purpose));
+ router_describe(router),
+ router_purpose_to_string(router->purpose));
signed_desc = &router->cache_info;
elt = router;
}
@@ -1357,7 +1356,6 @@ router_parse_entry_from_string(const char *s, const char *end,
tor_assert(tok->n_args >= 5);
router = tor_malloc_zero(sizeof(routerinfo_t));
- router->country = -1;
router->cache_info.routerlist_index = -1;
router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
router->cache_info.signed_descriptor_len = end-s;
@@ -1503,13 +1501,6 @@ router_parse_entry_from_string(const char *s, const char *end,
router->contact_info = tor_strdup(tok->args[0]);
}
- if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
- router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
- } else if (router->platform) {
- if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
- router->has_old_dnsworkers = 1;
- }
-
if (find_opt_by_keyword(tokens, K_REJECT6) ||
find_opt_by_keyword(tokens, K_ACCEPT6)) {
log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
@@ -1543,10 +1534,10 @@ router_parse_entry_from_string(const char *s, const char *end,
}
}
- if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
+ if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))
router->caches_extra_info = 1;
- if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)))
+ if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))
router->allow_single_hop_exits = 1;
if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
@@ -1559,7 +1550,7 @@ router_parse_entry_from_string(const char *s, const char *end,
}
}
- if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
+ if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) {
router->wants_to_be_hs_dir = 1;
}
@@ -1574,8 +1565,6 @@ router_parse_entry_from_string(const char *s, const char *end,
"router descriptor") < 0)
goto err;
- routerinfo_set_country(router);
-
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
@@ -1975,6 +1964,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
if (!consensus_method)
flav = FLAV_NS;
+ tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
eos = find_start_of_next_routerstatus(*s);
@@ -1987,15 +1977,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
goto err;
}
tok = find_by_keyword(tokens, K_R);
- tor_assert(tok->n_args >= 7);
+ tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
if (flav == FLAV_NS) {
if (tok->n_args < 8) {
log_warn(LD_DIR, "Too few arguments to r");
goto err;
}
- } else {
- offset = -1;
+ } else if (flav == FLAV_MICRODESC) {
+ offset = -1; /* There is no identity digest */
}
+
if (vote_rs) {
rs = &vote_rs->status;
} else {
@@ -2069,7 +2060,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
else if (!strcmp(tok->args[i], "Fast"))
rs->is_fast = 1;
else if (!strcmp(tok->args[i], "Running"))
- rs->is_running = 1;
+ rs->is_flagged_running = 1;
else if (!strcmp(tok->args[i], "Named"))
rs->is_named = 1;
else if (!strcmp(tok->args[i], "Valid"))
@@ -2100,6 +2091,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_supports_begindir = 1;
rs->version_supports_extrainfo_upload = 1;
rs->version_supports_conditional_consensus = 1;
+ rs->version_supports_microdesc_cache = 1;
} else {
rs->version_supports_begindir =
tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
@@ -2109,6 +2101,14 @@ routerstatus_parse_entry_from_string(memarea_t *area,
tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
rs->version_supports_conditional_consensus =
tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
+ /* XXXX023 NM microdescs: 0.2.3.1-alpha isn't widely used yet, but
+ * not all 0.2.3.0-alpha "versions" actually support microdesc cacheing
+ * right. There's a compromise here. Since this is 5 May, let's
+ * err on the side of having some possible caches to use. Once more
+ * caches are running 0.2.3.1-alpha, we can bump this version number.
+ */
+ rs->version_supports_microdesc_cache =
+ tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);
@@ -2171,6 +2171,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
vote_rs->microdesc = line;
}
} SMARTLIST_FOREACH_END(t);
+ } else if (flav == FLAV_MICRODESC) {
+ tok = find_opt_by_keyword(tokens, K_M);
+ if (tok) {
+ tor_assert(tok->n_args);
+ if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
+ log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
+ escaped(tok->args[0]));
+ goto err;
+ }
+ }
}
if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
@@ -2493,7 +2503,7 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
} else {
log_warn(LD_BUG, "Missing consensus bandwidth for router %s",
- rs->nickname);
+ routerstatus_describe(rs));
}
} SMARTLIST_FOREACH_END(rs);
@@ -3502,10 +3512,10 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
siglist = detached_get_signatures(sigs, flavor);
is_duplicate = 0;
- SMARTLIST_FOREACH(siglist, document_signature_t *, s, {
- if (s->alg == alg &&
- tor_memeq(id_digest, s->identity_digest, DIGEST_LEN) &&
- tor_memeq(sk_digest, s->signing_key_digest, DIGEST_LEN)) {
+ SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, {
+ if (dsig->alg == alg &&
+ tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) &&
+ tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) {
is_duplicate = 1;
}
});
@@ -3764,9 +3774,9 @@ token_check_object(memarea_t *area, const char *kwd,
break;
case NEED_KEY_1024: /* There must be a 1024-bit public key. */
case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
- if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
+ if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
- kwd, (int)crypto_pk_keysize(tok->key));
+ kwd, crypto_pk_num_bits(tok->key));
RET_ERR(ebuf);
}
/* fall through */
@@ -4358,7 +4368,7 @@ microdescs_parse_from_string(const char *s, const char *eos,
}
if ((tok = find_opt_by_keyword(tokens, K_P))) {
- md->exitsummary = tor_strdup(tok->args[0]);
+ md->exit_policy = parse_short_policy(tok->args[0]);
}
crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
diff --git a/src/or/status.c b/src/or/status.c
new file mode 100644
index 000000000..acb8ba414
--- /dev/null
+++ b/src/or/status.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file status.c
+ * \brief Keep status information and log the heartbeat messages.
+ **/
+
+#include "or.h"
+#include "config.h"
+#include "status.h"
+#include "nodelist.h"
+#include "router.h"
+#include "circuitlist.h"
+#include "main.h"
+
+/** Return the total number of circuits. */
+static int
+count_circuits(void)
+{
+ circuit_t *circ;
+ int nr=0;
+
+ for (circ = _circuit_get_global_list(); circ; circ = circ->next)
+ nr++;
+
+ return nr;
+}
+
+/** Take seconds <b>secs</b> and return a newly allocated human-readable
+ * uptime string */
+static char *
+secs_to_uptime(long secs)
+{
+ long int days = secs / 86400;
+ int hours = (int)((secs - (days * 86400)) / 3600);
+ int minutes = (int)((secs - (days * 86400) - (hours * 3600)) / 60);
+ char *uptime_string = NULL;
+
+ switch (days) {
+ case 0:
+ tor_asprintf(&uptime_string, "%d:%02d hours", hours, minutes);
+ break;
+ case 1:
+ tor_asprintf(&uptime_string, "%ld day %d:%02d hours",
+ days, hours, minutes);
+ break;
+ default:
+ tor_asprintf(&uptime_string, "%ld days %d:%02d hours",
+ days, hours, minutes);
+ break;
+ }
+
+ return uptime_string;
+}
+
+/** Take <b>bytes</b> and returns a newly allocated human-readable usage
+ * string. */
+static char *
+bytes_to_usage(uint64_t bytes)
+{
+ char *bw_string = NULL;
+
+ if (bytes < (1<<20)) { /* Less than a megabyte. */
+ tor_asprintf(&bw_string, U64_FORMAT" kB", U64_PRINTF_ARG(bytes>>10));
+ } else if (bytes < (1<<30)) { /* Megabytes. Let's add some precision. */
+ double bw = U64_TO_DBL(bytes);
+ tor_asprintf(&bw_string, "%.2f MB", bw/(1<<20));
+ } else { /* Gigabytes. */
+ double bw = U64_TO_DBL(bytes);
+ tor_asprintf(&bw_string, "%.2f GB", bw/(1<<30));
+ }
+
+ return bw_string;
+}
+
+/** Log a "heartbeat" message describing Tor's status and history so that the
+ * user can know that there is indeed a running Tor. Return 0 on success and
+ * -1 on failure. */
+int
+log_heartbeat(time_t now)
+{
+ char *bw_sent = NULL;
+ char *bw_rcvd = NULL;
+ char *uptime = NULL;
+ const routerinfo_t *me;
+
+ const or_options_t *options = get_options();
+ (void)now;
+
+ if (public_server_mode(options)) {
+ /* Let's check if we are in the current cached consensus. */
+ if (!(me = router_get_my_routerinfo()))
+ return -1; /* Something stinks, we won't even attempt this. */
+ else
+ if (!node_get_by_id(me->cache_info.identity_digest))
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: It seems like we are not "
+ "in the cached consensus.");
+ }
+
+ uptime = secs_to_uptime(get_uptime());
+ bw_rcvd = bytes_to_usage(get_bytes_read());
+ bw_sent = bytes_to_usage(get_bytes_written());
+
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d "
+ "circuits open. I've pushed %s and received %s.",
+ uptime, count_circuits(),bw_sent,bw_rcvd);
+
+ tor_free(uptime);
+ tor_free(bw_sent);
+ tor_free(bw_rcvd);
+
+ return 0;
+}
+
diff --git a/src/or/status.h b/src/or/status.h
new file mode 100644
index 000000000..ac726a1d2
--- /dev/null
+++ b/src/or/status.h
@@ -0,0 +1,10 @@
+/* Copyright (c) 2010, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef _TOR_STATUS_H
+#define _TOR_STATUS_H
+
+int log_heartbeat(time_t now);
+
+#endif
+
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 546fa2f4b..852715079 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -1,6 +1,6 @@
TESTS = test
-noinst_PROGRAMS = test
+noinst_PROGRAMS = test test-child
AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
-DLOCALSTATEDIR="\"$(localstatedir)\"" \
@@ -8,16 +8,17 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
-I"$(top_srcdir)/src/or"
# -L flags need to go in LDFLAGS. -l flags need to go in LDADD.
-# This seems to matter nowhere but on windows, but I assure you that it
+# This seems to matter nowhere but on Windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
test_SOURCES = \
- test_data.c \
test.c \
test_addr.c \
+ test_containers.c \
test_crypto.c \
+ test_data.c \
test_dir.c \
- test_containers.c \
+ test_microdesc.c \
test_util.c \
tinytest.c
@@ -25,6 +26,12 @@ test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
@TOR_LDFLAGS_libevent@
test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \
../common/libor-event.a \
- @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS = \
+ tinytest.h \
+ tinytest_macros.h \
+ test.h
+
-noinst_HEADERS = tinytest.h tinytest_macros.h test.h
diff --git a/src/test/test-child.c b/src/test/test-child.c
new file mode 100644
index 000000000..ca52750c2
--- /dev/null
+++ b/src/test/test-child.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+/** Trivial test program which prints out its command line arguments so we can
+ * check if tor_spawn_background() works */
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ fprintf(stdout, "OUT\n");
+ fprintf(stderr, "ERR\n");
+ for (i = 1; i < argc; i++)
+ fprintf(stdout, "%s\n", argv[i]);
+ fprintf(stdout, "DONE\n");
+
+ return 0;
+}
+
diff --git a/src/test/test.c b/src/test/test.c
index 9b24a99b5..02d238e26 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -119,30 +119,46 @@ get_fname(const char *name)
return buf;
}
-/** Remove all files stored under the temporary directory, and the directory
- * itself. Called by atexit(). */
+/* Remove a directory and all of its subdirectories */
static void
-remove_directory(void)
+rm_rf(const char *dir)
{
+ struct stat st;
smartlist_t *elements;
- if (getpid() != temp_dir_setup_in_pid) {
- /* Only clean out the tempdir when the main process is exiting. */
- return;
- }
- elements = tor_listdir(temp_dir);
+
+ elements = tor_listdir(dir);
if (elements) {
SMARTLIST_FOREACH(elements, const char *, cp,
{
- size_t len = strlen(cp)+strlen(temp_dir)+16;
- char *tmp = tor_malloc(len);
- tor_snprintf(tmp, len, "%s"PATH_SEPARATOR"%s", temp_dir, cp);
- unlink(tmp);
+ char *tmp = NULL;
+ tor_asprintf(&tmp, "%s"PATH_SEPARATOR"%s", dir, cp);
+ if (0 == stat(tmp,&st) && (st.st_mode & S_IFDIR)) {
+ rm_rf(tmp);
+ } else {
+ if (unlink(tmp)) {
+ fprintf(stderr, "Error removing %s: %s\n", tmp, strerror(errno));
+ }
+ }
tor_free(tmp);
});
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements);
}
- rmdir(temp_dir);
+ if (rmdir(dir))
+ fprintf(stderr, "Error removing directory %s: %s\n", dir, strerror(errno));
+}
+
+/** Remove all files stored under the temporary directory, and the directory
+ * itself. Called by atexit(). */
+static void
+remove_directory(void)
+{
+ if (getpid() != temp_dir_setup_in_pid) {
+ /* Only clean out the tempdir when the main process is exiting. */
+ return;
+ }
+
+ rm_rf(temp_dir);
}
/** Define this if unit tests spend too much time generating public keys*/
@@ -566,6 +582,7 @@ test_policy_summary_helper(const char *policy_str,
smartlist_t *policy = smartlist_create();
char *summary = NULL;
int r;
+ short_policy_t *short_policy = NULL;
line.key = (char*)"foo";
line.value = (char *)policy_str;
@@ -578,10 +595,14 @@ test_policy_summary_helper(const char *policy_str,
test_assert(summary != NULL);
test_streq(summary, expected_summary);
+ short_policy = parse_short_policy(summary);
+ tt_assert(short_policy);
+
done:
tor_free(summary);
if (policy)
addr_policy_list_free(policy);
+ short_policy_free(short_policy);
}
/** Run unit tests for generating summary lines of exit policies */
@@ -1053,8 +1074,8 @@ test_geoip(void)
test_streq("??", NAMEFOR(2000));
#undef NAMEFOR
- get_options()->BridgeRelay = 1;
- get_options()->BridgeRecordUsageByCountry = 1;
+ get_options_mutable()->BridgeRelay = 1;
+ get_options_mutable()->BridgeRecordUsageByCountry = 1;
/* Put 9 observations in AB... */
for (i=32; i < 40; ++i)
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200);
@@ -1089,7 +1110,8 @@ test_stats(void)
char *s = NULL;
int i;
- /* We shouldn't collect exit stats without initializing them. */
+ /* Start with testing exit port statistics; we shouldn't collect exit
+ * stats without initializing them. */
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
s = rep_hist_format_exit_stats(now + 86400);
@@ -1134,7 +1156,7 @@ test_stats(void)
test_assert(!s);
/* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no streams or bytes at all. */
+ * get when observing no streams or bytes at all. */
rep_hist_exit_stats_init(now);
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
@@ -1144,6 +1166,41 @@ test_stats(void)
"exit-kibibytes-written other=0\n"
"exit-kibibytes-read other=0\n"
"exit-streams-opened other=0\n", s);
+ tor_free(s);
+
+ /* Continue with testing connection statistics; we shouldn't collect
+ * conn stats without initializing them. */
+ rep_hist_note_or_conn_bytes(1, 20, 400, now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note bytes, and generate history string. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n", s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_conn_stats_term();
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no bytes at all. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ rep_hist_reset_conn_stats(now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", s);
done:
tor_free(s);
@@ -1203,6 +1260,7 @@ extern struct testcase_t crypto_tests[];
extern struct testcase_t container_tests[];
extern struct testcase_t util_tests[];
extern struct testcase_t dir_tests[];
+extern struct testcase_t microdesc_tests[];
static struct testgroup_t testgroups[] = {
{ "", test_array },
@@ -1211,6 +1269,7 @@ static struct testgroup_t testgroups[] = {
{ "container/", container_tests },
{ "util/", util_tests },
{ "dir/", dir_tests },
+ { "dir/md/", microdesc_tests },
END_OF_GROUPS
};
@@ -1259,7 +1318,10 @@ main(int c, const char **v)
}
options->command = CMD_RUN_UNITTESTS;
- crypto_global_init(0, NULL, NULL);
+ if (crypto_global_init(0, NULL, NULL)) {
+ printf("Can't initialize crypto subsystem; exiting.\n");
+ return 1;
+ }
rep_hist_init();
network_init();
setup_directory();
diff --git a/src/test/test.h b/src/test/test.h
index f7ae46ce6..a053a7ac4 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -45,7 +45,8 @@
_print = tor_malloc(printlen); \
base16_encode(_print, printlen, _value, \
(len)); }, \
- { tor_free(_print); } \
+ { tor_free(_print); }, \
+ TT_EXIT_TEST_FUNCTION \
);
#define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len)
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 6db4ee248..ec0c50897 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -74,7 +74,9 @@ test_addr_basic(void)
cp += 2; \
if (i != 15) *cp++ = ':'; \
} \
- }, { tor_free(_print); } \
+ }, \
+ { tor_free(_print); }, \
+ TT_EXIT_TEST_FUNCTION \
); \
STMT_END
@@ -436,13 +438,16 @@ test_addr_ip6_helpers(void)
/* test tor_addr_parse_mask_ports */
test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6,
0, 0, 0, 0x0000000f, 17, 47, 95);
+ test_streq(p1, "::f");
//test_addr_parse("[::fefe:4.1.1.7/120]:999-1000");
//test_addr_parse_check("::fefe:401:107", 120, 999, 1000);
test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6,
0, 0, 0x0000ffff, 0x04010107, 120, 443, 443);
+ test_streq(p1, "::ffff:4.1.1.7");
test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6,
0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000);
+ test_streq(p1, "abcd:2::44a:0");
r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL);
test_assert(r == -1);
r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL);
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 781081a4a..dca0d3a28 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -69,7 +69,7 @@ test_crypto_rng(void)
uint64_t big;
char *host;
j = crypto_rand_int(100);
- if (i < 0 || i >= 100)
+ if (j < 0 || j >= 100)
allok = 0;
big = crypto_rand_uint64(U64_LITERAL(1)<<40);
if (big >= (U64_LITERAL(1)<<40))
@@ -240,11 +240,13 @@ test_crypto_sha(void)
/* Test SHA-1 with a test vector from the specification. */
i = crypto_digest(data, "abc", 3);
test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D");
+ tt_int_op(i, ==, 0);
/* Test SHA-256 with a test vector from the specification. */
i = crypto_digest256(data, "abc", 3, DIGEST_SHA256);
test_memeq_hex(data, "BA7816BF8F01CFEA414140DE5DAE2223B00361A3"
"96177A9CB410FF61F20015AD");
+ tt_int_op(i, ==, 0);
/* Test HMAC-SHA-1 with test cases from RFC2202. */
@@ -341,7 +343,9 @@ test_crypto_pk(void)
test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
test_eq(128, crypto_pk_keysize(pk1));
+ test_eq(1024, crypto_pk_num_bits(pk1));
test_eq(128, crypto_pk_keysize(pk2));
+ test_eq(1024, crypto_pk_num_bits(pk2));
test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1),
"Hello whirled.", 15,
@@ -626,7 +630,7 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 4095);
- tor_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
+ tt_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
* greater than 0, but its truth is not
* obvious to all analysis tools. */
cipher = crypto_create_init_cipher(key1, 0);
@@ -635,7 +639,7 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 4095);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain, decrypted1, 4095);
/* Encrypt a second time (with a new random initialization vector). */
cipher = crypto_create_init_cipher(key1, 1);
@@ -644,14 +648,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 4095);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095,
encrypted2, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 4095);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain, decrypted2, 4095);
test_memneq(encrypted1, encrypted2, encrypted_size);
/* Decrypt with the wrong key. */
@@ -676,14 +680,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 1);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 1,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 1);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_1, decrypted1, 1);
/* Special length case: 15. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -692,14 +696,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 15);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 15,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 15);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_15, decrypted1, 15);
/* Special length case: 16. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -708,14 +712,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 16);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 16,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 16);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_16, decrypted1, 16);
/* Special length case: 17. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -724,12 +728,12 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 17);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 17,
encrypted1, encrypted_size);
test_eq(decrypted_size, 17);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_17, decrypted1, 17);
done:
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 8fd94289a..04ca29a9f 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -298,7 +298,7 @@ test_dir_versions(void)
#define tt_versionstatus_op(vs1, op, vs2) \
tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \
- (_val1 op _val2),"%d")
+ (_val1 op _val2),"%d",TT_EXIT_TEST_FUNCTION)
#define test_v_i_o(val, ver, lst) \
tt_versionstatus_op(val, ==, tor_version_is_obsolete(ver, lst))
@@ -803,7 +803,7 @@ test_dir_v3_networkstatus(void)
rs->or_port = 443;
rs->dir_port = 8000;
/* all flags but running cleared */
- rs->is_running = 1;
+ rs->is_flagged_running = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -818,7 +818,7 @@ test_dir_v3_networkstatus(void)
rs->addr = 0x99009901;
rs->or_port = 443;
rs->dir_port = 0;
- rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running =
+ rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -835,7 +835,8 @@ test_dir_v3_networkstatus(void)
rs->or_port = 400;
rs->dir_port = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
- rs->is_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
+ rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
+ rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -1075,7 +1076,8 @@ test_dir_v3_networkstatus(void)
test_assert(!rs->is_fast);
test_assert(!rs->is_possible_guard);
test_assert(!rs->is_stable);
- test_assert(rs->is_running); /* If it wasn't running it wouldn't be here */
+ /* (If it wasn't running it wouldn't be here) */
+ test_assert(rs->is_flagged_running);
test_assert(!rs->is_v2_dir);
test_assert(!rs->is_valid);
test_assert(!rs->is_named);
@@ -1097,7 +1099,7 @@ test_dir_v3_networkstatus(void)
test_assert(rs->is_fast);
test_assert(rs->is_possible_guard);
test_assert(rs->is_stable);
- test_assert(rs->is_running);
+ test_assert(rs->is_flagged_running);
test_assert(rs->is_v2_dir);
test_assert(rs->is_valid);
test_assert(!rs->is_named);
@@ -1167,10 +1169,10 @@ test_dir_v3_networkstatus(void)
/* Extract a detached signature from con3. */
detached_text1 = get_detached_sigs(con3, con_md3);
- tor_assert(detached_text1);
+ tt_assert(detached_text1);
/* Try to parse it. */
dsig1 = networkstatus_parse_detached_signatures(detached_text1, NULL);
- tor_assert(dsig1);
+ tt_assert(dsig1);
/* Are parsed values as expected? */
test_eq(dsig1->valid_after, con3->valid_after);
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
new file mode 100644
index 000000000..b807265c8
--- /dev/null
+++ b/src/test/test_microdesc.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "or.h"
+
+#include "config.h"
+#include "microdesc.h"
+
+#include "test.h"
+
+#ifdef MS_WINDOWS
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif
+
+static const char test_md1[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
+ "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
+ "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char test_md2[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
+ "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
+ "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char test_md3[] =
+ "@last-listed 2009-06-22\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
+ "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
+ "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept 1-700,800-1000\n"
+ "family nodeX nodeY nodeZ\n";
+
+static void
+test_md_cache(void *data)
+{
+ or_options_t *options = NULL;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *added = NULL, *wanted = NULL;
+ microdesc_t *md1, *md2, *md3;
+ char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
+ const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
+ time_t time1, time2, time3;
+ char *fn = NULL, *s = NULL;
+ (void)data;
+
+ options = get_options_mutable();
+ tt_assert(options);
+
+ time1 = time(NULL);
+ time2 = time(NULL) - 2*24*60*60;
+ time3 = time(NULL) - 15*24*60*60;
+
+ /* Possibly, turn this into a test setup/cleanup pair */
+ tor_free(options->DataDirectory);
+ options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
+#ifdef MS_WINDOWS
+ tt_int_op(0, ==, mkdir(options->DataDirectory));
+#else
+ tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
+#endif
+
+ tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
+
+ crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
+ crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
+ crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
+ DIGEST_SHA256);
+
+ mc = get_microdesc_cache();
+
+ added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
+ time1, NULL);
+ tt_int_op(1, ==, smartlist_len(added));
+ md1 = smartlist_get(added, 0);
+ smartlist_free(added);
+ added = NULL;
+
+ wanted = smartlist_create();
+ added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
+ time2, wanted);
+ /* Should fail, since we didn't list test_md2's digest in wanted */
+ tt_int_op(0, ==, smartlist_len(added));
+ smartlist_free(added);
+ added = NULL;
+
+ smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
+ smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
+ added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
+ time2, wanted);
+ /* Now it can work. md2 should have been added */
+ tt_int_op(1, ==, smartlist_len(added));
+ md2 = smartlist_get(added, 0);
+ /* And it should have gotten removed from 'wanted' */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
+ smartlist_free(added);
+ added = NULL;
+
+ added = microdescs_add_to_cache(mc, test_md3, NULL,
+ SAVED_NOWHERE, 0, -1, NULL);
+ /* Must fail, since SAVED_NOWHERE precludes annotations */
+ tt_int_op(0, ==, smartlist_len(added));
+ smartlist_free(added);
+ added = NULL;
+
+ added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
+ SAVED_NOWHERE, 0, time3, NULL);
+ /* Now it can work */
+ tt_int_op(1, ==, smartlist_len(added));
+ md3 = smartlist_get(added, 0);
+ smartlist_free(added);
+ added = NULL;
+
+ /* Okay. We added 1...3. Let's poke them to see how they look, and make
+ * sure they're really in the journal. */
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+
+ tt_int_op(md1->last_listed, ==, time1);
+ tt_int_op(md2->last_listed, ==, time2);
+ tt_int_op(md3->last_listed, ==, time3);
+
+ tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL);
+ tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL);
+ tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
+
+ tt_int_op(md1->bodylen, ==, strlen(test_md1));
+ tt_int_op(md2->bodylen, ==, strlen(test_md2));
+ tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
+ test_mem_op(md1->body, ==, test_md1, strlen(test_md1));
+ test_mem_op(md2->body, ==, test_md2, strlen(test_md2));
+ test_mem_op(md3->body, ==, test_md3_noannotation,
+ strlen(test_md3_noannotation));
+
+ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
+ options->DataDirectory);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ tt_assert(s);
+ test_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
+ test_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
+ test_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
+
+ tt_ptr_op(md1->family, ==, NULL);
+ tt_ptr_op(md3->family, !=, NULL);
+ tt_int_op(smartlist_len(md3->family), ==, 3);
+ tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX");
+
+ /* Now rebuild the cache! */
+ tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
+
+ tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
+ tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
+ tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
+
+ /* The journal should be empty now */
+ tor_free(s);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ tt_str_op(s, ==, "");
+ tor_free(s);
+ tor_free(fn);
+
+ /* read the cache. */
+ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
+ options->DataDirectory);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+
+ /* Okay, now we are going to forget about the cache entirely, and reload it
+ * from the disk. */
+ microdesc_free_all();
+ mc = get_microdesc_cache();
+ md1 = microdesc_cache_lookup_by_digest256(mc, d1);
+ md2 = microdesc_cache_lookup_by_digest256(mc, d2);
+ md3 = microdesc_cache_lookup_by_digest256(mc, d3);
+ test_assert(md1);
+ test_assert(md2);
+ test_assert(md3);
+ test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+
+ tt_int_op(md1->last_listed, ==, time1);
+ tt_int_op(md2->last_listed, ==, time2);
+ tt_int_op(md3->last_listed, ==, time3);
+
+ /* Okay, now we are going to clear out everything older than a week old.
+ * In practice, that means md3 */
+ microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+ md3 = NULL; /* it's history now! */
+
+ /* rebuild again, make sure it stays gone. */
+ microdesc_cache_rebuild(mc, 1);
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+
+ done:
+ if (options)
+ tor_free(options->DataDirectory);
+ microdesc_free_all();
+
+ smartlist_free(added);
+ if (wanted)
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+ tor_free(s);
+ tor_free(fn);
+}
+
+struct testcase_t microdesc_tests[] = {
+ { "cache", test_md_cache, TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 23cd059cf..c4769e640 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -6,6 +6,7 @@
#include "orconfig.h"
#define CONTROL_PRIVATE
#define MEMPOOL_PRIVATE
+#define UTIL_PRIVATE
#include "or.h"
#include "config.h"
#include "control.h"
@@ -375,7 +376,7 @@ test_util_strmisc(void)
/* Test memmem and memstr */
{
const char *haystack = "abcde";
- tor_assert(!tor_memmem(haystack, 5, "ef", 2));
+ tt_assert(!tor_memmem(haystack, 5, "ef", 2));
test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
haystack = "ababcad";
@@ -639,26 +640,26 @@ test_util_gzip(void)
tor_strdup("String with low redundancy that won't be compressed much.");
test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
ZLIB_METHOD));
- tor_assert(len1>16);
+ tt_assert(len1>16);
/* when we allow an incomplete string, we should succeed.*/
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
ZLIB_METHOD, 0, LOG_INFO));
buf3[len2]='\0';
- tor_assert(len2 > 5);
- tor_assert(!strcmpstart(buf1, buf3));
+ tt_assert(len2 > 5);
+ tt_assert(!strcmpstart(buf1, buf3));
/* when we demand a complete string, this must fail. */
tor_free(buf3);
- tor_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
+ tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
ZLIB_METHOD, 1, LOG_INFO));
- tor_assert(!buf3);
+ tt_assert(!buf3);
/* Now, try streaming compression. */
tor_free(buf1);
tor_free(buf2);
tor_free(buf3);
state = tor_zlib_new(1, ZLIB_METHOD);
- tor_assert(state);
+ tt_assert(state);
cp1 = buf1 = tor_malloc(1024);
len1 = 1024;
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
@@ -675,7 +676,7 @@ test_util_gzip(void)
test_eq(len2, 0);
test_assert(cp1 > cp2); /* Make sure we really added something. */
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
ZLIB_METHOD, 1, LOG_WARN));
test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
@@ -832,6 +833,18 @@ test_util_sscanf(void)
test_eq(u2, 3u);
test_eq(u3, 99u);
+ /* %x should work. */
+ r = tor_sscanf("1234 02aBcdEf", "%x %x", &u1, &u2);
+ test_eq(r, 2);
+ test_eq(u1, 0x1234);
+ test_eq(u2, 0x2ABCDEF);
+ /* Width works on %x */
+ r = tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3);
+ test_eq(r, 3);
+ test_eq(u1, 0xf00d);
+ test_eq(u2, 0xcafe);
+ test_eq(u3, 444);
+
r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/
test_eq(r, 1);
test_eq(u1, 99);
@@ -1239,6 +1252,204 @@ test_util_load_win_lib(void *ptr)
#endif
static void
+clear_hex_errno(char *hex_errno)
+{
+ memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
+}
+
+static void
+test_util_exit_status(void *ptr)
+{
+ /* Leave an extra byte for a \0 so we can do string comparison */
+ char hex_errno[HEX_ERRNO_SIZE + 1];
+
+ (void)ptr;
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0, 0, hex_errno);
+ tt_str_op(hex_errno, ==, " 0/0\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
+ tt_str_op(hex_errno, ==, " 0/7FFFFFFF\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0xFF, -0x80000000, hex_errno);
+ tt_str_op(hex_errno, ==, "FF/-80000000\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0x7F, 0, hex_errno);
+ tt_str_op(hex_errno, ==, " 7F/0\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0x08, -0x242, hex_errno);
+ tt_str_op(hex_errno, ==, " 8/-242\n");
+
+ done:
+ ;
+}
+
+#ifndef MS_WINDOWS
+/** Check that fgets waits until a full line, and not return a partial line, on
+ * a EAGAIN with a non-blocking pipe */
+static void
+test_util_fgets_eagain(void *ptr)
+{
+ int test_pipe[2] = {-1, -1};
+ int retval;
+ ssize_t retlen;
+ char *retptr;
+ FILE *test_stream = NULL;
+ char buf[10];
+
+ (void)ptr;
+
+ /* Set up a pipe to test on */
+ retval = pipe(test_pipe);
+ tt_int_op(retval, >=, 0);
+
+ /* Set up the read-end to be non-blocking */
+ retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
+ tt_int_op(retval, >=, 0);
+
+ /* Open it as a stdio stream */
+ test_stream = fdopen(test_pipe[0], "r");
+ tt_ptr_op(test_stream, !=, NULL);
+
+ /* Send in a partial line */
+ retlen = write(test_pipe[1], "A", 1);
+ tt_int_op(retlen, ==, 1);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_want(retptr == NULL);
+ tt_int_op(errno, ==, EAGAIN);
+
+ /* Send in the rest */
+ retlen = write(test_pipe[1], "B\n", 2);
+ tt_int_op(retlen, ==, 2);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "AB\n");
+
+ /* Send in a full line */
+ retlen = write(test_pipe[1], "CD\n", 3);
+ tt_int_op(retlen, ==, 3);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "CD\n");
+
+ /* Send in a partial line */
+ retlen = write(test_pipe[1], "E", 1);
+ tt_int_op(retlen, ==, 1);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, NULL);
+ tt_int_op(errno, ==, EAGAIN);
+
+ /* Send in the rest */
+ retlen = write(test_pipe[1], "F\n", 2);
+ tt_int_op(retlen, ==, 2);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "EF\n");
+
+ /* Send in a full line and close */
+ retlen = write(test_pipe[1], "GH", 2);
+ tt_int_op(retlen, ==, 2);
+ retval = close(test_pipe[1]);
+ test_pipe[1] = -1;
+ tt_int_op(retval, ==, 0);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "GH");
+
+ /* Check for EOF */
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, NULL);
+ tt_int_op(feof(test_stream), >, 0);
+
+ done:
+ if (test_stream != NULL)
+ fclose(test_stream);
+ if (test_pipe[0] != -1)
+ close(test_pipe[0]);
+ if (test_pipe[1] != -1)
+ close(test_pipe[1]);
+}
+#endif
+
+#ifndef MS_WINDOWS
+/** Helper function for testing tor_spawn_background */
+static void
+run_util_spawn_background(const char *argv[], const char *expected_out,
+ const char *expected_err, int expected_exit)
+{
+ int stdout_pipe=-1, stderr_pipe=-1;
+ int retval, stat_loc;
+ pid_t pid;
+ ssize_t pos;
+ char stdout_buf[100], stderr_buf[100];
+
+ /* Start the program */
+ retval = tor_spawn_background(argv[0], &stdout_pipe, &stderr_pipe, argv);
+ tt_int_op(retval, >, 0);
+ tt_int_op(stdout_pipe, >, 0);
+ tt_int_op(stderr_pipe, >, 0);
+ pid = retval;
+
+ /* Check stdout */
+ pos = read_all(stdout_pipe, stdout_buf, sizeof(stdout_buf) - 1, 0);
+ tt_assert(pos >= 0);
+ stdout_buf[pos] = '\0';
+ tt_int_op(pos, ==, strlen(expected_out));
+ tt_str_op(stdout_buf, ==, expected_out);
+
+ /* Check it terminated correctly */
+ retval = waitpid(pid, &stat_loc, 0);
+ tt_int_op(retval, ==, pid);
+ tt_assert(WIFEXITED(stat_loc));
+ tt_int_op(WEXITSTATUS(stat_loc), ==, expected_exit);
+ tt_assert(!WIFSIGNALED(stat_loc));
+ tt_assert(!WIFSTOPPED(stat_loc));
+
+ /* Check stderr */
+ pos = read_all(stderr_pipe, stderr_buf, sizeof(stderr_buf) - 1, 0);
+ tt_assert(pos >= 0);
+ stderr_buf[pos] = '\0';
+ tt_int_op(pos, ==, strlen(expected_err));
+ tt_str_op(stderr_buf, ==, expected_err);
+
+ done:
+ ;
+}
+
+/** Check that we can launch a process and read the output */
+static void
+test_util_spawn_background_ok(void *ptr)
+{
+ const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
+ const char *expected_out = "OUT\n--test\nDONE\n";
+ const char *expected_err = "ERR\n";
+
+ (void)ptr;
+
+ run_util_spawn_background(argv, expected_out, expected_err, 0);
+}
+
+/** Check that failing to find the executable works as expected */
+static void
+test_util_spawn_background_fail(void *ptr)
+{
+ const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
+ const char *expected_out = "ERR: Failed to spawn background process "
+ "- code 9/2\n";
+ const char *expected_err = "";
+
+ (void)ptr;
+
+ run_util_spawn_background(argv, expected_out, expected_err, 255);
+}
+#endif
+
+static void
test_util_di_ops(void)
{
#define LT -1
@@ -1319,6 +1530,12 @@ struct testcase_t util_tests[] = {
#ifdef MS_WINDOWS
UTIL_TEST(load_win_lib, 0),
#endif
+ UTIL_TEST(exit_status, 0),
+#ifndef MS_WINDOWS
+ UTIL_TEST(fgets_eagain, TT_SKIP),
+ UTIL_TEST(spawn_background_ok, 0),
+ UTIL_TEST(spawn_background_fail, 0),
+#endif
END_OF_TESTCASES
};
diff --git a/src/test/tinytest.c b/src/test/tinytest.c
index 11ffc2fe5..8caa4f545 100644
--- a/src/test/tinytest.c
+++ b/src/test/tinytest.c
@@ -28,7 +28,11 @@
#include <string.h>
#include <assert.h>
-#ifdef WIN32
+#ifdef TINYTEST_LOCAL
+#include "tinytest_local.h"
+#endif
+
+#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
@@ -40,9 +44,6 @@
#define __attribute__(x)
#endif
-#ifdef TINYTEST_LOCAL
-#include "tinytest_local.h"
-#endif
#include "tinytest.h"
#include "tinytest_macros.h"
@@ -64,7 +65,7 @@ const char *cur_test_prefix = NULL; /**< prefix of the current test group */
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL;
-#ifdef WIN32
+#ifdef _WIN32
/** Pointer to argv[0] for win32. */
static const char *commandname = NULL;
#endif
@@ -103,7 +104,7 @@ static enum outcome
_testcase_run_forked(const struct testgroup_t *group,
const struct testcase_t *testcase)
{
-#ifdef WIN32
+#ifdef _WIN32
/* Fork? On Win32? How primitive! We'll do what the smart kids do:
we'll invoke our own exe (whose name we recall from the command
line) with a command line that tells it to run just the test we
@@ -174,6 +175,7 @@ _testcase_run_forked(const struct testgroup_t *group,
exit(1);
}
exit(0);
+ return FAIL; /* unreachable */
} else {
/* parent */
int status, r;
@@ -239,6 +241,7 @@ testcase_run_one(const struct testgroup_t *group,
if (opt_forked) {
exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
+ return 1; /* unreachable */
} else {
return (int)outcome;
}
@@ -287,7 +290,7 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
{
int i, j, n=0;
-#ifdef WIN32
+#ifdef _WIN32
commandname = v[0];
#endif
for (i=1; i<c; ++i) {
diff --git a/src/test/tinytest_demo.c b/src/test/tinytest_demo.c
index bd33cc37f..98cb773d1 100644
--- a/src/test/tinytest_demo.c
+++ b/src/test/tinytest_demo.c
@@ -1,4 +1,4 @@
-/* tinytest_demo.c -- Copyright 2009 Nick Mathewson
+/* tinytest_demo.c -- Copyright 2009-2010 Nick Mathewson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,7 +39,7 @@
/* ============================================================ */
/* First, let's see if strcmp is working. (All your test cases should be
- * functions declared to take a single void * as) an argument. */
+ * functions declared to take a single void * as an argument.) */
void
test_strcmp(void *data)
{
@@ -53,7 +53,7 @@ test_strcmp(void *data)
}
/* Pretty often, calling tt_abort_msg to indicate failure is more
- heavy-weight than you want. Instead, just say: */
+ heavy-weight than you want. Instead, just say: */
tt_assert(strcmp("testcase", "testcase") == 0);
/* Occasionally, you don't want to stop the current testcase just
@@ -91,7 +91,7 @@ test_strcmp(void *data)
/* First you declare a type to hold the environment info, and functions to
set it up and tear it down. */
struct data_buffer {
- /* We're just going to have couple of character buffer. Using
+ /* We're just going to have couple of character buffer. Using
setup/teardown functions is probably overkill for this case.
You could also do file descriptors, complicated handles, temporary
@@ -164,7 +164,7 @@ test_memcpy(void *ptr)
/* ============================================================ */
-/* Now we need to make sure that our tests get invoked. First, you take
+/* Now we need to make sure that our tests get invoked. First, you take
a bunch of related tests and put them into an array of struct testcase_t.
*/
@@ -189,15 +189,15 @@ struct testgroup_t groups[] = {
/* Every group has a 'prefix', and an array of tests. That's it. */
{ "demo/", demo_tests },
- END_OF_GROUPS
+ END_OF_GROUPS
};
int
main(int c, const char **v)
{
- /* Finally, just call tinytest_main(). It lets you specify verbose
- or quiet output with --verbose and --quiet. You can list
+ /* Finally, just call tinytest_main(). It lets you specify verbose
+ or quiet output with --verbose and --quiet. You can list
specific tests:
tinytest-demo demo/memcpy
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index a7fa64a82..032393ccf 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -90,10 +90,10 @@
TT_STMT_BEGIN \
if (!(b)) { \
_tinytest_set_test_failed(); \
- TT_GRIPE((msg)); \
+ TT_GRIPE(("%s",msg)); \
fail; \
} else { \
- TT_BLATHER((msg)); \
+ TT_BLATHER(("%s",msg)); \
} \
TT_STMT_END
@@ -111,7 +111,7 @@
#define tt_assert(b) tt_assert_msg((b), "assert("#b")")
#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
- setup_block,cleanup_block) \
+ setup_block,cleanup_block,die_on_fail) \
TT_STMT_BEGIN \
type _val1 = (type)(a); \
type _val2 = (type)(b); \
@@ -135,33 +135,50 @@
cleanup_block; \
if (!_tt_status) { \
_tinytest_set_test_failed(); \
- TT_EXIT_TEST_FUNCTION; \
+ die_on_fail ; \
} \
} \
TT_STMT_END
-#define tt_assert_test_type(a,b,str_test,type,test,fmt) \
+#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \
tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \
- {_print=_value;},{})
+ {_print=_value;},{},die_on_fail)
/* Helper: assert that a op b, when cast to type. Format the values with
* printf format fmt on failure. */
#define tt_assert_op_type(a,op,b,type,fmt) \
- tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt)
+ tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt, \
+ TT_EXIT_TEST_FUNCTION)
#define tt_int_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld")
+ tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2), \
+ "%ld",TT_EXIT_TEST_FUNCTION)
#define tt_uint_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
- (_val1 op _val2),"%lu")
+ (_val1 op _val2),"%lu",TT_EXIT_TEST_FUNCTION)
#define tt_ptr_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
- (_val1 op _val2),"%p")
+ (_val1 op _val2),"%p",TT_EXIT_TEST_FUNCTION)
#define tt_str_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
- (strcmp(_val1,_val2) op 0),"<%s>")
+ (strcmp(_val1,_val2) op 0),"<%s>",TT_EXIT_TEST_FUNCTION)
+
+#define tt_want_int_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld",(void)0)
+
+#define tt_want_uint_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
+ (_val1 op _val2),"%lu",(void)0)
+
+#define tt_want_ptr_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
+ (_val1 op _val2),"%p",(void)0)
+
+#define tt_want_str_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
+ (strcmp(_val1,_val2) op 0),"<%s>",(void)0)
#endif
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 1bb507684..a9a619757 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -2,17 +2,19 @@ bin_PROGRAMS = tor-resolve tor-gencert
noinst_PROGRAMS = tor-checkkey
tor_resolve_SOURCES = tor-resolve.c
-tor_resolve_LDFLAGS = @TOR_LDFLAGS_libevent@
-tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIBEVENT_LIBS@ @TOR_LIB_WS32@
+tor_resolve_LDFLAGS =
+tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIB_WS32@
tor_gencert_SOURCES = tor-gencert.c
-tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
+tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
tor_gencert_LDADD = ../common/libor.a ../common/libor-crypto.a \
- -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ -lm @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
tor_checkkey_SOURCES = tor-checkkey.c
-tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
+tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
tor_checkkey_LDADD = ../common/libor.a ../common/libor-crypto.a \
- -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ -lm @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+SUBDIRS = tor-fw-helper
+DIST_SUBDIRS = tor-fw-helper
+
diff --git a/src/tools/tor-fw-helper/Makefile.am b/src/tools/tor-fw-helper/Makefile.am
new file mode 100644
index 000000000..75878f259
--- /dev/null
+++ b/src/tools/tor-fw-helper/Makefile.am
@@ -0,0 +1,38 @@
+if USE_FW_HELPER
+bin_PROGRAMS = tor-fw-helper
+else
+bin_PROGRAMS =
+endif
+
+tor_fw_helper_SOURCES = \
+ tor-fw-helper.c \
+ tor-fw-helper-natpmp.c \
+ tor-fw-helper-upnp.c
+noinst_HEADERS = \
+ tor-fw-helper.h \
+ tor-fw-helper-natpmp.h \
+ tor-fw-helper-upnp.h
+
+if NAT_PMP
+nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@
+nat_pmp_ldadd = -lnatpmp
+nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@
+else
+nat_pmp_ldflags =
+nat_pmp_ldadd =
+nat_pmp_cppflags =
+endif
+
+if MINIUPNPC
+miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@
+miniupnpc_ldadd = -lminiupnpc -lm
+miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@
+else
+miniupnpc_ldflags =
+miniupnpc_ldadd =
+miniupnpc_cppflags =
+endif
+
+tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags)
+tor_fw_helper_LDADD = $(nat_pmp_ldadd) $(miniupnpc_ldadd) ../../common/libor.a @TOR_LIB_WS32@
+tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags)
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
new file mode 100644
index 000000000..f9d5d0d58
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-natpmp.c
+ * \brief The implementation of our NAT-PMP firewall helper.
+ **/
+
+#include "orconfig.h"
+#ifdef NAT_PMP
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+// debugging stuff
+#include <assert.h>
+
+#include "tor-fw-helper.h"
+#include "tor-fw-helper-natpmp.h"
+
+/** This hooks NAT-PMP into our multi-backend API. */
+static tor_fw_backend_t tor_natpmp_backend = {
+ "natpmp",
+ sizeof(struct natpmp_state_t),
+ tor_natpmp_init,
+ tor_natpmp_cleanup,
+ tor_natpmp_fetch_public_ip,
+ tor_natpmp_add_tcp_mapping
+};
+
+/** Return the backend for NAT-PMP. */
+const tor_fw_backend_t *
+tor_fw_get_natpmp_backend(void)
+{
+ return &tor_natpmp_backend;
+}
+
+/** Initialize the NAT-PMP backend and store the results in
+ * <b>backend_state</b>.*/
+int
+tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+
+ memset(&(state->natpmp), 0, sizeof(natpmp_t));
+ memset(&(state->response), 0, sizeof(natpmpresp_t));
+ state->init = 0;
+ state->protocol = NATPMP_PROTOCOL_TCP;
+ state->lease = NATPMP_DEFAULT_LEASE;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: natpmp init...\n");
+
+ r = initnatpmp(&(state->natpmp), 0, 0);
+ if (r == 0) {
+ state->init = 1;
+ fprintf(stdout, "tor-fw-helper: natpmp initialized...\n");
+ return r;
+ } else {
+ fprintf(stderr, "tor-fw-helper: natpmp failed to initialize...\n");
+ return r;
+ }
+}
+
+/** Tear down the NAT-PMP connection stored in <b>backend_state</b>.*/
+int
+tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: natpmp cleanup...\n");
+ r = closenatpmp(&(state->natpmp));
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: closing natpmp socket: %d\n", r);
+ return r;
+}
+
+/** Use select() to wait until we can read on fd. */
+static int
+wait_until_fd_readable(int fd, struct timeval *timeout)
+{
+ int r;
+ fd_set fds;
+ if (fd >= FD_SETSIZE) {
+ fprintf(stderr, "E: NAT-PMP FD_SETSIZE error %d\n", fd);
+ return -1;
+ }
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ r = select(fd+1, &fds, NULL, NULL, timeout);
+ if (r == -1) {
+ fprintf(stdout, "V: select failed in wait_until_fd_readable: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ /* XXXX we should really check to see whether fd was readable, or we timed
+ out. */
+ return 0;
+}
+
+/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
+ * using the <b>natpmp_t</b> stored in <b>backend_state</b>. */
+int
+tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options,
+ void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+ int x = 0;
+ int sav_errno;
+
+ struct timeval timeout;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: sending natpmp portmapping request...\n");
+ r = sendnewportmappingrequest(&(state->natpmp), state->protocol,
+ tor_fw_options->internal_port,
+ tor_fw_options->external_port,
+ state->lease);
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "tor-fw-helper: NAT-PMP sendnewportmappingrequest "
+ "returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED");
+
+ do {
+ getnatpmprequesttimeout(&(state->natpmp), &timeout);
+ x = wait_until_fd_readable(state->natpmp.s, &timeout);
+ if (x == -1)
+ return -1;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: attempting to readnatpmpreponseorretry...\n");
+ r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
+ sav_errno = errno;
+
+ if (r<0 && r!=NATPMP_TRYAGAIN) {
+ fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r);
+ fprintf(stderr, "E: errno=%d '%s'\n", sav_errno,
+ strerror(sav_errno));
+ }
+
+ } while (r == NATPMP_TRYAGAIN);
+
+ if (r != 0) {
+ /* XXX TODO: NATPMP_* should be formatted into useful error strings */
+ fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
+ " %d\n", r);
+ if (r == -51)
+ fprintf(stderr, "E: NAT-PMP It appears that the request was "
+ "unauthorized\n");
+ return r;
+ }
+
+ if (r == NATPMP_SUCCESS) {
+ fprintf(stdout, "tor-fw-helper: NAT-PMP mapped public port %hu to"
+ " localport %hu liftime %u\n",
+ (state->response).pnu.newportmapping.mappedpublicport,
+ (state->response).pnu.newportmapping.privateport,
+ (state->response).pnu.newportmapping.lifetime);
+ }
+
+ tor_fw_options->nat_pmp_status = 1;
+
+ return r;
+}
+
+/** Fetch our likely public IP from our upstream NAT-PMP enabled NAT device.
+ * Use the connection context stored in <b>backend_state</b>. */
+int
+tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ void *backend_state)
+{
+ int r = 0;
+ int x = 0;
+ int sav_errno;
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+
+ struct timeval timeout;
+
+ r = sendpublicaddressrequest(&(state->natpmp));
+ fprintf(stdout, "tor-fw-helper: NAT-PMP sendpublicaddressrequest returned"
+ " %d (%s)\n", r, r==2?"SUCCESS":"FAILED");
+
+ do {
+ getnatpmprequesttimeout(&(state->natpmp), &timeout);
+
+ x = wait_until_fd_readable(state->natpmp.s, &timeout);
+ if (x == -1)
+ return -1;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: NAT-PMP attempting to read reponse...\n");
+ r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
+ sav_errno = errno;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: NAT-PMP readnatpmpresponseorretry returned"
+ " %d\n", r);
+
+ if ( r < 0 && r != NATPMP_TRYAGAIN) {
+ fprintf(stderr, "E: NAT-PMP readnatpmpresponseorretry failed %d\n",
+ r);
+ fprintf(stderr, "E: NAT-PMP errno=%d '%s'\n", sav_errno,
+ strerror(sav_errno));
+ }
+
+ } while (r == NATPMP_TRYAGAIN );
+
+ if (r != 0) {
+ fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
+ " %d\n", r);
+ return r;
+ }
+
+ fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n",
+ inet_ntoa((state->response).pnu.publicaddress.addr));
+ tor_fw_options->public_ip_status = 1;
+
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: result = %u\n", r);
+ fprintf(stdout, "V: type = %u\n", (state->response).type);
+ fprintf(stdout, "V: resultcode = %u\n", (state->response).resultcode);
+ fprintf(stdout, "V: epoch = %u\n", (state->response).epoch);
+ }
+
+ return r;
+}
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h
new file mode 100644
index 000000000..0190379a2
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-natpmp.h
+ **/
+
+#ifdef NAT_PMP
+#ifndef _TOR_FW_HELPER_NATPMP_H
+#define _TOR_FW_HELPER_NATPMP_H
+
+#include <natpmp.h>
+
+/** This is the default NAT-PMP lease time in seconds. */
+#define NATPMP_DEFAULT_LEASE 3600
+/** NAT-PMP has many codes for success; this is one of them. */
+#define NATPMP_SUCCESS 0
+
+/** This is our NAT-PMP meta structure - it holds our request data, responses,
+ * various NAT-PMP parameters, and of course the status of the motion in the
+ * NAT-PMP ocean. */
+typedef struct natpmp_state_t {
+ natpmp_t natpmp;
+ natpmpresp_t response;
+ int fetch_public_ip;
+ int status;
+ int init; /**< Have we been initialized? */
+ int protocol; /**< This will only be TCP. */
+ int lease;
+} natpmp_state_t;
+
+const tor_fw_backend_t *tor_fw_get_natpmp_backend(void);
+
+int tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state);
+
+int tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state);
+
+int tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options,
+ void *backend_state);
+
+int tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ void *backend_state);
+
+#endif
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c
new file mode 100644
index 000000000..18ca56394
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c
@@ -0,0 +1,186 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-upnp.c
+ * \brief The implementation of our UPnP firewall helper.
+ **/
+
+#include "orconfig.h"
+#ifdef MINIUPNPC
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <assert.h>
+
+#include "compat.h"
+#include "tor-fw-helper.h"
+#include "tor-fw-helper-upnp.h"
+
+/** UPnP timeout value. */
+#define UPNP_DISCOVER_TIMEOUT 2000
+/** Description of the port mapping in the UPnP table. */
+#define UPNP_DESC "Tor relay"
+
+/* XXX TODO: We should print these as a useful user string when we return the
+ * number to a user */
+/** Magic numbers as miniupnpc return codes. */
+#define UPNP_ERR_SUCCESS 0
+#define UPNP_ERR_NODEVICESFOUND 1
+#define UPNP_ERR_NOIGDFOUND 2
+#define UPNP_ERR_ADDPORTMAPPING 3
+#define UPNP_ERR_GETPORTMAPPING 4
+#define UPNP_ERR_DELPORTMAPPING 5
+#define UPNP_ERR_GETEXTERNALIP 6
+#define UPNP_ERR_INVAL 7
+#define UPNP_ERR_OTHER 8
+#define UPNP_SUCCESS 1
+
+/** This hooks miniupnpc into our multi-backend API. */
+static tor_fw_backend_t tor_miniupnp_backend = {
+ "miniupnp",
+ sizeof(struct miniupnpc_state_t),
+ tor_upnp_init,
+ tor_upnp_cleanup,
+ tor_upnp_fetch_public_ip,
+ tor_upnp_add_tcp_mapping
+};
+
+/** Return the backend for miniupnp. */
+const tor_fw_backend_t *
+tor_fw_get_miniupnp_backend(void)
+{
+ return &tor_miniupnp_backend;
+}
+
+/** Initialize the UPnP backend and store the results in
+ * <b>backend_state</b>.*/
+int
+tor_upnp_init(tor_fw_options_t *options, void *backend_state)
+{
+ /*
+ This leaks the user agent from the client to the router - perhaps we don't
+ want to do that? eg:
+
+ User-Agent: Ubuntu/10.04, UPnP/1.0, MiniUPnPc/1.4
+
+ */
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ struct UPNPDev *devlist;
+ int r;
+
+ memset(&(state->urls), 0, sizeof(struct UPNPUrls));
+ memset(&(state->data), 0, sizeof(struct IGDdatas));
+ state->init = 0;
+
+ devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0);
+ if (NULL == devlist) {
+ fprintf(stderr, "E: upnpDiscover returned: NULL\n");
+ return UPNP_ERR_NODEVICESFOUND;
+ }
+
+ assert(options);
+ r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data),
+ state->lanaddr, UPNP_LANADDR_SZ);
+ fprintf(stdout, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r,
+ r==UPNP_SUCCESS?"SUCCESS":"FAILED");
+
+ freeUPNPDevlist(devlist);
+
+ if (r != 1 && r != 2)
+ return UPNP_ERR_NOIGDFOUND;
+
+ state->init = 1;
+ return UPNP_ERR_SUCCESS;
+}
+
+/** Tear down the UPnP connection stored in <b>backend_state</b>.*/
+int
+tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state)
+{
+
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ assert(options);
+
+ if (state->init)
+ FreeUPNPUrls(&(state->urls));
+ state->init = 0;
+
+ return UPNP_ERR_SUCCESS;
+}
+
+/** Fetch our likely public IP from our upstream UPnP IGD enabled NAT device.
+ * Use the connection context stored in <b>backend_state</b>. */
+int
+tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state)
+{
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ int r;
+ char externalIPAddress[16];
+
+ if (!state->init) {
+ r = tor_upnp_init(options, state);
+ if (r != UPNP_ERR_SUCCESS)
+ return r;
+ }
+
+ r = UPNP_GetExternalIPAddress(state->urls.controlURL,
+ state->data.first.servicetype,
+ externalIPAddress);
+
+ if (r != UPNPCOMMAND_SUCCESS)
+ goto err;
+
+ if (externalIPAddress[0]) {
+ fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n",
+ externalIPAddress); tor_upnp_cleanup(options, state);
+ options->public_ip_status = 1;
+ return UPNP_ERR_SUCCESS;
+ } else {
+ goto err;
+ }
+
+ err:
+ tor_upnp_cleanup(options, state);
+ return UPNP_ERR_GETEXTERNALIP;
+}
+
+/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
+ * and store the results in <b>backend_state</b>. */
+int
+tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state)
+{
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ int r;
+ char internal_port_str[6];
+ char external_port_str[6];
+
+ if (!state->init) {
+ r = tor_upnp_init(options, state);
+ if (r != UPNP_ERR_SUCCESS)
+ return r;
+ }
+
+ if (options->verbose)
+ fprintf(stdout, "V: internal port: %d, external port: %d\n",
+ (int)options->internal_port, (int)options->external_port);
+
+ tor_snprintf(internal_port_str, sizeof(internal_port_str),
+ "%d", (int)options->internal_port);
+ tor_snprintf(external_port_str, sizeof(external_port_str),
+ "%d", (int)options->external_port);
+
+ r = UPNP_AddPortMapping(state->urls.controlURL,
+ state->data.first.servicetype,
+ external_port_str, internal_port_str,
+ state->lanaddr, UPNP_DESC, "TCP", 0);
+ if (r != UPNPCOMMAND_SUCCESS)
+ return UPNP_ERR_ADDPORTMAPPING;
+
+ options->upnp_status = 1;
+ return UPNP_ERR_SUCCESS;
+}
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h
new file mode 100644
index 000000000..021a8e0aa
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-upnp.h
+ * \brief The main header for our firewall helper.
+ **/
+
+#ifdef MINIUPNPC
+#ifndef _TOR_FW_HELPER_UPNP_H
+#define _TOR_FW_HELPER_UPNP_H
+
+#include <miniupnpc/miniwget.h>
+#include <miniupnpc/miniupnpc.h>
+#include <miniupnpc/upnpcommands.h>
+#include <miniupnpc/upnperrors.h>
+
+/** This is a magic number for miniupnpc lan address size. */
+#define UPNP_LANADDR_SZ 64
+
+/** This is our miniupnpc meta structure - it holds our request data,
+ * responses, and various miniupnpc parameters. */
+typedef struct miniupnpc_state_t {
+ struct UPNPUrls urls;
+ struct IGDdatas data;
+ char lanaddr[UPNP_LANADDR_SZ];
+ int init;
+} miniupnpc_state_t;
+
+const tor_fw_backend_t *tor_fw_get_miniupnp_backend(void);
+
+int tor_upnp_init(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state);
+
+#endif
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.c b/src/tools/tor-fw-helper/tor-fw-helper.c
new file mode 100644
index 000000000..20d60d7ba
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper.c
@@ -0,0 +1,363 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper.c
+ * \brief The main wrapper around our firewall helper logic.
+ **/
+
+/*
+ * tor-fw-helper is a tool for opening firewalls with NAT-PMP and UPnP; this
+ * tool is designed to be called by hand or by Tor by way of a exec() at a
+ * later date.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+#include <string.h>
+
+#include "orconfig.h"
+#include "tor-fw-helper.h"
+#ifdef NAT_PMP
+#include "tor-fw-helper-natpmp.h"
+#endif
+#ifdef MINIUPNPC
+#include "tor-fw-helper-upnp.h"
+#endif
+
+/** This is our meta storage type - it holds information about each helper
+ including the total number of helper backends, function pointers, and helper
+ state. */
+typedef struct backends_t {
+ /** The total number of backends */
+ int n_backends;
+ /** The backend functions as an array */
+ tor_fw_backend_t backend_ops[MAX_BACKENDS];
+ /** The internal backend state */
+ void *backend_state[MAX_BACKENDS];
+} backends_t;
+
+/** Initalize each backend helper with the user input stored in <b>options</b>
+ * and put the results in the <b>backends</b> struct. */
+static int
+init_backends(tor_fw_options_t *options, backends_t *backends)
+{
+ int n_available = 0;
+ int i, r, n;
+ tor_fw_backend_t *backend_ops_list[MAX_BACKENDS];
+ void *data = NULL;
+ /* First, build a list of the working backends. */
+ n = 0;
+#ifdef MINIUPNPC
+ backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_miniupnp_backend();
+#endif
+#ifdef NAT_PMP
+ backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_natpmp_backend();
+#endif
+ n_available = n;
+
+ /* Now, for each backend that might work, try to initialize it.
+ * That's how we roll, initialized.
+ */
+ n = 0;
+ for (i=0; i<n_available; ++i) {
+ data = calloc(1, backend_ops_list[i]->state_len);
+ if (!data) {
+ perror("calloc");
+ exit(1);
+ }
+ r = backend_ops_list[i]->init(options, data);
+ if (r == 0) {
+ backends->backend_ops[n] = *backend_ops_list[i];
+ backends->backend_state[n] = data;
+ n++;
+ } else {
+ free(data);
+ }
+ }
+ backends->n_backends = n;
+
+ return n;
+}
+
+/** Return the proper commandline switches when the user needs information. */
+static void
+usage(void)
+{
+ fprintf(stderr, "tor-fw-helper usage:\n"
+ " [-h|--help]\n"
+ " [-T|--Test]\n"
+ " [-v|--verbose]\n"
+ " [-g|--fetch-public-ip]\n"
+ " -i|--internal-or-port [TCP port]\n"
+ " [-e|--external-or-port [TCP port]]\n"
+ " [-d|--internal-dir-port [TCP port]\n"
+ " [-p|--external-dir-port [TCP port]]]\n");
+}
+
+/** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the
+ * current working directory. */
+static int
+log_commandline_options(int argc, char **argv)
+{
+ int i, retval;
+ FILE *logfile;
+ time_t now;
+
+ /* Open the log file */
+ logfile = fopen("tor-fw-helper.log", "a");
+ if (NULL == logfile)
+ return -1;
+
+ /* Send all commandline arguments to the file */
+ now = time(NULL);
+ retval = fprintf(logfile, "START: %s\n", ctime(&now));
+ for (i = 0; i < argc; i++) {
+ retval = fprintf(logfile, "ARG: %d: %s\n", i, argv[i]);
+ if (retval < 0)
+ goto error;
+
+ retval = fprintf(stdout, "ARG: %d: %s\n", i, argv[i]);
+ if (retval < 0)
+ goto error;
+ }
+ now = time(NULL);
+ retval = fprintf(logfile, "END: %s\n", ctime(&now));
+
+ /* Close and clean up */
+ retval = fclose(logfile);
+ return retval;
+
+ /* If there was an error during writing */
+ error:
+ fclose(logfile);
+ return -1;
+}
+
+/** Iterate over over each of the supported <b>backends</b> and attempt to
+ * fetch the public ip. */
+static void
+tor_fw_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_fetch_public_ip\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (char *)(backends->backend_ops)[i].name);
+ }
+ r = backends->backend_ops[i].fetch_public_ip(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_fetch_public_ip backend %s "
+ " returned: %i\n", (char *)(backends->backend_ops)[i].name, r);
+ }
+}
+
+/** Iterate over each of the supported <b>backends</b> and attempt to add a
+ * port forward for the OR port stored in <b>tor_fw_options</b>. */
+static void
+tor_fw_add_or_port(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_add_or_port\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (const char *) backends->backend_ops[i].name);
+ }
+ r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_add_or_port backend %s "
+ "returned: %i\n", (const char *) backends->backend_ops[i].name, r);
+ }
+}
+
+/** Iterate over each of the supported <b>backends</b> and attempt to add a
+ * port forward for the Dir port stored in <b>tor_fw_options</b>. */
+static void
+tor_fw_add_dir_port(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_add_dir_port\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (char *)(backends->backend_ops)[i].name);
+ }
+ r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_add_dir_port backend %s "
+ "returned: %i\n", (const char *)backends->backend_ops[i].name, r);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int r = 0;
+ int c = 0;
+
+ tor_fw_options_t tor_fw_options;
+ backends_t backend_state;
+
+ memset(&tor_fw_options, 0, sizeof(tor_fw_options));
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"verbose", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {"internal-or-port", 1, 0, 'i'},
+ {"external-or-port", 1, 0, 'e'},
+ {"internal-dir-port", 1, 0, 'd'},
+ {"external-dir-port", 1, 0, 'p'},
+ {"fetch-public-ip", 0, 0, 'g'},
+ {"test-commandline", 0, 0, 'T'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "vhi:e:d:p:gT",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'v': tor_fw_options.verbose = 1; break;
+ case 'h': tor_fw_options.help = 1; usage(); exit(1); break;
+ case 'i': sscanf(optarg, "%hu", &tor_fw_options.private_or_port);
+ break;
+ case 'e': sscanf(optarg, "%hu", &tor_fw_options.public_or_port);
+ break;
+ case 'd': sscanf(optarg, "%hu", &tor_fw_options.private_dir_port);
+ break;
+ case 'p': sscanf(optarg, "%hu", &tor_fw_options.public_dir_port);
+ break;
+ case 'g': tor_fw_options.fetch_public_ip = 1; break;
+ case 'T': tor_fw_options.test_commandline = 1; break;
+ case '?': break;
+ default : fprintf(stderr, "Unknown option!\n"); usage(); exit(1);
+ }
+ }
+
+ if (tor_fw_options.verbose) {
+ fprintf(stderr, "V: tor-fw-helper version %s\n"
+ "V: We were called with the following arguments:\n"
+ "V: verbose = %d, help = %d, pub or port = %u, "
+ "priv or port = %u\n"
+ "V: pub dir port = %u, priv dir port = %u\n"
+ "V: fetch_public_ip = %u\n",
+ tor_fw_version, tor_fw_options.verbose, tor_fw_options.help,
+ tor_fw_options.private_or_port, tor_fw_options.public_or_port,
+ tor_fw_options.private_dir_port, tor_fw_options.public_dir_port,
+ tor_fw_options.fetch_public_ip);
+ }
+
+ if (tor_fw_options.test_commandline) {
+ return log_commandline_options(argc, argv);
+ }
+
+ /* At the very least, we require an ORPort;
+ Given a private ORPort, we can ask for a mapping that matches the port
+ externally.
+ */
+ if (!tor_fw_options.private_or_port && !tor_fw_options.fetch_public_ip) {
+ fprintf(stderr, "E: We require an ORPort or fetch_public_ip"
+ " request!\n");
+ usage();
+ exit(1);
+ } else {
+ /* When we only have one ORPort, internal/external are
+ set to be the same.*/
+ if (!tor_fw_options.public_or_port && tor_fw_options.private_or_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We're setting public_or_port = "
+ "private_or_port.\n");
+ tor_fw_options.public_or_port = tor_fw_options.private_or_port;
+ }
+ }
+ if (!tor_fw_options.private_dir_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We have no DirPort; no hole punching for "
+ "DirPorts\n");
+
+ } else {
+ /* When we only have one DirPort, internal/external are
+ set to be the same.*/
+ if (!tor_fw_options.public_dir_port && tor_fw_options.private_dir_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We're setting public_or_port = "
+ "private_or_port.\n");
+
+ tor_fw_options.public_dir_port = tor_fw_options.private_dir_port;
+ }
+ }
+
+ if (tor_fw_options.verbose) {
+ fprintf(stdout, "V: pub or port = %u, priv or port = %u\n"
+ "V: pub dir port = %u, priv dir port = %u\n",
+ tor_fw_options.private_or_port, tor_fw_options.public_or_port,
+ tor_fw_options.private_dir_port,
+ tor_fw_options.public_dir_port);
+ }
+
+ // Initalize the various fw-helper backend helpers
+ r = init_backends(&tor_fw_options, &backend_state);
+ if (r)
+ printf("tor-fw-helper: %i NAT traversal helper(s) loaded\n", r);
+
+ if (tor_fw_options.fetch_public_ip) {
+ tor_fw_fetch_public_ip(&tor_fw_options, &backend_state);
+ }
+
+ if (tor_fw_options.private_or_port) {
+ tor_fw_options.internal_port = tor_fw_options.private_or_port;
+ tor_fw_options.external_port = tor_fw_options.private_or_port;
+ tor_fw_add_or_port(&tor_fw_options, &backend_state);
+ }
+
+ if (tor_fw_options.private_dir_port) {
+ tor_fw_options.internal_port = tor_fw_options.private_dir_port;
+ tor_fw_options.external_port = tor_fw_options.private_dir_port;
+ tor_fw_add_dir_port(&tor_fw_options, &backend_state);
+ }
+
+ r = (((tor_fw_options.nat_pmp_status | tor_fw_options.upnp_status)
+ |tor_fw_options.public_ip_status));
+ if (r > 0) {
+ fprintf(stdout, "tor-fw-helper: SUCCESS\n");
+ } else {
+ fprintf(stderr, "tor-fw-helper: FAILURE\n");
+ }
+
+ exit(r);
+}
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.h b/src/tools/tor-fw-helper/tor-fw-helper.h
new file mode 100644
index 000000000..39d852d21
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper.h
+ * \brief The main header for our firewall helper.
+ **/
+
+#ifndef _TOR_FW_HELPER_H
+#define _TOR_FW_HELPER_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+
+/** The current version of tor-fw-helper. */
+#define tor_fw_version "0.1"
+
+/** This is an arbitrary hard limit - We currently have two (NAT-PMP and UPnP).
+ We're likely going to add the Intel UPnP library but nothing else comes to
+ mind at the moment. */
+#define MAX_BACKENDS 23
+
+/** This is where we store parsed commandline options. */
+typedef struct {
+ int verbose;
+ int help;
+ int test_commandline;
+ uint16_t private_dir_port;
+ uint16_t private_or_port;
+ uint16_t public_dir_port;
+ uint16_t public_or_port;
+ uint16_t internal_port;
+ uint16_t external_port;
+ int fetch_public_ip;
+ int nat_pmp_status;
+ int upnp_status;
+ int public_ip_status;
+} tor_fw_options_t;
+
+/** This is our main structure that defines our backend helper API; each helper
+ * must conform to these public methods if it expects to be handled in a
+ * non-special way. */
+typedef struct tor_fw_backend_t {
+ const char *name;
+ size_t state_len;
+ int (*init)(tor_fw_options_t *options, void *backend_state);
+ int (*cleanup)(tor_fw_options_t *options, void *backend_state);
+ int (*fetch_public_ip)(tor_fw_options_t *options, void *backend_state);
+ int (*add_tcp_mapping)(tor_fw_options_t *options, void *backend_state);
+} tor_fw_backend_t;
+
+#endif
+
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 12349d9d1..8c4d3f648 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -319,7 +319,7 @@ main(int argc, char **argv)
{
uint32_t sockshost;
uint16_t socksport = 0, port_option = 0;
- int isSocks4 = 0, isVerbose = 0, isReverse = 0, force = 0;
+ int isSocks4 = 0, isVerbose = 0, isReverse = 0;
char **arg;
int n_args;
struct in_addr a;
@@ -349,8 +349,6 @@ main(int argc, char **argv)
isSocks4 = 0;
else if (!strcmp("-x", arg[0]))
isReverse = 1;
- else if (!strcmp("-F", arg[0]))
- force = 1;
else if (!strcmp("-p", arg[0])) {
int p;
if (n_args < 2) {
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index b3cd1db50..5483b6d06 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -233,5 +233,4 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.2.2.19-alpha"
-
+#define VERSION "0.2.3.1-alpha-dev"