diff options
Diffstat (limited to 'src')
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>&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>&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<<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 = ¤t_consensus->digests; - current_valid_after = current_consensus->valid_after; + if (current_ns_consensus) { + current_digests = ¤t_ns_consensus->digests; + current_valid_after = current_ns_consensus->valid_after; + } + } else if (!strcmp(flavor, "microdesc")) { + consensus_fname = get_datadir_fname("cached-microdesc-consensus"); + unverified_fname = get_datadir_fname("unverified-microdesc-consensus"); + if (current_md_consensus) { + current_digests = ¤t_md_consensus->digests; + current_valid_after = current_md_consensus->valid_after; } } else { cached_dir_t *cur; @@ -1695,24 +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" |