summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/compat.c34
-rw-r--r--src/common/compat.h38
-rw-r--r--src/common/container.c5
-rw-r--r--src/common/container.h4
-rw-r--r--src/common/crypto.c19
-rw-r--r--src/common/log.c20
-rw-r--r--src/common/torlog.h4
-rw-r--r--src/common/tortls.c4
-rw-r--r--src/common/util.c22
-rw-r--r--src/common/util.h3
-rw-r--r--src/or/circuitbuild.c2
-rw-r--r--src/or/circuitstats.c10
-rw-r--r--src/or/config.c61
-rw-r--r--src/or/connection.c12
-rw-r--r--src/or/cpuworker.c12
-rw-r--r--src/or/directory.c6
-rw-r--r--src/or/dirserv.c14
-rw-r--r--src/or/dirvote.c36
-rw-r--r--src/or/entrynodes.c220
-rw-r--r--src/or/entrynodes.h29
-rw-r--r--src/or/geoip.c4
-rw-r--r--src/or/main.c54
-rw-r--r--src/or/ntmain.h2
-rw-r--r--src/or/or.h2
-rw-r--r--src/or/reasons.c4
-rw-r--r--src/or/rendcommon.c2
-rw-r--r--src/or/rephist.c11
-rw-r--r--src/or/router.c3
-rw-r--r--src/or/routerlist.c36
-rw-r--r--src/or/routerlist.h3
-rw-r--r--src/test/include.am4
-rw-r--r--src/test/test.c13
-rw-r--r--src/test/test_config.c10
-rw-r--r--src/test/test_descriptors.inc305
-rw-r--r--src/test/test_entrynodes.c636
-rw-r--r--src/test/test_logging.c2
-rw-r--r--src/test/test_pt.c2
-rw-r--r--src/test/test_util.c102
-rw-r--r--src/win32/orconfig.h13
39 files changed, 1425 insertions, 338 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index e25ecc462d..c4f5987d5a 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -1004,6 +1004,23 @@ tor_fd_setpos(int fd, off_t pos)
#endif
}
+/** Replacement for ftruncate(fd, 0): move to the front of the file and remove
+ * all the rest of the file. Return -1 on error, 0 on success. */
+int
+tor_ftruncate(int fd)
+{
+ /* Rumor has it that some versions of ftruncate do not move the file pointer.
+ */
+ if (tor_fd_setpos(fd, 0) < 0)
+ return -1;
+
+#ifdef _WIN32
+ return _chsize(fd, 0);
+#else
+ return ftruncate(fd, 0);
+#endif
+}
+
#undef DEBUG_SOCKET_COUNTING
#ifdef DEBUG_SOCKET_COUNTING
/** A bitarray of all fds that should be passed to tor_socket_close(). Only
@@ -1670,12 +1687,12 @@ log_credential_status(void)
/* log supplementary groups */
sup_gids_size = 64;
- sup_gids = tor_malloc(sizeof(gid_t) * 64);
+ sup_gids = tor_calloc(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);
+ sup_gids = tor_reallocarray(sup_gids, sizeof(gid_t), sup_gids_size);
}
if (ngids < 0) {
@@ -2485,14 +2502,12 @@ get_uname(void)
"Unrecognized version of Windows [major=%d,minor=%d]",
(int)info.dwMajorVersion,(int)info.dwMinorVersion);
}
-#if !defined (WINCE)
#ifdef VER_NT_SERVER
if (info.wProductType == VER_NT_SERVER ||
info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
strlcat(uname_result, " [server]", sizeof(uname_result));
}
#endif
-#endif
#else
strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
#endif
@@ -2697,15 +2712,8 @@ tor_gettimeofday(struct timeval *timeval)
uint64_t ft_64;
FILETIME ft_ft;
} ft;
-#if defined (WINCE)
- /* wince do not have GetSystemTimeAsFileTime */
- SYSTEMTIME stime;
- GetSystemTime(&stime);
- SystemTimeToFileTime(&stime,&ft.ft_ft);
-#else
/* number of 100-nsec units since Jan 1, 1601 */
GetSystemTimeAsFileTime(&ft.ft_ft);
-#endif
if (ft.ft_64 < EPOCH_BIAS) {
log_err(LD_GENERAL,"System time is before 1970; failing.");
exit(1);
@@ -2731,7 +2739,7 @@ tor_gettimeofday(struct timeval *timeval)
return;
}
-#if defined(TOR_IS_MULTITHREADED) && !defined(_WIN32)
+#if !defined(_WIN32)
/** Defined iff we need to add locks when defining fake versions of reentrant
* versions of time-related functions. */
#define TIME_FNS_NEED_LOCKS
@@ -2991,7 +2999,6 @@ tor_get_thread_id(void)
}
#endif
-#ifdef TOR_IS_MULTITHREADED
/** Return a newly allocated, ready-for-use mutex. */
tor_mutex_t *
tor_mutex_new(void)
@@ -3009,7 +3016,6 @@ tor_mutex_free(tor_mutex_t *m)
tor_mutex_uninit(m);
tor_free(m);
}
-#endif
/* Conditions. */
#ifdef USE_PTHREADS
diff --git a/src/common/compat.h b/src/common/compat.h
index ec7d2415ed..852a432187 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -56,21 +56,6 @@
#include <stdio.h>
#include <errno.h>
-#if defined (WINCE)
-#include <fcntl.h>
-#include <io.h>
-#include <math.h>
-#include <projects.h>
-/* this is not exported as W .... */
-#define SHGetPathFromIDListW SHGetPathFromIDList
-/* wcecompat has vasprintf */
-#define HAVE_VASPRINTF
-/* no service here */
-#ifdef NT_SERVICE
-#undef NT_SERVICE
-#endif
-#endif // WINCE
-
#ifndef NULL_REP_IS_ZERO_BYTES
#error "It seems your platform does not represent NULL as zero. We can't cope."
#endif
@@ -423,6 +408,7 @@ void tor_lockfile_unlock(tor_lockfile_t *lockfile);
off_t tor_fd_getpos(int fd);
int tor_fd_setpos(int fd, off_t pos);
int tor_fd_seekend(int fd);
+int tor_ftruncate(int fd);
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
@@ -648,15 +634,12 @@ int get_total_system_memory(size_t *mem_out);
int spawn_func(void (*func)(void *), void *data);
void spawn_exit(void) ATTR_NORETURN;
-#if defined(ENABLE_THREADS) && defined(_WIN32)
+#if defined(_WIN32)
#define USE_WIN32_THREADS
-#define TOR_IS_MULTITHREADED 1
-#elif (defined(ENABLE_THREADS) && defined(HAVE_PTHREAD_H) && \
- defined(HAVE_PTHREAD_CREATE))
+#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE)
#define USE_PTHREADS
-#define TOR_IS_MULTITHREADED 1
#else
-#undef TOR_IS_MULTITHREADED
+#error "No threading system was found"
#endif
int compute_num_cpus(void);
@@ -682,7 +665,6 @@ typedef struct tor_mutex_t {
int tor_mlockall(void);
-#ifdef TOR_IS_MULTITHREADED
tor_mutex_t *tor_mutex_new(void);
void tor_mutex_init(tor_mutex_t *m);
void tor_mutex_acquire(tor_mutex_t *m);
@@ -691,21 +673,10 @@ void tor_mutex_free(tor_mutex_t *m);
void tor_mutex_uninit(tor_mutex_t *m);
unsigned long tor_get_thread_id(void);
void tor_threads_init(void);
-#else
-#define tor_mutex_new() ((tor_mutex_t*)tor_malloc(sizeof(int)))
-#define tor_mutex_init(m) STMT_NIL
-#define tor_mutex_acquire(m) STMT_VOID(m)
-#define tor_mutex_release(m) STMT_NIL
-#define tor_mutex_free(m) STMT_BEGIN tor_free(m); STMT_END
-#define tor_mutex_uninit(m) STMT_NIL
-#define tor_get_thread_id() (1UL)
-#define tor_threads_init() STMT_NIL
-#endif
void set_main_thread(void);
int in_main_thread(void);
-#ifdef TOR_IS_MULTITHREADED
#if 0
typedef struct tor_cond_t tor_cond_t;
tor_cond_t *tor_cond_new(void);
@@ -714,7 +685,6 @@ int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex);
void tor_cond_signal_one(tor_cond_t *cond);
void tor_cond_signal_all(tor_cond_t *cond);
#endif
-#endif
/** Macros for MIN/MAX. Never use these when the arguments could have
* side-effects.
diff --git a/src/common/container.c b/src/common/container.c
index b937d544fc..54f041bac7 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -34,7 +34,7 @@ smartlist_new(void)
smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
sl->num_used = 0;
sl->capacity = SMARTLIST_DEFAULT_CAPACITY;
- sl->list = tor_malloc(sizeof(void *) * sl->capacity);
+ sl->list = tor_calloc(sizeof(void *), sl->capacity);
return sl;
}
@@ -77,7 +77,8 @@ smartlist_ensure_capacity(smartlist_t *sl, int size)
higher *= 2;
}
sl->capacity = higher;
- sl->list = tor_realloc(sl->list, sizeof(void*)*((size_t)sl->capacity));
+ sl->list = tor_reallocarray(sl->list, sizeof(void *),
+ ((size_t)sl->capacity));
}
}
diff --git a/src/common/container.h b/src/common/container.h
index 0d31f2093b..08da34e07e 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -563,7 +563,7 @@ bitarray_init_zero(unsigned int n_bits)
{
/* round up to the next int. */
size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT;
- return tor_malloc_zero(sz*sizeof(unsigned int));
+ return tor_calloc(sz, sizeof(unsigned int));
}
/** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>,
* clearing all new bits. Returns a possibly changed pointer to the
@@ -577,7 +577,7 @@ bitarray_expand(bitarray_t *ba,
char *ptr;
if (sz_new <= sz_old)
return ba;
- ptr = tor_realloc(ba, sz_new*sizeof(unsigned int));
+ ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int));
/* This memset does nothing to the older excess bytes. But they were
* already set to 0 by bitarry_init_zero. */
memset(ptr+sz_old*sizeof(unsigned int), 0,
diff --git a/src/common/crypto.c b/src/common/crypto.c
index a247a87d48..014c83e850 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -75,12 +75,10 @@
/** Macro: is k a valid RSA private key? */
#define PRIVATE_KEY_OK(k) ((k) && (k)->key && (k)->key->p)
-#ifdef TOR_IS_MULTITHREADED
/** A number of preallocated mutexes for use by OpenSSL. */
static tor_mutex_t **openssl_mutexes_ = NULL;
/** How many mutexes have we allocated for use by OpenSSL? */
static int n_openssl_mutexes_ = 0;
-#endif
/** A public key, or a public/private key-pair. */
struct crypto_pk_t
@@ -1840,7 +1838,7 @@ crypto_store_dynamic_dh_modulus(const char *fname)
goto done;
}
- base64_encoded_dh = tor_malloc_zero(len * 2); /* should be enough */
+ base64_encoded_dh = tor_calloc(len, 2); /* should be enough */
new_len = base64_encode(base64_encoded_dh, len * 2,
(char *)dh_string_repr, len);
if (new_len < 0) {
@@ -3090,8 +3088,6 @@ memwipe(void *mem, uint8_t byte, size_t sz)
memset(mem, byte, sz);
}
-#ifdef TOR_IS_MULTITHREADED
-
#ifndef OPENSSL_THREADS
#error OpenSSL has been built without thread support. Tor requires an \
OpenSSL library with thread support enabled.
@@ -3168,7 +3164,7 @@ setup_openssl_threading(void)
int i;
int n = CRYPTO_num_locks();
n_openssl_mutexes_ = n;
- openssl_mutexes_ = tor_malloc(n*sizeof(tor_mutex_t *));
+ openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
for (i=0; i < n; ++i)
openssl_mutexes_[i] = tor_mutex_new();
CRYPTO_set_locking_callback(openssl_locking_cb_);
@@ -3178,13 +3174,6 @@ setup_openssl_threading(void)
CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy_cb_);
return 0;
}
-#else
-static int
-setup_openssl_threading(void)
-{
- return 0;
-}
-#endif
/** Uninitialize the crypto library. Return 0 on success, -1 on failure.
*/
@@ -3208,7 +3197,7 @@ crypto_global_cleanup(void)
CONF_modules_unload(1);
CRYPTO_cleanup_all_ex_data();
-#ifdef TOR_IS_MULTITHREADED
+
if (n_openssl_mutexes_) {
int n = n_openssl_mutexes_;
tor_mutex_t **ms = openssl_mutexes_;
@@ -3220,7 +3209,7 @@ crypto_global_cleanup(void)
}
tor_free(ms);
}
-#endif
+
tor_free(crypto_openssl_version_str);
tor_free(crypto_openssl_header_version_str);
return 0;
diff --git a/src/common/log.c b/src/common/log.c
index 517fa4faaa..2e51e5c578 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -1010,12 +1010,16 @@ mark_logs_temp(void)
* logfile fails, -1 is returned and errno is set appropriately (by open(2)).
*/
int
-add_file_log(const log_severity_list_t *severity, const char *filename)
+add_file_log(const log_severity_list_t *severity, const char *filename,
+ const int truncate)
{
int fd;
logfile_t *lf;
- fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ int open_flags = O_WRONLY|O_CREAT;
+ open_flags |= truncate ? O_TRUNC : O_APPEND;
+
+ fd = tor_open_cloexec(filename, open_flags, 0644);
if (fd<0)
return -1;
if (tor_fd_seekend(fd)<0) {
@@ -1297,3 +1301,15 @@ switch_logs_debug(void)
UNLOCK_LOGS();
}
+/** Truncate all the log files. */
+void
+truncate_logs(void)
+{
+ logfile_t *lf;
+ for (lf = logfiles; lf; lf = lf->next) {
+ if (lf->fd >= 0) {
+ tor_ftruncate(lf->fd);
+ }
+ }
+}
+
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 34f70f3c00..34e39b4b94 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -130,7 +130,8 @@ void set_log_severity_config(int minSeverity, int maxSeverity,
log_severity_list_t *severity_out);
void add_stream_log(const log_severity_list_t *severity, const char *name,
int fd);
-int add_file_log(const log_severity_list_t *severity, const char *filename);
+int add_file_log(const log_severity_list_t *severity, const char *filename,
+ const int truncate);
#ifdef HAVE_SYSLOG_H
int add_syslog_log(const log_severity_list_t *severity);
#endif
@@ -148,6 +149,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
void flush_pending_log_callbacks(void);
void log_set_application_name(const char *name);
void set_log_time_granularity(int granularity_msec);
+void truncate_logs(void);
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
CHECK_PRINTF(3,4);
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 4fd9bba380..0f989684cf 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -16,10 +16,6 @@
#include "orconfig.h"
-#if defined (WINCE)
-#include <WinSock2.h>
-#endif
-
#include <assert.h>
#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
#ifndef _WIN32_WINNT
diff --git a/src/common/util.c b/src/common/util.c
index 2d7893b38a..4029512978 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -244,6 +244,20 @@ tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS)
return result;
}
+/**
+ * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for
+ * overflow. Unlike other allocation functions, return NULL on overflow.
+ */
+void *
+tor_reallocarray_(void *ptr, size_t sz1, size_t sz2 DMALLOC_PARAMS)
+{
+ /* XXXX we can make this return 0, but we would need to check all the
+ * reallocarray users. */
+ tor_assert(sz2 == 0 || sz1 < SIZE_T_CEILING / sz2);
+
+ return tor_realloc(ptr, (sz1 * sz2) DMALLOC_FN_ARGS);
+}
+
/** Return a newly allocated copy of the NUL-terminated string s. On
* error, log and terminate. (Like strdup(s), but never returns
* NULL.)
@@ -1893,7 +1907,7 @@ check_private_dir(const char *dirname, cpd_check_t check,
}
if (check & CPD_CREATE) {
log_info(LD_GENERAL, "Creating directory %s", dirname);
-#if defined (_WIN32) && !defined (WINCE)
+#if defined (_WIN32)
r = mkdir(dirname);
#else
r = mkdir(dirname, 0700);
@@ -3378,8 +3392,8 @@ format_win_cmdline_argument(const char *arg)
smartlist_add(arg_chars, (void*)&backslash);
/* Allocate space for argument, quotes (if needed), and terminator */
- formatted_arg = tor_malloc(sizeof(char) *
- (smartlist_len(arg_chars) + (need_quotes?2:0) + 1));
+ formatted_arg = tor_calloc(sizeof(char),
+ (smartlist_len(arg_chars) + (need_quotes ? 2 : 0) + 1));
/* Add leading quote */
i=0;
@@ -5008,7 +5022,7 @@ tor_check_port_forwarding(const char *filename,
for each smartlist element (one for "-p" and one for the
ports), and one for the final NULL. */
args_n = 1 + 2*smartlist_len(ports_to_forward) + 1;
- argv = tor_malloc_zero(sizeof(char*)*args_n);
+ argv = tor_calloc(sizeof(char *), args_n);
argv[argv_index++] = filename;
SMARTLIST_FOREACH_BEGIN(ports_to_forward, const char *, port) {
diff --git a/src/common/util.h b/src/common/util.h
index 97367a9a7b..61bb05f016 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -79,6 +79,7 @@ void *tor_malloc_(size_t size DMALLOC_PARAMS) ATTR_MALLOC;
void *tor_malloc_zero_(size_t size DMALLOC_PARAMS) ATTR_MALLOC;
void *tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC;
void *tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS);
+void *tor_reallocarray_(void *ptr, size_t size1, size_t size2 DMALLOC_PARAMS);
char *tor_strdup_(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1));
char *tor_strndup_(const char *s, size_t n DMALLOC_PARAMS)
ATTR_MALLOC ATTR_NONNULL((1));
@@ -116,6 +117,8 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
#define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS)
#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS)
#define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS)
+#define tor_reallocarray(ptr, sz1, sz2) \
+ tor_reallocarray_((ptr), (sz1), (sz2) DMALLOC_ARGS)
#define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS)
#define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS)
#define tor_memdup(s, n) tor_memdup_(s, n DMALLOC_ARGS)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 283afee31f..2b17d1faba 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1560,7 +1560,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity)
* -1 means "Don't use this router at all."
*/
the_nodes = nodelist_get_list();
- n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes));
+ n_supported = tor_calloc(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)) {
diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c
index e362b1b49e..5cdd534507 100644
--- a/src/or/circuitstats.c
+++ b/src/or/circuitstats.c
@@ -404,7 +404,7 @@ circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
* distress anyway, so memory correctness here is paramount over
* doing acrobatics to preserve the array.
*/
- recent_circs = tor_malloc_zero(sizeof(int8_t)*num);
+ recent_circs = tor_calloc(sizeof(int8_t), num);
if (cbt->liveness.timeouts_after_firsthop &&
cbt->liveness.num_recent_circs > 0) {
memcpy(recent_circs, cbt->liveness.timeouts_after_firsthop,
@@ -508,7 +508,7 @@ circuit_build_times_init(circuit_build_times_t *cbt)
cbt->liveness.num_recent_circs =
circuit_build_times_recent_circuit_count(NULL);
cbt->liveness.timeouts_after_firsthop =
- tor_malloc_zero(sizeof(int8_t)*cbt->liveness.num_recent_circs);
+ tor_calloc(sizeof(int8_t), cbt->liveness.num_recent_circs);
} else {
cbt->liveness.num_recent_circs = 0;
cbt->liveness.timeouts_after_firsthop = NULL;
@@ -649,7 +649,7 @@ circuit_build_times_create_histogram(const circuit_build_times_t *cbt,
int i, c;
*nbins = 1 + (max_build_time / CBT_BIN_WIDTH);
- histogram = tor_malloc_zero(*nbins * sizeof(build_time_t));
+ histogram = tor_calloc(*nbins, sizeof(build_time_t));
// calculate histogram
for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
@@ -691,7 +691,7 @@ circuit_build_times_get_xm(circuit_build_times_t *cbt)
if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE)
num_modes = 1;
- nth_max_bin = (build_time_t*)tor_malloc_zero(num_modes*sizeof(build_time_t));
+ nth_max_bin = (build_time_t*)tor_calloc(num_modes, sizeof(build_time_t));
/* Determine the N most common build times */
for (i = 0; i < nbins; i++) {
@@ -873,7 +873,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
}
/* build_time_t 0 means uninitialized */
- loaded_times = tor_malloc_zero(sizeof(build_time_t)*state->TotalBuildTimes);
+ loaded_times = tor_calloc(sizeof(build_time_t), state->TotalBuildTimes);
for (line = state->BuildtimeHistogram; line; line = line->next) {
smartlist_t *args = smartlist_new();
diff --git a/src/or/config.c b/src/or/config.c
index 2661ce3b73..2535a72d39 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -302,6 +302,7 @@ static config_var_t option_vars_[] = {
OBSOLETE("LogLevel"),
OBSOLETE("LogFile"),
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
+ V(TruncateLogFile, BOOL, "0"),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -557,7 +558,8 @@ static int check_server_ports(const smartlist_t *ports,
static int validate_data_directory(or_options_t *options);
static int write_configuration_file(const char *fname,
const or_options_t *options);
-static int options_init_logs(or_options_t *options, int validate_only);
+static int options_init_logs(const or_options_t *old_options,
+ or_options_t *options, int validate_only);
static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
@@ -1145,7 +1147,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)
mark_logs_temp(); /* Close current logs once new logs are open. */
logs_marked = 1;
- if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */
+ /* Configure the tor_log(s) */
+ if (options_init_logs(old_options, options, 0)<0) {
*msg = tor_strdup("Failed to init Log options. See logs for details.");
goto rollback;
}
@@ -1592,6 +1595,20 @@ options_act(const or_options_t *old_options)
return -1;
}
+ config_maybe_load_geoip_files_(options, old_options);
+
+ if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
+ /* ExcludeUnknown is true or "auto" */
+ const int is_auto = options->GeoIPExcludeUnknown == -1;
+ int changed;
+
+ changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto);
+ changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto);
+
+ if (changed)
+ routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto);
+ }
+
/* Check for transitions that need action. */
if (old_options) {
int revise_trackexithosts = 0;
@@ -1687,20 +1704,6 @@ options_act(const or_options_t *old_options)
connection_or_update_token_buckets(get_connection_array(), options);
}
- config_maybe_load_geoip_files_(options, old_options);
-
- if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
- /* ExcludeUnknown is true or "auto" */
- const int is_auto = options->GeoIPExcludeUnknown == -1;
- int changed;
-
- changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto);
- changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto);
-
- if (changed)
- routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto);
- }
-
if (options->CellStatistics || options->DirReqStatistics ||
options->EntryStatistics || options->ExitPortStatistics ||
options->ConnDirectionStatistics ||
@@ -2547,7 +2550,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
config_line_append(&options->Logs, "Log", "warn stdout");
}
- if (options_init_logs(options, 1)<0) /* Validate the tor_log(s) */
+ /* Validate the tor_log(s) */
+ if (options_init_logs(old_options, options, 1)<0)
REJECT("Failed to validate Log options. See logs for details.");
if (authdir_mode(options)) {
@@ -4446,7 +4450,8 @@ addressmap_register_auto(const char *from, const char *to,
* Initialize the logs based on the configuration file.
*/
static int
-options_init_logs(or_options_t *options, int validate_only)
+options_init_logs(const or_options_t *old_options, or_options_t *options,
+ int validate_only)
{
config_line_t *opt;
int ok;
@@ -4539,7 +4544,21 @@ options_init_logs(or_options_t *options, int validate_only)
!strcasecmp(smartlist_get(elts,0), "file")) {
if (!validate_only) {
char *fname = expand_filename(smartlist_get(elts, 1));
- if (add_file_log(severity, fname) < 0) {
+ /* Truncate if TruncateLogFile is set and we haven't seen this option
+ line before. */
+ int truncate = 0;
+ if (options->TruncateLogFile) {
+ truncate = 1;
+ if (old_options) {
+ config_line_t *opt2;
+ for (opt2 = old_options->Logs; opt2; opt2 = opt2->next)
+ if (!strcmp(opt->value, opt2->value)) {
+ truncate = 0;
+ break;
+ }
+ }
+ }
+ if (add_file_log(severity, fname, truncate) < 0) {
log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
opt->value, strerror(errno));
ok = 0;
@@ -4828,7 +4847,7 @@ parse_client_transport_line(const or_options_t *options,
if (!validate_only && !is_useless_proxy) {
proxy_argc = line_length-2;
tor_assert(proxy_argc > 0);
- proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
+ proxy_argv = tor_calloc(sizeof(char *), (proxy_argc + 1));
tmp = proxy_argv;
for (i=0;i<proxy_argc;i++) { /* store arguments */
*tmp++ = smartlist_get(items, 2);
@@ -5108,7 +5127,7 @@ parse_server_transport_line(const or_options_t *options,
if (!validate_only) {
proxy_argc = line_length-2;
tor_assert(proxy_argc > 0);
- proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
+ proxy_argv = tor_calloc(sizeof(char *), (proxy_argc + 1));
tmp = proxy_argv;
for (i=0;i<proxy_argc;i++) { /* store arguments */
diff --git a/src/or/connection.c b/src/or/connection.c
index 4788bdf950..4d7cec7f9a 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -3715,9 +3715,15 @@ connection_handle_write_impl(connection_t *conn, int force)
if (connection_state_is_connecting(conn)) {
if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) {
log_warn(LD_BUG, "getsockopt() syscall failed");
- if (CONN_IS_EDGE(conn))
- connection_edge_end_errno(TO_EDGE_CONN(conn));
- connection_mark_for_close(conn);
+ if (conn->type == CONN_TYPE_OR) {
+ or_connection_t *orconn = TO_OR_CONN(conn);
+ connection_or_close_for_error(orconn, 0);
+ } else {
+ if (CONN_IS_EDGE(conn)) {
+ connection_edge_end_errno(TO_EDGE_CONN(conn));
+ }
+ connection_mark_for_close(conn);
+ }
return -1;
}
if (e) {
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 61b2c29b38..94138f8c1e 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -414,12 +414,6 @@ cpuworker_main(void *data)
cpuworker_reply_t rpl;
fd = fdarray[1]; /* this side is ours */
-#ifndef TOR_IS_MULTITHREADED
- tor_close_socket(fdarray[0]); /* this is the side of the socketpair the
- * parent uses */
- tor_free_all(1); /* so the child doesn't hold the parent's fd's open */
- handle_signals(0); /* ignore interrupts from the keyboard, etc */
-#endif
tor_free(data);
setup_server_onion_keys(&onion_keys);
@@ -516,7 +510,7 @@ spawn_cpuworker(void)
connection_t *conn;
int err;
- fdarray = tor_malloc(sizeof(tor_socket_t)*2);
+ fdarray = tor_calloc(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));
@@ -535,10 +529,6 @@ spawn_cpuworker(void)
return -1;
}
log_debug(LD_OR,"just spawned a cpu worker.");
-#ifndef TOR_IS_MULTITHREADED
- tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */
- tor_free(fdarray);
-#endif
conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX);
diff --git a/src/or/directory.c b/src/or/directory.c
index 51ea312689..d8492cbbec 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -197,9 +197,9 @@ dir_conn_purpose_to_string(int purpose)
return "(unknown)";
}
-/** Return true iff <b>identity_digest</b> is the digest of a router we
- * believe to support extrainfo downloads. (If <b>is_authority</b> we do
- * additional checking that's only valid for authorities.) */
+/** Return true iff <b>identity_digest</b> is the digest of a router which
+ * says that it caches extrainfos. (If <b>is_authority</b> we always
+ * believe that to be true.) */
int
router_supports_extrainfo(const char *identity_digest, int is_authority)
{
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 49fafafab2..f33437ff52 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1468,7 +1468,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
* to fix the bug was 0.2.2.25-alpha. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
- node->is_running);
+ router_is_active(router, node, now));
}
/** Don't consider routers with less bandwidth than this when computing
@@ -1537,18 +1537,18 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
* sort them and use that to compute thresholds. */
n_active = n_active_nonexit = 0;
/* Uptime for every active router. */
- uptimes = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers));
+ uptimes = tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers));
/* Bandwidth for every active router. */
- bandwidths_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers));
+ bandwidths_kb = tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers));
/* Bandwidth for every active non-exit router. */
bandwidths_excluding_exits_kb =
- tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers));
+ tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers));
/* Weighted mean time between failure for each active router. */
- mtbfs = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
+ mtbfs = tor_calloc(sizeof(double), smartlist_len(rl->routers));
/* Time-known for each active router. */
- tks = tor_malloc(sizeof(long)*smartlist_len(rl->routers));
+ tks = tor_calloc(sizeof(long), smartlist_len(rl->routers));
/* Weighted fractional uptime for each active router. */
- wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
+ wfus = tor_calloc(sizeof(double), smartlist_len(rl->routers));
nodelist_assert_ok();
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index c7be343ca2..30f132115b 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -607,7 +607,7 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
between INT32_MIN and INT32_MAX inclusive. This should be guaranteed by
the parsing code. */
- vals = tor_malloc(sizeof(int)*n_votes);
+ vals = tor_calloc(sizeof(int), n_votes);
SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
if (!v->net_params)
@@ -1353,11 +1353,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
* routers we might need to talk about. */
{
int n_votes = smartlist_len(votes);
- time_t *va_times = tor_malloc(n_votes * sizeof(time_t));
- time_t *fu_times = tor_malloc(n_votes * sizeof(time_t));
- time_t *vu_times = tor_malloc(n_votes * sizeof(time_t));
- int *votesec_list = tor_malloc(n_votes * sizeof(int));
- int *distsec_list = tor_malloc(n_votes * sizeof(int));
+ time_t *va_times = tor_calloc(n_votes, sizeof(time_t));
+ time_t *fu_times = tor_calloc(n_votes, sizeof(time_t));
+ time_t *vu_times = tor_calloc(n_votes, sizeof(time_t));
+ int *votesec_list = tor_calloc(n_votes, sizeof(int));
+ int *distsec_list = tor_calloc(n_votes, sizeof(int));
int n_versioning_clients = 0, n_versioning_servers = 0;
smartlist_t *combined_client_versions = smartlist_new();
smartlist_t *combined_server_versions = smartlist_new();
@@ -1555,9 +1555,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_t *chosen_flags = smartlist_new();
smartlist_t *versions = smartlist_new();
smartlist_t *exitsummaries = smartlist_new();
- uint32_t *bandwidths_kb = tor_malloc(sizeof(uint32_t) *
+ uint32_t *bandwidths_kb = tor_calloc(sizeof(uint32_t),
smartlist_len(votes));
- uint32_t *measured_bws_kb = tor_malloc(sizeof(uint32_t) *
+ uint32_t *measured_bws_kb = tor_calloc(sizeof(uint32_t),
smartlist_len(votes));
int num_bandwidths;
int num_mbws;
@@ -1579,13 +1579,13 @@ networkstatus_compute_consensus(smartlist_t *votes,
memset(conflict, 0, sizeof(conflict));
memset(unknown, 0xff, sizeof(conflict));
- index = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
- size = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
- n_voter_flags = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
- n_flag_voters = tor_malloc_zero(sizeof(int) * smartlist_len(flags));
- flag_map = tor_malloc_zero(sizeof(int*) * smartlist_len(votes));
- named_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
- unnamed_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
+ index = tor_calloc(sizeof(int), smartlist_len(votes));
+ size = tor_calloc(sizeof(int), smartlist_len(votes));
+ n_voter_flags = tor_calloc(sizeof(int), smartlist_len(votes));
+ n_flag_voters = tor_calloc(sizeof(int), smartlist_len(flags));
+ flag_map = tor_calloc(sizeof(int *), smartlist_len(votes));
+ named_flag = tor_calloc(sizeof(int), smartlist_len(votes));
+ unnamed_flag = tor_calloc(sizeof(int), smartlist_len(votes));
for (i = 0; i < smartlist_len(votes); ++i)
unnamed_flag[i] = named_flag[i] = -1;
chosen_named_idx = smartlist_string_pos(flags, "Named");
@@ -1597,8 +1597,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
* that they're actually set before doing U64_LITERAL(1) << index with
* them.*/
SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
- flag_map[v_sl_idx] = tor_malloc_zero(
- sizeof(int)*smartlist_len(v->known_flags));
+ flag_map[v_sl_idx] = tor_calloc(sizeof(int),
+ smartlist_len(v->known_flags));
if (smartlist_len(v->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) {
log_warn(LD_BUG, "Somehow, a vote has %d entries in known_flags",
smartlist_len(v->known_flags));
@@ -1678,7 +1678,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
);
/* Now go through all the votes */
- flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags));
+ flag_counts = tor_calloc(sizeof(int), smartlist_len(flags));
while (1) {
vote_routerstatus_t *rs;
routerstatus_t rs_out;
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 66b7201187..365b9274ec 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -12,6 +12,8 @@
* circumvention).
**/
+#define ENTRYNODES_PRIVATE
+
#include "or.h"
#include "circpathbias.h"
#include "circuitbuild.h"
@@ -155,7 +157,7 @@ entry_guard_set_status(entry_guard_t *e, const node_t *node,
/** Return true iff enough time has passed since we last tried to connect
* to the unreachable guard <b>e</b> that we're willing to try again. */
static int
-entry_is_time_to_retry(entry_guard_t *e, time_t now)
+entry_is_time_to_retry(const entry_guard_t *e, time_t now)
{
long diff;
if (e->last_attempted < e->unreachable_since)
@@ -188,12 +190,17 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
* If need_descriptor is true, only return the node if we currently have
* a descriptor (routerinfo or microdesc) for it.
*/
-static INLINE const node_t *
-entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
- int assume_reachable, int need_descriptor, const char **msg)
+STATIC const node_t *
+entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags,
+ const char **msg)
{
const node_t *node;
const or_options_t *options = get_options();
+ int need_uptime = (flags & ENTRY_NEED_UPTIME) != 0;
+ int need_capacity = (flags & ENTRY_NEED_CAPACITY) != 0;
+ const int assume_reachable = (flags & ENTRY_ASSUME_REACHABLE) != 0;
+ const int need_descriptor = (flags & ENTRY_NEED_DESCRIPTOR) != 0;
+
tor_assert(msg);
if (e->path_bias_disabled) {
@@ -255,12 +262,18 @@ num_live_entry_guards(int for_directory)
{
int n = 0;
const char *msg;
+ /* Set the entry node attributes we are interested in. */
+ entry_is_live_flags_t entry_flags = ENTRY_NEED_CAPACITY;
+ if (!for_directory) {
+ entry_flags |= ENTRY_NEED_DESCRIPTOR;
+ }
+
if (! entry_guards)
return 0;
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
if (for_directory && !entry->is_dir_cache)
continue;
- if (entry_is_live(entry, 0, 1, 0, !for_directory, &msg))
+ if (entry_is_live(entry, entry_flags, &msg))
++n;
} SMARTLIST_FOREACH_END(entry);
return n;
@@ -289,7 +302,7 @@ log_entry_guards(int severity)
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e)
{
const char *msg = NULL;
- if (entry_is_live(e, 0, 1, 0, 0, &msg))
+ if (entry_is_live(e, ENTRY_NEED_CAPACITY, &msg))
smartlist_add_asprintf(elements, "%s [%s] (up %s)",
e->nickname,
hex_str(e->identity, DIGEST_LEN),
@@ -350,7 +363,7 @@ 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 const node_t *
+STATIC const node_t *
add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
int for_discovery, int for_directory)
{
@@ -437,7 +450,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
/** Choose how many entry guards or directory guards we'll use. If
* <b>for_directory</b> is true, we return how many directory guards to
* use; else we return how many entry guards to use. */
-static int
+STATIC int
decide_num_guards(const or_options_t *options, int for_directory)
{
if (for_directory) {
@@ -676,7 +689,7 @@ entry_guards_compute_status(const or_options_t *options, time_t now)
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *reason = digestmap_get(reasons, entry->identity);
const char *live_msg = "";
- const node_t *r = entry_is_live(entry, 0, 1, 0, 0, &live_msg);
+ const node_t *r = entry_is_live(entry, ENTRY_NEED_CAPACITY, &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),
@@ -794,7 +807,9 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
break;
if (e->made_contact) {
const char *msg;
- const node_t *r = entry_is_live(e, 0, 1, 1, 0, &msg);
+ const node_t *r = entry_is_live(e,
+ ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE,
+ &msg);
if (r && e->unreachable_since) {
refuse_conn = 1;
e->can_retry = 1;
@@ -847,7 +862,7 @@ update_node_guard_status(void)
/** Adjust the entry guards list so that it only contains entries from
* EntryNodes, adding new entries from EntryNodes to the list as needed. */
-static void
+STATIC void
entry_guards_set_from_config(const or_options_t *options)
{
smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps;
@@ -1007,47 +1022,61 @@ choose_random_dirguard(dirinfo_type_t type)
return choose_random_entry_impl(NULL, 1, type, NULL);
}
-/** Helper for choose_random{entry,dirguard}. */
-static const node_t *
-choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
- dirinfo_type_t dirinfo_type, int *n_options_out)
+/** Filter <b>all_entry_guards</b> for usable entry guards and put them
+ * in <b>live_entry_guards</b>. We filter based on whether the node is
+ * currently alive, and on whether it satisfies the restrictions
+ * imposed by the other arguments of this function.
+ *
+ * We don't place more guards than NumEntryGuards in <b>live_entry_guards</b>.
+ *
+ * If <b>chosen_exit</b> is set, it contains the exit node of this
+ * circuit. Make sure to not use it or its family as an entry guard.
+ *
+ * If <b>need_uptime</b> is set, we are looking for a stable entry guard.
+ * if <b>need_capacity</b> is set, we are looking for a fast entry guard.
+ *
+ * The rest of the arguments are the same as in choose_random_entry_impl().
+ *
+ * Return 1 if we should choose a guard right away. Return 0 if we
+ * should try to add more nodes to our list before deciding on a
+ * guard.
+ */
+STATIC int
+populate_live_entry_guards(smartlist_t *live_entry_guards,
+ const smartlist_t *all_entry_guards,
+ const node_t *chosen_exit,
+ dirinfo_type_t dirinfo_type,
+ int for_directory,
+ int need_uptime, int need_capacity)
{
const or_options_t *options = get_options();
- smartlist_t *live_entry_guards = smartlist_new();
- smartlist_t *exit_family = smartlist_new();
- const node_t *chosen_exit =
- state?build_state_get_exit_node(state) : NULL;
const node_t *node = NULL;
- int need_uptime = state ? state->need_uptime : 0;
- int need_capacity = state ? state->need_capacity : 0;
- int preferred_min, consider_exit_family = 0;
- int need_descriptor = !for_directory;
const int num_needed = decide_num_guards(options, for_directory);
+ smartlist_t *exit_family = smartlist_new();
+ int retval = 0;
+ entry_is_live_flags_t entry_flags = 0;
- if (n_options_out)
- *n_options_out = 0;
+ { /* Set the flags we want our entry node to have */
+ if (need_uptime) {
+ entry_flags |= ENTRY_NEED_UPTIME;
+ }
+ if (need_capacity) {
+ entry_flags |= ENTRY_NEED_CAPACITY;
+ }
+ if (!for_directory) {
+ entry_flags |= ENTRY_NEED_DESCRIPTOR;
+ }
+ }
+
+ tor_assert(all_entry_guards);
if (chosen_exit) {
nodelist_add_node_and_family(exit_family, chosen_exit);
- consider_exit_family = 1;
}
- if (!entry_guards)
- entry_guards = smartlist_new();
-
- if (should_add_entry_nodes)
- entry_guards_set_from_config(options);
-
- if (!entry_list_is_constrained(options) &&
- smartlist_len(entry_guards) < num_needed)
- pick_entry_guards(options, for_directory);
-
- retry:
- smartlist_clear(live_entry_guards);
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
+ SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) {
const char *msg;
- node = entry_is_live(entry, need_uptime, need_capacity, 0,
- need_descriptor, &msg);
+ node = entry_is_live(entry, entry_flags, &msg);
if (!node)
continue; /* down, no point */
if (for_directory) {
@@ -1056,39 +1085,94 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
}
if (node == chosen_exit)
continue; /* don't pick the same node for entry and exit */
- if (consider_exit_family && smartlist_contains(exit_family, node))
+ if (smartlist_contains(exit_family, node))
continue; /* avoid relays that are family members of our exit */
if (dirinfo_type != NO_DIRINFO &&
!node_can_handle_dirinfo(node, dirinfo_type))
continue; /* this node won't be able to answer our dir questions */
-#if 0 /* since EntryNodes is always strict now, this clause is moot */
- if (options->EntryNodes &&
- !routerset_contains_node(options->EntryNodes, node)) {
- /* We've come to the end of our preferred entry nodes. */
- if (smartlist_len(live_entry_guards))
- goto choose_and_finish; /* only choose from the ones we like */
- if (options->StrictNodes) {
- /* in theory this case should never happen, since
- * entry_guards_set_from_config() drops unwanted relays */
- tor_fragile_assert();
- } else {
- log_info(LD_CIRC,
- "No relays from EntryNodes available. Using others.");
- }
- }
-#endif
smartlist_add(live_entry_guards, (void*)node);
if (!entry->made_contact) {
/* Always start with the first not-yet-contacted entry
* guard. Otherwise we might add several new ones, pick
* the second new one, and now we've expanded our entry
* guard list without needing to. */
- goto choose_and_finish;
+ retval = 1;
+ goto done;
+ }
+ if (smartlist_len(live_entry_guards) >= num_needed) {
+ retval = 1;
+ goto done; /* We picked enough entry guards. Done! */
}
- if (smartlist_len(live_entry_guards) >= num_needed)
- goto choose_and_finish; /* we have enough */
} SMARTLIST_FOREACH_END(entry);
+ done:
+ smartlist_free(exit_family);
+
+ return retval;
+}
+
+/** Pick a node to be used as the entry guard of a circuit.
+ *
+ * If <b>state</b> is set, it contains the information we know about
+ * the upcoming circuit.
+ *
+ * If <b>for_directory</b> is set, we are looking for a directory guard.
+ *
+ * <b>dirinfo_type</b> contains the kind of directory information we
+ * are looking for in our node.
+ *
+ * If <b>n_options_out</b> is set, we set it to the number of
+ * candidate guard nodes we had before picking a specific guard node.
+ *
+ * On success, return the node that should be used as the entry guard
+ * of the circuit. Return NULL if no such node could be found.
+ *
+ * Helper for choose_random{entry,dirguard}.
+*/
+static const node_t *
+choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
+ dirinfo_type_t dirinfo_type, int *n_options_out)
+{
+ const or_options_t *options = get_options();
+ smartlist_t *live_entry_guards = smartlist_new();
+ const node_t *chosen_exit =
+ state?build_state_get_exit_node(state) : NULL;
+ const node_t *node = NULL;
+ int need_uptime = state ? state->need_uptime : 0;
+ int need_capacity = state ? state->need_capacity : 0;
+ int preferred_min = 0;
+ const int num_needed = decide_num_guards(options, for_directory);
+ int retval = 0;
+
+ if (n_options_out)
+ *n_options_out = 0;
+
+ if (!entry_guards)
+ entry_guards = smartlist_new();
+
+ if (should_add_entry_nodes)
+ entry_guards_set_from_config(options);
+
+ if (!entry_list_is_constrained(options) &&
+ smartlist_len(entry_guards) < num_needed)
+ pick_entry_guards(options, for_directory);
+
+ retry:
+ smartlist_clear(live_entry_guards);
+
+ /* Populate the list of live entry guards so that we pick one of
+ them. */
+ retval = populate_live_entry_guards(live_entry_guards,
+ entry_guards,
+ chosen_exit,
+ dirinfo_type,
+ for_directory,
+ need_uptime, need_capacity);
+
+ if (retval == 1) { /* We should choose a guard right now. */
+ goto choose_and_finish;
+ }
+
if (entry_list_is_constrained(options)) {
/* If we prefer the entry nodes we've got, and we have at least
* one choice, that's great. Use it. */
@@ -1127,18 +1211,7 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
need_capacity = 0;
goto retry;
}
-#if 0
- /* Removing this retry logic: if we only allow one exit, and it is in the
- same family as all our entries, then we are just plain not going to win
- here. */
- if (!node && entry_list_is_constrained(options) && consider_exit_family) {
- /* still no? if we're using bridges or have strictentrynodes
- * set, and our chosen exit is in the same family as all our
- * bridges/entry guards, then be flexible about families. */
- consider_exit_family = 0;
- goto retry;
- }
-#endif
+
/* live_entry_guards may be empty below. Oh well, we tried. */
}
@@ -1156,7 +1229,6 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
if (n_options_out)
*n_options_out = smartlist_len(live_entry_guards);
smartlist_free(live_entry_guards);
- smartlist_free(exit_family);
return node;
}
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index e229f3b79a..5d91756aa4 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -77,6 +77,35 @@ int num_live_entry_guards(int for_directory);
#endif
+#ifdef ENTRYNODES_PRIVATE
+STATIC const node_t *add_an_entry_guard(const node_t *chosen,
+ int reset_status, int prepend,
+ int for_discovery, int for_directory);
+
+STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards,
+ const smartlist_t *all_entry_guards,
+ const node_t *chosen_exit,
+ dirinfo_type_t dirinfo_type,
+ int for_directory,
+ int need_uptime, int need_capacity);
+STATIC int decide_num_guards(const or_options_t *options, int for_directory);
+
+STATIC void entry_guards_set_from_config(const or_options_t *options);
+
+/** Flags to be passed to entry_is_live() to indicate what kind of
+ * entry nodes we are looking for. */
+typedef enum {
+ ENTRY_NEED_UPTIME = 1<<0,
+ ENTRY_NEED_CAPACITY = 1<<1,
+ ENTRY_ASSUME_REACHABLE = 1<<2,
+ ENTRY_NEED_DESCRIPTOR = 1<<3,
+} entry_is_live_flags_t;
+
+STATIC const node_t *entry_is_live(const entry_guard_t *e,
+ entry_is_live_flags_t flags,
+ const char **msg);
+#endif
+
void remove_all_entry_guards(void);
void entry_guards_compute_status(const or_options_t *options, time_t now);
diff --git a/src/or/geoip.c b/src/or/geoip.c
index f722bac468..feb54aac6e 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -963,7 +963,7 @@ geoip_get_dirreq_history(dirreq_type_t type)
/* We may have rounded 'completed' up. Here we want to use the
* real value. */
complete = smartlist_len(dirreq_completed);
- dltimes = tor_malloc_zero(sizeof(uint32_t) * complete);
+ dltimes = tor_calloc(sizeof(uint32_t), complete);
SMARTLIST_FOREACH_BEGIN(dirreq_completed, dirreq_map_entry_t *, ent) {
uint32_t bytes_per_second;
uint32_t time_diff = (uint32_t) tv_mdiff(&ent->request_time,
@@ -1033,7 +1033,7 @@ geoip_get_client_history(geoip_client_action_t action,
if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6))
return -1;
- counts = tor_malloc_zero(sizeof(unsigned)*n_countries);
+ counts = tor_calloc(sizeof(unsigned), n_countries);
HT_FOREACH(ent, clientmap, &client_history) {
int country;
if ((*ent)->action != (int)action)
diff --git a/src/or/main.c b/src/or/main.c
index 9c1cabf037..c7b532bbab 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1861,6 +1861,10 @@ do_hup(void)
return -1;
}
options = get_options(); /* they have changed now */
+ /* Logs are only truncated the first time they are opened, but were
+ probably intended to be cleaned up on signal. */
+ if (options->TruncateLogFile)
+ truncate_logs();
} else {
char *msg = NULL;
log_notice(LD_GENERAL, "Not reloading config file: the controller told "
@@ -2709,31 +2713,6 @@ do_dump_config(void)
return 0;
}
-#if defined (WINCE)
-int
-find_flashcard_path(PWCHAR path, size_t size)
-{
- WIN32_FIND_DATA d = {0};
- HANDLE h = NULL;
-
- if (!path)
- return -1;
-
- h = FindFirstFlashCard(&d);
- if (h == INVALID_HANDLE_VALUE)
- return -1;
-
- if (wcslen(d.cFileName) == 0) {
- FindClose(h);
- return -1;
- }
-
- wcsncpy(path,d.cFileName,size);
- FindClose(h);
- return 0;
-}
-#endif
-
static void
init_addrinfo(void)
{
@@ -2962,31 +2941,6 @@ int
tor_main(int argc, char *argv[])
{
int result = 0;
-#if defined (WINCE)
- WCHAR path [MAX_PATH] = {0};
- WCHAR fullpath [MAX_PATH] = {0};
- PWCHAR p = NULL;
- FILE* redir = NULL;
- FILE* redirdbg = NULL;
-
- // this is to facilitate debugging by opening
- // a file on a folder shared by the wm emulator.
- // if no flashcard (real or emulated) is present,
- // log files will be written in the root folder
- if (find_flashcard_path(path,MAX_PATH) == -1) {
- redir = _wfreopen( L"\\stdout.log", L"w", stdout );
- redirdbg = _wfreopen( L"\\stderr.log", L"w", stderr );
- } else {
- swprintf(fullpath,L"\\%s\\tor",path);
- CreateDirectory(fullpath,NULL);
-
- swprintf(fullpath,L"\\%s\\tor\\stdout.log",path);
- redir = _wfreopen( fullpath, L"w", stdout );
-
- swprintf(fullpath,L"\\%s\\tor\\stderr.log",path);
- redirdbg = _wfreopen( fullpath, L"w", stderr );
- }
-#endif
#ifdef _WIN32
/* Call SetProcessDEPPolicy to permanently enable DEP.
diff --git a/src/or/ntmain.h b/src/or/ntmain.h
index d3027936cd..d09a413aee 100644
--- a/src/or/ntmain.h
+++ b/src/or/ntmain.h
@@ -13,10 +13,8 @@
#define TOR_NTMAIN_H
#ifdef _WIN32
-#if !defined (WINCE)
#define NT_SERVICE
#endif
-#endif
#ifdef NT_SERVICE
int nt_service_parse_options(int argc, char **argv, int *should_exit);
diff --git a/src/or/or.h b/src/or/or.h
index 131bce3e11..0419111a4e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3402,6 +3402,8 @@ typedef struct {
int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
* each log message occurs? */
+ int TruncateLogFile; /**< Boolean: Should we truncate the log file
+ before we start writing? */
char *DebugLogFile; /**< Where to send verbose log messages. */
char *DataDirectory; /**< OR only: where to store long-term data. */
diff --git a/src/or/reasons.c b/src/or/reasons.c
index 750e89bbe7..1a53a93d88 100644
--- a/src/or/reasons.c
+++ b/src/or/reasons.c
@@ -367,7 +367,7 @@ circuit_end_reason_to_control_string(int reason)
}
}
-/** Return a string corresponding to a SOCKS4 reponse code. */
+/** Return a string corresponding to a SOCKS4 response code. */
const char *
socks4_response_code_to_string(uint8_t code)
{
@@ -385,7 +385,7 @@ socks4_response_code_to_string(uint8_t code)
}
}
-/** Return a string corresponding to a SOCKS5 reponse code. */
+/** Return a string corresponding to a SOCKS5 response code. */
const char *
socks5_response_code_to_string(uint8_t code)
{
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index a664b5d501..aca9da198a 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -528,7 +528,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
return -1;
}
/* Base64-encode introduction points. */
- ipos_base64 = tor_malloc_zero(ipos_len * 2);
+ ipos_base64 = tor_calloc(ipos_len, 2);
if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len)<0) {
log_warn(LD_REND, "Could not encode introduction point string to "
"base64. length=%d", (int)ipos_len);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 5446c25e36..8a0dbe1a88 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1998,12 +1998,9 @@ void
rep_hist_exit_stats_init(time_t now)
{
start_of_exit_stats_interval = now;
- exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS *
- sizeof(uint64_t));
- exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS *
- sizeof(uint64_t));
- exit_streams = tor_malloc_zero(EXIT_STATS_NUM_PORTS *
- sizeof(uint32_t));
+ exit_bytes_read = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t));
+ exit_bytes_written = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t));
+ exit_streams = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint32_t));
}
/** Reset counters for exit port statistics. */
@@ -2572,7 +2569,7 @@ rep_hist_format_desc_stats(time_t now)
size = digestmap_size(served_descs);
if (size > 0) {
- vals = tor_malloc(size * sizeof(int));
+ vals = tor_calloc(size, sizeof(int));
for (iter = digestmap_iter_init(served_descs);
!digestmap_iter_done(iter);
iter = digestmap_iter_next(served_descs, iter)) {
diff --git a/src/or/router.c b/src/or/router.c
index 2cdbb0c8bb..4fcd4a5b89 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -2371,7 +2371,8 @@ router_dump_router_to_string(routerinfo_t *router,
has_extra_info_digest ? "extra-info-digest " : "",
has_extra_info_digest ? extra_info_digest : "",
has_extra_info_digest ? "\n" : "",
- options->DownloadExtraInfo ? "caches-extra-info\n" : "",
+ (options->DownloadExtraInfo || options->V3AuthoritativeDir) ?
+ "caches-extra-info\n" : "",
onion_pkey, identity_pkey,
family_line,
we_are_hibernating() ? "hibernating 1\n" : "",
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index b5e924522e..12ed71d01e 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -448,9 +448,10 @@ trusted_dirs_flush_certs_to_disk(void)
trusted_dir_servers_certs_changed = 0;
}
-/** Remove all v3 authority certificates that have been superseded for more
- * than 48 hours. (If the most recent cert was published more than 48 hours
- * ago, then we aren't going to get any consensuses signed with older
+/** Remove all expired v3 authority certificates that have been superseded for
+ * more than 48 hours or, if not expired, that were published more than 7 days
+ * before being superseded. (If the most recent cert was published more than 48
+ * hours ago, then we aren't going to get any consensuses signed with older
* keys.) */
static void
trusted_dirs_remove_old_certs(void)
@@ -488,6 +489,7 @@ trusted_dirs_remove_old_certs(void)
} SMARTLIST_FOREACH_END(cert);
}
} DIGESTMAP_FOREACH_END;
+#undef DEAD_CERT_LIFETIME
#undef OLD_CERT_LIFETIME
trusted_dirs_flush_certs_to_disk();
@@ -1438,7 +1440,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
/* Find all the running dirservers we know about. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
- int is_trusted;
+ int is_trusted, is_trusted_extrainfo;
int is_overloaded;
tor_addr_t addr;
const routerstatus_t *status = node->rs;
@@ -1453,8 +1455,10 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
if (requireother && router_digest_is_me(node->identity))
continue;
is_trusted = router_digest_is_trusted_dir(node->identity);
+ is_trusted_extrainfo = router_digest_is_trusted_dir_type(
+ node->identity, EXTRAINFO_DIRINFO);
if ((type & EXTRAINFO_DIRINFO) &&
- !router_supports_extrainfo(node->identity, 0))
+ !router_supports_extrainfo(node->identity, is_trusted_extrainfo))
continue;
if ((type & MICRODESC_DIRINFO) && !is_trusted &&
!node->rs->version_supports_microdesc_cache)
@@ -1530,7 +1534,7 @@ dirserver_choose_by_weight(const smartlist_t *servers, double authority_weight)
u64_dbl_t *weights;
const dir_server_t *ds;
- weights = tor_malloc(sizeof(u64_dbl_t) * n);
+ weights = tor_calloc(sizeof(u64_dbl_t), n);
for (i = 0; i < n; ++i) {
ds = smartlist_get(servers, i);
weights[i].dbl = ds->weight;
@@ -2038,7 +2042,7 @@ compute_weighted_bandwidths(const smartlist_t *sl,
Web /= weight_scale;
Wdb /= weight_scale;
- bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl));
+ bandwidths = tor_calloc(sizeof(u64_dbl_t), smartlist_len(sl));
// Cycle through smartlist and total the bandwidth.
SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
@@ -2185,7 +2189,7 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl,
/* First count the total bandwidth weight, and make a list
* of each value. We use UINT64_MAX to indicate "unknown". */
- bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl));
+ bandwidths = tor_calloc(sizeof(u64_dbl_t), smartlist_len(sl));
fast_bits = bitarray_init_zero(smartlist_len(sl));
exit_bits = bitarray_init_zero(smartlist_len(sl));
guard_bits = bitarray_init_zero(smartlist_len(sl));
@@ -3292,6 +3296,14 @@ routerlist_reset_warnings(void)
networkstatus_reset_warnings();
}
+/** Return 1 if the signed descriptor of this router is older than
+ * <b>seconds</b> seconds. Otherwise return 0. */
+MOCK_IMPL(int,
+router_descriptor_is_older_than,(const routerinfo_t *router, int seconds))
+{
+ return router->cache_info.published_on < time(NULL) - seconds;
+}
+
/** Add <b>router</b> to the routerlist, if we don't already have it. Replace
* older entries (if any) with the same key. Note: Callers should not hold
* their pointers to <b>router</b> if this function fails; <b>router</b>
@@ -3461,7 +3473,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
}
if (!in_consensus && from_cache &&
- router->cache_info.published_on < time(NULL) - OLD_ROUTER_DESC_MAX_AGE) {
+ router_descriptor_is_older_than(router, OLD_ROUTER_DESC_MAX_AGE)) {
*msg = "Router descriptor was really old.";
routerinfo_free(router);
return ROUTER_WAS_NOT_NEW;
@@ -3569,9 +3581,9 @@ routerlist_remove_old_cached_routers_with_id(time_t now,
n_extra = n - mdpr;
}
- lifespans = tor_malloc_zero(sizeof(struct duration_idx_t)*n);
- rmv = tor_malloc_zero(sizeof(uint8_t)*n);
- must_keep = tor_malloc_zero(sizeof(uint8_t)*n);
+ lifespans = tor_calloc(sizeof(struct duration_idx_t), n);
+ rmv = tor_calloc(sizeof(uint8_t), n);
+ must_keep = tor_calloc(sizeof(uint8_t), n);
/* Set lifespans to contain the lifespan and index of each server. */
/* Set rmv[i-lo]=1 if we're going to remove a server for being too old. */
for (i = lo; i <= hi; ++i) {
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 6e2f2eaea0..52f2303c7c 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -212,6 +212,9 @@ STATIC int choose_array_element_by_weight(const u64_dbl_t *entries,
int n_entries);
STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
uint64_t *total_out);
+
+MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
+ int seconds));
#endif
#endif
diff --git a/src/test/include.am b/src/test/include.am
index fba439a616..d5163aac2f 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -28,6 +28,7 @@ src_test_test_SOURCES = \
src/test/test_cell_queue.c \
src/test/test_data.c \
src/test/test_dir.c \
+ src/test/test_entrynodes.c \
src/test/test_extorport.c \
src/test/test_introduce.c \
src/test/test_logging.c \
@@ -71,7 +72,8 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
noinst_HEADERS+= \
- src/test/test.h
+ src/test/test.h \
+ src/test/test_descriptors.inc
if CURVE25519_ENABLED
noinst_PROGRAMS+= src/test/test-ntor-cl
diff --git a/src/test/test.c b/src/test/test.c
index 8bce9c91f4..5786f3ca54 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -106,11 +106,18 @@ setup_directory(void)
{
char buf[MAX_PATH];
const char *tmp = buf;
+ const char *extra_backslash = "";
/* If this fails, we're probably screwed anyway */
if (!GetTempPathA(sizeof(buf),buf))
- tmp = "c:\\windows\\temp";
+ tmp = "c:\\windows\\temp\\";
+ if (strcmpend(tmp, "\\")) {
+ /* According to MSDN, it should be impossible for GetTempPath to give us
+ * an answer that doesn't end with \. But let's make sure. */
+ extra_backslash = "\\";
+ }
tor_snprintf(temp_dir, sizeof(temp_dir),
- "%s\\tor_test_%d_%s", tmp, (int)getpid(), rnd32);
+ "%s%stor_test_%d_%s", tmp, extra_backslash,
+ (int)getpid(), rnd32);
r = mkdir(temp_dir);
}
#else
@@ -1306,6 +1313,7 @@ extern struct testcase_t circuitmux_tests[];
extern struct testcase_t cell_queue_tests[];
extern struct testcase_t options_tests[];
extern struct testcase_t socks_tests[];
+extern struct testcase_t entrynodes_tests[];
extern struct testcase_t extorport_tests[];
extern struct testcase_t controller_event_tests[];
extern struct testcase_t logging_tests[];
@@ -1337,6 +1345,7 @@ static struct testgroup_t testgroups[] = {
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
{ "options/", options_tests },
+ { "entrynodes/", entrynodes_tests },
{ "extorport/", extorport_tests },
{ "control/", controller_event_tests },
{ "hs/", hs_tests },
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 94ac4dca13..b35984f761 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -184,7 +184,7 @@ is_private_dir(const char* path)
if (r) {
return 0;
}
-#if !defined (_WIN32) || defined (WINCE)
+#if !defined (_WIN32)
if ((st.st_mode & (S_IFDIR | 0777)) != (S_IFDIR | 0700)) {
return 0;
}
@@ -201,7 +201,7 @@ test_config_check_or_create_data_subdir(void *arg)
char *subpath;
struct stat st;
int r;
-#if !defined (_WIN32) || defined (WINCE)
+#if !defined (_WIN32)
unsigned group_permission;
#endif
(void)arg;
@@ -210,7 +210,7 @@ test_config_check_or_create_data_subdir(void *arg)
datadir = options->DataDirectory = tor_strdup(get_fname("datadir-0"));
subpath = get_datadir_fname(subdir);
-#if defined (_WIN32) && !defined (WINCE)
+#if defined (_WIN32)
tt_int_op(mkdir(options->DataDirectory), ==, 0);
#else
tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0);
@@ -233,7 +233,7 @@ test_config_check_or_create_data_subdir(void *arg)
tt_abort_perror("stat");
}
-#if !defined (_WIN32) || defined (WINCE)
+#if !defined (_WIN32)
group_permission = st.st_mode | 0070;
r = chmod(subpath, group_permission);
@@ -284,7 +284,7 @@ test_config_write_to_data_subdir(void *arg)
datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1"));
filepath = get_datadir_fname2(subdir, fname);
-#if defined (_WIN32) && !defined (WINCE)
+#if defined (_WIN32)
tt_int_op(mkdir(options->DataDirectory), ==, 0);
#else
tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0);
diff --git a/src/test/test_descriptors.inc b/src/test/test_descriptors.inc
new file mode 100644
index 0000000000..ecbccbd43a
--- /dev/null
+++ b/src/test/test_descriptors.inc
@@ -0,0 +1,305 @@
+const char TEST_DESCRIPTORS[] =
+"@uploaded-at 2014-06-08 19:20:11\n"
+"@source \"127.0.0.1\"\n"
+"router test000a 127.0.0.1 5000 0 7000\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n"
+"caches-extra-info\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n"
+"HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n"
+"DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n"
+"O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n"
+"3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"contact auth0@test.test\n"
+"ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n"
+"reject *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n"
+"aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n"
+"eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:11\n"
+"@source \"127.0.0.1\"\n"
+"router test001a 127.0.0.1 5001 0 7001\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint 35DA 711C FC62 F88B C243 DE32 DC0B C28A 3F62 2610\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 9E12278D6CF7608071FE98CE9DCEE48FA264518A\n"
+"caches-extra-info\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAPbyUrorqoXMW4oezqd307ZGxgobqvQs2nb3TdQyWrwsHtJmS3utdrJS\n"
+"xJUZPNHOQ2hrDWW1VvevYqRTGeXGZr9TDZ3+t/gVUttqYRhuzzgEKVAZSsTo5ctO\n"
+"QNHnzJ6Xx/w/trhWqPTeJ7R0TCyAbWW7aE3KaKdwvZilRZp/oRUnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALwOJ7XZHBnjJEuwF3Os6eashNbTH9YnH8TBZBdKgu3iFJYqDslcMIPX\n"
+"gWCJ9apPHyh1+/8OLRWeEYlwoZzgGi0rjm/+BNeOOmJbjfyjk97DuB9/2O5zr1BM\n"
+"CvOHqQSzMD+vz1ebvfM039a2mO8lXruUFPZQaFVxk8371XP2khqhAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"contact auth1@test.test\n"
+"ntor-onion-key t5bI1ksTdigOksMKRHUDwx/34ajEvDN1IpArOxIEWgk=\n"
+"reject *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"KtMW7A/pzu+np6aKJSy6d7drIb4yjz8SPCo+oQNxj2IqNHJir2O2nWu69xy+K0c1\n"
+"RL05KkcDaYzr5hC80FD1H+sTpGYD28SPkQkzPw+0pReSDl93pVXh0rU6Cdcm75FC\n"
+"t0UZzDt4TsMuFB0ZYpM3phKcQPpiDG6aR0LskL/YUvY=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:11\n"
+"@source \"127.0.0.1\"\n"
+"router test004r 127.0.0.1 5004 0 7004\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:10\n"
+"fingerprint CC6A 48BD 52BD 9A2C 6670 5863 AC31 AE17 6E63 8B02\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest B5CC249CEF394B5AFCA0C77FA7D5605615FA487C\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAMze36Hupy7HACcF3TMv5mJuZbx3d3cS0WYLl6vTeChBgpS5CEXq6zIu\n"
+"d31YmtUcxH6fOjDOudhbnXuoh1nH4CP+LocVHAdlGG1giAm7u8yZudVvVJiIqFgQ\n"
+"wVDcWx8LbGCi5P9J/ZPKAIVsSyS7xkOqHjz3VMo/uYLbQCFAwfkdAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAM/qGP365x6bH+ug7rKVy7V5lC9Ff2Jfk0wlTFIzzwn+DMSG6xDvulKe\n"
+"wcIzgGNdQu7qlKlQUif3GPMr0KSS32cRsmoRQJcsm9+lGUK871NyZ8AyrHT+LhyF\n"
+"cs718P0iN5yKF2FikNr727kEANCzvC1l9eP4qF5GGzsNtglbJ7bTAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"ntor-onion-key a9Pavqnx7DFhMWUO0d17qF9Py8+iie4FnxTHaTgfIXY=\n"
+"reject *:25\n"
+"reject *:119\n"
+"reject *:135-139\n"
+"reject *:445\n"
+"reject *:563\n"
+"reject *:1214\n"
+"reject *:4661-4666\n"
+"reject *:6346-6429\n"
+"reject *:6699\n"
+"reject *:6881-6999\n"
+"accept *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"HVW7kjBgEt+Qdvcrq+NQE1F9B8uV9D38KA2Bp6cYHLWCxL6N4GS8JQqbOEtnqaj7\n"
+"Vxrv7uy1Fzb15Zr+1sUVMxNv+LLRfr+JzfETMNYVkYDrNgr1cAAVEQzFWbIziond\n"
+"xMFp64yjEW9/I+82lb5GBZEiKdEd4QqWMmQosoYMTM8=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:12\n"
+"@source \"127.0.0.1\"\n"
+"router test002a 127.0.0.1 5002 0 7002\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint 29C7 BBB6 C437 32D5 BDF1 5671 F5C5 F1FB 6E36 4B47\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 9BB181EA86E0130680C3CC04AD7DE4C341ADC2C7\n"
+"caches-extra-info\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALNH19oF8Ajf+djlH/g7L+enFBf5Wwjmf3bPwNKWZ9G+B+Lg8SpfhZiw\n"
+"rUqi7h21f45BV/dN05dK6leWD8rj1T9kuM9TKBOEZxIWeq7zbXihyu4XPxP4FNTS\n"
+"+0G7BhdP4biALENmeyLhUCZaw5Ic/jFkHT4gV9S0iVZiEDwC9twXAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALeyQGMQBHgTxpO/i30uHjflTm9MNi3ZBNcOKpvBXWYgY42qTqOZ7Uam\n"
+"c5pmZhTLrQ1W8XlGDw8Cl8ktZ0ylodLZyUNajBtJvSFWTb8iwdZsshW6Ahb8TyfI\n"
+"Y7MwTlQ/7xw4mj1NEaui6bwGgEZUs18RTqhDrUc2Mcj1Yf61Rq+7AgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"contact auth2@test.test\n"
+"ntor-onion-key ukR41RjtiZ69KO0SrFTvL0LoZK/ZTT01FQWmCXTCUlE=\n"
+"reject *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"IY2s/RY4tdahrgfGG+vW7lOvpfofoxxSo7guGpSKGxVApiroCQtumoYifnnJ88G2\n"
+"K4IbxwEO8pgO8fnz1mibblUWw2vdDNjCifc1wtXJUE+ONA0UcLRlfQ94GbL8h2PG\n"
+"72z6i1+NN0QahXMk7MUbzI7bOXTJOiO8e2Zjk9vRnxI=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:12\n"
+"@source \"127.0.0.1\"\n"
+"router test006r 127.0.0.1 5006 0 7006\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint 829B 3FAA A42B 605A EB0B F380 8F32 8ED1 73E7 0D25\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 7ECB757002EB9B5838B13AE6F2357A5E585131B8\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALsNBChcLVndlS4HNXL3hxBJVgXctATz6yXcJt3bkDB5cjv7Q9fqN3Ue\n"
+"j3SI1OUBx4YrLcSLD/hELHVilLrrfbaraAFfAsydlRLjTVcMRx5FFlDd0E7TAadc\n"
+"71CkTipNnjwqz1mTRKkEFeepnh/JaFDidY9ER1rMBA5JRyBvqrD9AgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAPgipA8yLj1kqrMlAH7cK7IQEdmqmfNHGXdkYQ+TKtfLh0zeEIvvh9yh\n"
+"k+vKHS+HVoHo3tecB9QjJyDyyJTiETXCupSOY+ebG648JADAvv8v1WiE+KBXtjpl\n"
+"qgDTrDj5CwGuY6cvQdej5yg1UAVlMMZSg3thL3tCYtQbOq66lAlnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"ntor-onion-key q02F3AQsCX7+zXNpfTqBF8O8lusPhRJpQVxOnBvbOwc=\n"
+"reject *:25\n"
+"reject *:119\n"
+"reject *:135-139\n"
+"reject *:445\n"
+"reject *:563\n"
+"reject *:1214\n"
+"reject *:4661-4666\n"
+"reject *:6346-6429\n"
+"reject *:6699\n"
+"reject *:6881-6999\n"
+"accept *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"L1fdgoN/eXgdzIIXO63W4yGoC9lRozMU+T0Fimhd/XFV8qxeUT83Vgf63vxLUHIb\n"
+"D4a80Wj7Pm4y5a766qLGXxlz2FYjCdkp070UpgZneB+VifUlFd/bNAjsiYTstBKM\n"
+"EI2L0mhl9d/7KK8vgtadHdX1z1u7QjyF6ccnzhfqeiY=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:12\n"
+"@source \"127.0.0.1\"\n"
+"router test003r 127.0.0.1 5003 0 7003\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint 71FD 3A35 F705 8020 D595 B711 D52A 9A0A 99BB B467\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 3796BE0A95B699595445DFD3453CA2074E75BCE8\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAL44ctIioIfCYFzMTYNfK5qFAPGGUpsAFmS8pThQEY/tJU14+frJDBrC\n"
+"BkLvBs05Bw7xOUb0f2geiYGowBA6028smiq5HzTO7Kaga8vfV7AnANPX+n9cfHCr\n"
+"/2cMnKkT/GZzpdk0WbUw5Kc/G1ATIPFQHA8gZAi1fsSIDDn3GRV5AgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALlPo5AI1mVTi+194yOSf40caoFlxSTfXt8KjGVa1dO/bpX7L3noOjYg\n"
+"goU4Aqim7BHmBWQDE/tZNTrchFoLQFHi9N4pv/0ND3sY904pzqGpe3FeTuU8P9Jg\n"
+"q2w3MeO3GwG8CJf4FOdSkgi8UKkJhOld4g4kViQbrFLXfdFvnT/zAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"ntor-onion-key qluYCRrsesOTkavCLnNK6H1ToywyDquCyYeP0h/qol4=\n"
+"reject *:25\n"
+"reject *:119\n"
+"reject *:135-139\n"
+"reject *:445\n"
+"reject *:563\n"
+"reject *:1214\n"
+"reject *:4661-4666\n"
+"reject *:6346-6429\n"
+"reject *:6699\n"
+"reject *:6881-6999\n"
+"accept *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"d09K7rW/OpVzoUpfZXJuJW7a+P4pROCOZTgvDUIy/Nv+EAjcYqv95PlJ8cAMqnn3\n"
+"1oQibRmmQwn0OmG5cB8NaZiueaVIRheGzHEM8rndpHn5oFXdFvV7KKjScvfuBbTk\n"
+"RYME8XyawRaqsEZnwirDDlZuiZOjdQs8bbGsko3grJE=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:12\n"
+"@source \"127.0.0.1\"\n"
+"router test005r 127.0.0.1 5005 0 7005\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint EB6E 42ED E6BF 5EE0 19F5 EFC1 53AD 094C 1327 7B76\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest C031EE4E1AE826C1E3C4E21D81C961869E63F5D2\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAMd9Fm4KTSjFDzEABPZ1fwBCC2DNgee6nAmlde8FRbCVfcIHRiJyv9YG\n"
+"h530yUJal3hBfiWwy/SBA4LDz1flNCEwJm81s3waj4T9c676dAOLPcnOcJM5SbaQ\n"
+"hYPDrIZLEZHAk+IoM+avKYYocwCJXwx6WTtsedF0wJBZ9mQAJERJAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAKT7ldhV43S1CgoER/pU0Rigf0NzcSy25DQJrMRQnNmXnL03Dwuv/Iu7\n"
+"dCjgg64odnvSkXHFhkbjGcg8aXikvfbMyZTbsD8NrrP6FS6pfgPgZD9W2TK7QdHI\n"
+"QXwx1IYaaJK4nDUNfJhjrclydEdxmHbO1nLG1aS0ypn/G0EBpOSnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"ntor-onion-key umFmyRPA0dIsi0CFYCbGIPe2+OUkyslTkKKDEohjQQg=\n"
+"reject *:25\n"
+"reject *:119\n"
+"reject *:135-139\n"
+"reject *:445\n"
+"reject *:563\n"
+"reject *:1214\n"
+"reject *:4661-4666\n"
+"reject *:6346-6429\n"
+"reject *:6699\n"
+"reject *:6881-6999\n"
+"accept *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"JiXEbqPgDPWEb9DzCYINRXfmvMIc/IRtvshS8Vmmn7DW67TrTLKCEAnisGo92gMA\n"
+"bhxGb9G5Mxq/8YqGoqdI2Vp6tfKlz/9AmjHzFAo01y42gafXIdr1oUS2RimA8jfF\n"
+"hwfQkbG0FYEsJrH3EUa8sMhcjsEaohK/kgklMR7OgQY=\n"
+"-----END SIGNATURE-----\n"
+"@uploaded-at 2014-06-08 19:20:12\n"
+"@source \"127.0.0.1\"\n"
+"router test007r 127.0.0.1 5007 0 7007\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint DABD 2AAF 8C9F 3B71 7839 9C08 DCD8 CD9D 341D 0002\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest F80104A0DFFB4EB429325D41D1F71E5BF8C6C726\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAL42fYAriR/JeB/9NpVq5Y5EEHca+ugIpaSdRfbopWDtFjXLEk2jmO5A\n"
+"KoAGIkTKDr7e9101x63H+0Nh/7w3uYs/WqTXEH8/1sHwe+0PY2HL0S6qhlOo6X54\n"
+"EfK0nDDBAWFOpyiAMHRk8JVikKb56+FVIhCJgi1RIbLIiUQK2/kxAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAKQj2U5hmB68V6NQBqD8DfIkJjovvM8t6nGfYpkT8ORsROnmgI5mjM38\n"
+"cmh5GIjY9RgoOWolLmsWQ4SXtS0FvrPft1M61UMTSHzlrEeuod5KenV7vGlX2TxT\n"
+"0DoA5TL9yY7CmxCk8CNRCtN/g7WocgIiP4KCIiEZ4VE6LIb6sxUnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"ntor-onion-key 1UBS8rTlL39u9YxRJWhz+GTG1dS15VRi4au1i5qZOyI=\n"
+"reject *:25\n"
+"reject *:119\n"
+"reject *:135-139\n"
+"reject *:445\n"
+"reject *:563\n"
+"reject *:1214\n"
+"reject *:4661-4666\n"
+"reject *:6346-6429\n"
+"reject *:6699\n"
+"reject *:6881-6999\n"
+"accept *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"m7xHh+XPdLN+qcMLz1dBAEAmcdCFrtdseMHCc0FyAP2kXdayxqe3o2IOOHN++bTH\n"
+"Y5iHsZembsIJJ+D/d0YEKWKh42TUWCXBu0Gbfc4OcNuR6PFlTWO2wk7rDT3HOiFr\n"
+"pe3wJqZYkLxlBDamROAlMMRe71iag89H/4EulC18opw=\n"
+"-----END SIGNATURE-----\n";
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
new file mode 100644
index 0000000000..ede93fb43a
--- /dev/null
+++ b/src/test/test_entrynodes.c
@@ -0,0 +1,636 @@
+/* Copyright (c) 2014, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#define STATEFILE_PRIVATE
+#define ENTRYNODES_PRIVATE
+#define ROUTERLIST_PRIVATE
+
+#include "or.h"
+#include "test.h"
+#include "entrynodes.h"
+#include "routerparse.h"
+#include "nodelist.h"
+#include "util.h"
+#include "routerlist.h"
+#include "routerset.h"
+#include "statefile.h"
+#include "config.h"
+
+#include "test_descriptors.inc"
+
+/* TODO:
+ * choose_random_entry() test with state set.
+ *
+ * parse_state() tests with more than one guards.
+ *
+ * More tests for set_from_config(): Multiple nodes, use fingerprints,
+ * use country codes.
+ */
+
+/** Dummy Tor state used in unittests. */
+static or_state_t *dummy_state = NULL;
+static or_state_t *
+get_or_state_replacement(void)
+{
+ return dummy_state;
+}
+
+/* NOP replacement for router_descriptor_is_older_than() */
+static int
+router_descriptor_is_older_than_replacement(const routerinfo_t *router,
+ int seconds)
+{
+ (void) router;
+ (void) seconds;
+ return 0;
+}
+
+/* Number of descriptors contained in test_descriptors.txt. */
+#define NUMBER_OF_DESCRIPTORS 8
+
+/** Parse a file containing router descriptors and load them to our
+ routerlist. This function is used to setup an artificial network
+ so that we can conduct entry guard tests. */
+static void
+setup_fake_routerlist(void)
+{
+ int retval;
+ routerlist_t *our_routerlist = NULL;
+ smartlist_t *our_nodelist = NULL;
+
+ /* Read the file that contains our test descriptors. */
+
+ /* We need to mock this function otherwise the descriptors will not
+ accepted as they are too old. */
+ MOCK(router_descriptor_is_older_than,
+ router_descriptor_is_older_than_replacement);
+
+ /* Load all the test descriptors to the routerlist. */
+ retval = router_load_routers_from_string(TEST_DESCRIPTORS,
+ NULL, SAVED_IN_JOURNAL,
+ NULL, 0, NULL);
+ tt_int_op(retval, ==, NUMBER_OF_DESCRIPTORS);
+
+ /* Sanity checking of routerlist and nodelist. */
+ our_routerlist = router_get_routerlist();
+ tt_int_op(smartlist_len(our_routerlist->routers), ==, NUMBER_OF_DESCRIPTORS);
+ routerlist_assert_ok(our_routerlist);
+
+ our_nodelist = nodelist_get_list();
+ tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS);
+
+ /* Mark all routers as non-guards but up and running! */
+ SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) {
+ node->is_running = 1;
+ node->is_valid = 1;
+ node->is_possible_guard = 0;
+ } SMARTLIST_FOREACH_END(node);
+
+ done:
+ UNMOCK(router_descriptor_is_older_than);
+}
+
+/* Unittest cleanup function: Cleanup the fake network. */
+static int
+fake_network_cleanup(const struct testcase_t *testcase, void *ptr)
+{
+ (void) testcase;
+ (void) ptr;
+
+ routerlist_free_all();
+ nodelist_free_all();
+ entry_guards_free_all();
+ or_state_free(dummy_state);
+
+ return 1; /* NOP */
+}
+
+/* Unittest setup function: Setup a fake network. */
+static void *
+fake_network_setup(const struct testcase_t *testcase)
+{
+ (void) testcase;
+
+ /* Setup fake state */
+ dummy_state = tor_malloc_zero(sizeof(or_state_t));
+ MOCK(get_or_state,
+ get_or_state_replacement);
+
+ /* Setup fake routerlist. */
+ setup_fake_routerlist();
+
+ /* Return anything but NULL (it's interpreted as test fail) */
+ return dummy_state;
+}
+
+/** Test choose_random_entry() with none of our routers being guard nodes. */
+static void
+test_choose_random_entry_no_guards(void *arg)
+{
+ const node_t *chosen_entry = NULL;
+
+ (void) arg;
+
+ /* Try to pick an entry even though none of our routers are guards. */
+ chosen_entry = choose_random_entry(NULL);
+
+ /* Unintuitively, we actually pick a random node as our entry,
+ because router_choose_random_node() relaxes its constraints if it
+ can't find a proper entry guard. */
+ test_assert(chosen_entry);
+
+ done:
+ ;
+}
+
+/** Test choose_random_entry() with only one of our routers being a
+ guard node. */
+static void
+test_choose_random_entry_one_possible_guard(void *arg)
+{
+ const node_t *chosen_entry = NULL;
+ node_t *the_guard = NULL;
+ smartlist_t *our_nodelist = NULL;
+
+ (void) arg;
+
+ /* Set one of the nodes to be a guard. */
+ our_nodelist = nodelist_get_list();
+ the_guard = smartlist_get(our_nodelist, 4); /* chosen by fair dice roll */
+ the_guard->is_possible_guard = 1;
+
+ /* Pick an entry. Make sure we pick the node we marked as guard. */
+ chosen_entry = choose_random_entry(NULL);
+ tt_ptr_op(chosen_entry, ==, the_guard);
+
+ done:
+ ;
+}
+
+/** Helper to conduct tests for populate_live_entry_guards().
+
+ This test adds some entry guards to our list, and then tests
+ populate_live_entry_guards() to mke sure it filters them correctly.
+
+ <b>num_needed</b> is the number of guard nodes we support. It's
+ configurable to make sure we function properly with 1 or 3 guard
+ nodes configured.
+*/
+static void
+populate_live_entry_guards_test_helper(int num_needed)
+{
+ smartlist_t *our_nodelist = NULL;
+ smartlist_t *live_entry_guards = smartlist_new();
+ const smartlist_t *all_entry_guards = get_entry_guards();
+ or_options_t *options = get_options_mutable();
+ int retval;
+
+ /* Set NumEntryGuards to the provided number. */
+ options->NumEntryGuards = num_needed;
+ tt_int_op(num_needed, ==, decide_num_guards(options, 0));
+
+ /* The global entry guards smartlist should be empty now. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, 0);
+
+ /* Walk the nodelist and add all nodes as entry guards. */
+ our_nodelist = nodelist_get_list();
+ tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS);
+
+ SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
+ const node_t *node_tmp;
+ node_tmp = add_an_entry_guard(node, 0, 1, 0, 0);
+ test_assert(node_tmp);
+ } SMARTLIST_FOREACH_END(node);
+
+ /* Make sure the nodes were added as entry guards. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, NUMBER_OF_DESCRIPTORS);
+
+ /* Ensure that all the possible entry guards are enough to satisfy us. */
+ tt_int_op(smartlist_len(all_entry_guards), >=, num_needed);
+
+ /* Walk the entry guard list for some sanity checking */
+ SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) {
+ /* Since we called add_an_entry_guard() with 'for_discovery' being
+ False, all guards should have made_contact enabled. */
+ tt_int_op(entry->made_contact, ==, 1);
+
+ /* Since we don't have a routerstatus, all of the entry guards are
+ not directory servers. */
+ tt_int_op(entry->is_dir_cache, ==, 0);
+ } SMARTLIST_FOREACH_END(entry);
+
+ /* First, try to get some fast guards. This should fail. */
+ retval = populate_live_entry_guards(live_entry_guards,
+ all_entry_guards,
+ NULL,
+ NO_DIRINFO, /* Don't care about DIRINFO*/
+ 0, 0,
+ 1); /* We want fast guard! */
+ tt_int_op(retval, ==, 0);
+ tt_int_op(smartlist_len(live_entry_guards), ==, 0);
+
+ /* Now try to get some stable guards. This should fail too. */
+ retval = populate_live_entry_guards(live_entry_guards,
+ all_entry_guards,
+ NULL,
+ NO_DIRINFO,
+ 0,
+ 1, /* We want stable guard! */
+ 0);
+ tt_int_op(retval, ==, 0);
+ tt_int_op(smartlist_len(live_entry_guards), ==, 0);
+
+ /* Now try to get any guard we can find. This should succeed. */
+ retval = populate_live_entry_guards(live_entry_guards,
+ all_entry_guards,
+ NULL,
+ NO_DIRINFO,
+ 0, 0, 0); /* No restrictions! */
+
+ /* Since we had more than enough guards in 'all_entry_guards', we
+ should have added 'num_needed' of them to live_entry_guards.
+ 'retval' should be 1 since we now have enough live entry guards
+ to pick one. */
+ tt_int_op(retval, ==, 1);
+ tt_int_op(smartlist_len(live_entry_guards), ==, num_needed);
+
+ done:
+ smartlist_free(live_entry_guards);
+}
+
+/* Test populate_live_entry_guards() for 1 guard node. */
+static void
+test_populate_live_entry_guards_1guard(void *arg)
+{
+ (void) arg;
+
+ populate_live_entry_guards_test_helper(1);
+}
+
+/* Test populate_live_entry_guards() for 3 guard nodes. */
+static void
+test_populate_live_entry_guards_3guards(void *arg)
+{
+ (void) arg;
+
+ populate_live_entry_guards_test_helper(3);
+}
+
+/** Append some EntryGuard lines to the Tor state at <b>state</b>.
+
+ <b>entry_guard_lines</b> is a smartlist containing 2-tuple
+ smartlists that carry the key and values of the statefile.
+ As an example:
+ entry_guard_lines =
+ (("EntryGuard", "name 67E72FF33D7D41BF11C569646A0A7B4B188340DF DirCache"),
+ ("EntryGuardDownSince", "2014-06-07 16:02:46 2014-06-07 16:02:46"))
+*/
+static void
+state_insert_entry_guard_helper(or_state_t *state,
+ smartlist_t *entry_guard_lines)
+{
+ config_line_t **next, *line;
+
+ next = &state->EntryGuards;
+ *next = NULL;
+
+ /* Loop over all the state lines in the smartlist */
+ SMARTLIST_FOREACH_BEGIN(entry_guard_lines, const smartlist_t *,state_lines) {
+ /* Get key and value for each line */
+ const char *state_key = smartlist_get(state_lines, 0);
+ const char *state_value = smartlist_get(state_lines, 1);
+
+ *next = line = tor_malloc_zero(sizeof(config_line_t));
+ line->key = tor_strdup(state_key);
+ tor_asprintf(&line->value, "%s", state_value);
+ next = &(line->next);
+ } SMARTLIST_FOREACH_END(state_lines);
+}
+
+/** Free memory occupied by <b>entry_guard_lines</b>. */
+static void
+state_lines_free(smartlist_t *entry_guard_lines)
+{
+ SMARTLIST_FOREACH_BEGIN(entry_guard_lines, smartlist_t *, state_lines) {
+ char *state_key = smartlist_get(state_lines, 0);
+ char *state_value = smartlist_get(state_lines, 1);
+
+ tor_free(state_key);
+ tor_free(state_value);
+ smartlist_free(state_lines);
+ } SMARTLIST_FOREACH_END(state_lines);
+
+ smartlist_free(entry_guard_lines);
+}
+
+/* Tests entry_guards_parse_state(). It creates a fake Tor state with
+ a saved entry guard and makes sure that Tor can parse it and
+ creates the right entry node out of it.
+*/
+static void
+test_entry_guards_parse_state_simple(void *arg)
+{
+ or_state_t *state = or_state_new();
+ const smartlist_t *all_entry_guards = get_entry_guards();
+ smartlist_t *entry_state_lines = smartlist_new();
+ char *msg = NULL;
+ int retval;
+
+ /* Details of our fake guard node */
+ const char *nickname = "hagbard";
+ const char *fpr = "B29D536DD1752D542E1FBB3C9CE4449D51298212";
+ const char *tor_version = "0.2.5.3-alpha-dev";
+ const char *added_at = "2014-05-22 02:40:47";
+ const char *unlisted_since = "2014-06-08 16:16:50";
+
+ (void) arg;
+
+ /* The global entry guards smartlist should be empty now. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, 0);
+
+ { /* Prepare the state entry */
+
+ /* Prepare the smartlist to hold the key/value of each line */
+ smartlist_t *state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuard");
+ smartlist_add_asprintf(state_line, "%s %s %s", nickname, fpr, "DirCache");
+ smartlist_add(entry_state_lines, state_line);
+
+ state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuardAddedBy");
+ smartlist_add_asprintf(state_line, "%s %s %s", fpr, tor_version, added_at);
+ smartlist_add(entry_state_lines, state_line);
+
+ state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince");
+ smartlist_add_asprintf(state_line, "%s", unlisted_since);
+ smartlist_add(entry_state_lines, state_line);
+ }
+
+ /* Inject our lines in the state */
+ state_insert_entry_guard_helper(state, entry_state_lines);
+
+ /* Parse state */
+ retval = entry_guards_parse_state(state, 1, &msg);
+ tt_int_op(retval, >=, 0);
+
+ /* Test that the guard was registered.
+ We need to re-get the entry guard list since its pointer was
+ overwritten in entry_guards_parse_state(). */
+ all_entry_guards = get_entry_guards();
+ tt_int_op(smartlist_len(all_entry_guards), ==, 1);
+
+ { /* Test the entry guard structure */
+ char hex_digest[1024];
+ char str_time[1024];
+
+ const entry_guard_t *e = smartlist_get(all_entry_guards, 0);
+ tt_str_op(e->nickname, ==, nickname); /* Verify nickname */
+
+ base16_encode(hex_digest, sizeof(hex_digest),
+ e->identity, DIGEST_LEN);
+ tt_str_op(hex_digest, ==, fpr); /* Verify fingerprint */
+
+ tt_assert(e->is_dir_cache); /* Verify dirness */
+
+ tt_str_op(e->chosen_by_version, ==, tor_version); /* Verify tor version */
+
+ tt_assert(e->made_contact); /* All saved guards have been contacted */
+
+ tt_assert(e->bad_since); /* Verify bad_since timestamp */
+ format_iso_time(str_time, e->bad_since);
+ tt_str_op(str_time, ==, unlisted_since);
+
+ /* The rest should be unset */
+ tt_assert(!e->unreachable_since);
+ tt_assert(!e->can_retry);
+ tt_assert(!e->path_bias_noticed);
+ tt_assert(!e->path_bias_warned);
+ tt_assert(!e->path_bias_extreme);
+ tt_assert(!e->path_bias_disabled);
+ tt_assert(!e->path_bias_use_noticed);
+ tt_assert(!e->path_bias_use_extreme);
+ tt_assert(!e->last_attempted);
+ }
+
+ done:
+ state_lines_free(entry_state_lines);
+ or_state_free(state);
+}
+
+/** Similar to test_entry_guards_parse_state_simple() but aims to test
+ the PathBias-related details of the entry guard. */
+static void
+test_entry_guards_parse_state_pathbias(void *arg)
+{
+ or_state_t *state = or_state_new();
+ const smartlist_t *all_entry_guards = get_entry_guards();
+ char *msg = NULL;
+ int retval;
+ smartlist_t *entry_state_lines = smartlist_new();
+
+ /* Path bias details of the fake guard */
+ const double circ_attempts = 9;
+ const double circ_successes = 8;
+ const double successful_closed = 4;
+ const double collapsed = 2;
+ const double unusable = 0;
+ const double timeouts = 1;
+
+ (void) arg;
+
+ /* The global entry guards smartlist should be empty now. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, 0);
+
+ { /* Prepare the state entry */
+
+ /* Prepare the smartlist to hold the key/value of each line */
+ smartlist_t *state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuard");
+ smartlist_add_asprintf(state_line,
+ "givethanks B29D536DD1752D542E1FBB3C9CE4449D51298212 NoDirCache");
+ smartlist_add(entry_state_lines, state_line);
+
+ state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuardAddedBy");
+ smartlist_add_asprintf(state_line,
+ "B29D536DD1752D542E1FBB3C9CE4449D51298212 0.2.5.3-alpha-dev "
+ "2014-05-22 02:40:47");
+ smartlist_add(entry_state_lines, state_line);
+
+ state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince");
+ smartlist_add_asprintf(state_line, "2014-06-08 16:16:50");
+ smartlist_add(entry_state_lines, state_line);
+
+ state_line = smartlist_new();
+ smartlist_add_asprintf(state_line, "EntryGuardPathBias");
+ smartlist_add_asprintf(state_line, "%f %f %f %f %f %f",
+ circ_attempts, circ_successes, successful_closed,
+ collapsed, unusable, timeouts);
+ smartlist_add(entry_state_lines, state_line);
+ }
+
+ /* Inject our lines in the state */
+ state_insert_entry_guard_helper(state, entry_state_lines);
+
+ /* Parse state */
+ retval = entry_guards_parse_state(state, 1, &msg);
+ tt_int_op(retval, >=, 0);
+
+ /* Test that the guard was registered */
+ all_entry_guards = get_entry_guards();
+ tt_int_op(smartlist_len(all_entry_guards), ==, 1);
+
+ { /* Test the path bias of this guard */
+ const entry_guard_t *e = smartlist_get(all_entry_guards, 0);
+
+ tt_assert(!e->is_dir_cache);
+ tt_assert(!e->can_retry);
+
+ /* XXX tt_double_op doesn't support equality. Cast to int for now. */
+ tt_int_op((int)e->circ_attempts, ==, (int)circ_attempts);
+ tt_int_op((int)e->circ_successes, ==, (int)circ_successes);
+ tt_int_op((int)e->successful_circuits_closed, ==, (int)successful_closed);
+ tt_int_op((int)e->timeouts, ==, (int)timeouts);
+ tt_int_op((int)e->collapsed_circuits, ==, (int)collapsed);
+ tt_int_op((int)e->unusable_circuits, ==, (int)unusable);
+ }
+
+ done:
+ or_state_free(state);
+ state_lines_free(entry_state_lines);
+}
+
+/* Simple test of entry_guards_set_from_config() by specifying a
+ particular EntryNode and making sure it gets picked. */
+static void
+test_entry_guards_set_from_config(void *arg)
+{
+ or_options_t *options = get_options_mutable();
+ const smartlist_t *all_entry_guards = get_entry_guards();
+ const char *entrynodes_str = "test003r";
+ const node_t *chosen_entry = NULL;
+ int retval;
+
+ (void) arg;
+
+ /* Prase EntryNodes as a routerset. */
+ options->EntryNodes = routerset_new();
+ retval = routerset_parse(options->EntryNodes,
+ entrynodes_str,
+ "test_entrynodes");
+ tt_int_op(retval, >=, 0);
+
+ /* Read nodes from EntryNodes */
+ entry_guards_set_from_config(options);
+
+ /* Test that only one guard was added. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, 1);
+
+ /* Make sure it was the guard we specified. */
+ chosen_entry = choose_random_entry(NULL);
+ tt_str_op(chosen_entry->ri->nickname, ==, entrynodes_str);
+
+ done:
+ routerset_free(options->EntryNodes);
+}
+
+/** XXX Do some tests that entry_is_live() */
+static void
+test_entry_is_live(void *arg)
+{
+ smartlist_t *our_nodelist = NULL;
+ const smartlist_t *all_entry_guards = get_entry_guards();
+ const node_t *test_node = NULL;
+ const entry_guard_t *test_entry = NULL;
+ const char *msg;
+ int which_node;
+
+ (void) arg;
+
+ /* The global entry guards smartlist should be empty now. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, 0);
+
+ /* Walk the nodelist and add all nodes as entry guards. */
+ our_nodelist = nodelist_get_list();
+ tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS);
+
+ SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
+ const node_t *node_tmp;
+ node_tmp = add_an_entry_guard(node, 0, 1, 0, 0);
+ test_assert(node_tmp);
+
+ tt_int_op(node->is_stable, ==, 0);
+ tt_int_op(node->is_fast, ==, 0);
+ } SMARTLIST_FOREACH_END(node);
+
+ /* Make sure the nodes were added as entry guards. */
+ tt_int_op(smartlist_len(all_entry_guards), ==, NUMBER_OF_DESCRIPTORS);
+
+ /* Now get a random test entry that we will use for this unit test. */
+ which_node = 3; /* (chosen by fair dice roll) */
+ test_entry = smartlist_get(all_entry_guards, which_node);
+
+ /* Let's do some entry_is_live() tests! */
+
+ /* Require the node to be stable, but it's not. Should fail.
+ Also enable 'assume_reachable' because why not. */
+ test_node = entry_is_live(test_entry,
+ ENTRY_NEED_UPTIME | ENTRY_ASSUME_REACHABLE,
+ &msg);
+ test_assert(!test_node);
+
+ /* Require the node to be fast, but it's not. Should fail. */
+ test_node = entry_is_live(test_entry,
+ ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE,
+ &msg);
+ test_assert(!test_node);
+
+ /* Don't impose any restrictions on the node. Should succeed. */
+ test_node = entry_is_live(test_entry, 0, &msg);
+ test_assert(test_node);
+ tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity));
+
+ /* Require descriptor for this node. It has one so it should succeed. */
+ test_node = entry_is_live(test_entry, ENTRY_NEED_DESCRIPTOR, &msg);
+ test_assert(test_node);
+ tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity));
+
+ done:
+ ; /* XXX */
+}
+
+static const struct testcase_setup_t fake_network = {
+ fake_network_setup, fake_network_cleanup
+};
+
+struct testcase_t entrynodes_tests[] = {
+ { "choose_random_entry_no_guards", test_choose_random_entry_no_guards,
+ TT_FORK, &fake_network, NULL },
+ { "choose_random_entry_one_possibleguard",
+ test_choose_random_entry_one_possible_guard,
+ TT_FORK, &fake_network, NULL },
+ { "populate_live_entry_guards_1guard",
+ test_populate_live_entry_guards_1guard,
+ TT_FORK, &fake_network, NULL },
+ { "populate_live_entry_guards_3guards",
+ test_populate_live_entry_guards_3guards,
+ TT_FORK, &fake_network, NULL },
+ { "entry_guards_parse_state_simple",
+ test_entry_guards_parse_state_simple,
+ TT_FORK, &fake_network, NULL },
+ { "entry_guards_parse_state_pathbias",
+ test_entry_guards_parse_state_pathbias,
+ TT_FORK, &fake_network, NULL },
+ { "entry_guards_set_from_config",
+ test_entry_guards_set_from_config,
+ TT_FORK, &fake_network, NULL },
+ { "entry_is_live",
+ test_entry_is_live,
+ TT_FORK, &fake_network, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_logging.c b/src/test/test_logging.c
index 7e558f83b1..9f57000bea 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -89,7 +89,7 @@ test_sigsafe_err(void *arg)
init_logging();
mark_logs_temp();
- add_file_log(&include_bug, fn);
+ add_file_log(&include_bug, fn, 0);
tor_log_update_sigsafe_err_fds();
close_temp_logs();
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index f71627df1e..f55c059580 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -194,7 +194,7 @@ test_pt_protocol(void)
managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
mp->conf_state = PT_PROTO_LAUNCHED;
mp->transports = smartlist_new();
- mp->argv = tor_malloc_zero(sizeof(char*)*2);
+ mp->argv = tor_calloc(sizeof(char *), 2);
mp->argv[0] = tor_strdup("<testcase>");
/* various wrong protocol runs: */
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 151ec69127..c32fadd119 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1383,12 +1383,6 @@ test_util_threads(void)
tv.tv_sec=0;
tv.tv_usec=100*1000;
#endif
-#ifndef TOR_IS_MULTITHREADED
- /* Skip this test if we aren't threading. We should be threading most
- * everywhere by now. */
- if (1)
- return;
-#endif
thread_test_mutex_ = tor_mutex_new();
thread_test_start1_ = tor_mutex_new();
thread_test_start2_ = tor_mutex_new();
@@ -1493,7 +1487,7 @@ test_util_gzip(void)
/* Check whether we can uncompress concatenated, compressed strings. */
tor_free(buf3);
- buf2 = tor_realloc(buf2, len1*2);
+ buf2 = tor_reallocarray(buf2, len1, 2);
memcpy(buf2+len1, buf2, len1);
test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
ZLIB_METHOD, 1, LOG_INFO));
@@ -2391,6 +2385,54 @@ test_util_parent_dir(void *ptr)
tor_free(cp);
}
+static void
+test_util_ftruncate(void *ptr)
+{
+ char *buf = NULL;
+ const char *fname;
+ int fd = -1;
+ const char *message = "Hello world";
+ const char *message2 = "Hola mundo";
+ struct stat st;
+
+ (void) ptr;
+
+ fname = get_fname("ftruncate");
+
+ fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
+ tt_int_op(fd, >=, 0);
+
+ /* Make the file be there. */
+ tt_int_op(strlen(message), ==, write_all(fd, message, strlen(message), 0));
+ tt_int_op((int)tor_fd_getpos(fd), ==, strlen(message));
+ tt_int_op(0, ==, fstat(fd, &st));
+ tt_int_op((int)st.st_size, ==, strlen(message));
+
+ /* Truncate and see if it got truncated */
+ tt_int_op(0, ==, tor_ftruncate(fd));
+ tt_int_op((int)tor_fd_getpos(fd), ==, 0);
+ tt_int_op(0, ==, fstat(fd, &st));
+ tt_int_op((int)st.st_size, ==, 0);
+
+ /* Replace, and see if it got replaced */
+ tt_int_op(strlen(message2), ==,
+ write_all(fd, message2, strlen(message2), 0));
+ tt_int_op((int)tor_fd_getpos(fd), ==, strlen(message2));
+ tt_int_op(0, ==, fstat(fd, &st));
+ tt_int_op((int)st.st_size, ==, strlen(message2));
+
+ close(fd);
+ fd = -1;
+
+ buf = read_file_to_str(fname, 0, NULL);
+ tt_str_op(message2, ==, buf);
+
+ done:
+ if (fd >= 0)
+ close(fd);
+ tor_free(buf);
+}
+
#ifdef _WIN32
static void
test_util_load_win_lib(void *ptr)
@@ -2453,8 +2495,9 @@ test_util_exit_status(void *ptr)
#endif
#ifndef _WIN32
-/** Check that fgets waits until a full line, and not return a partial line, on
- * a EAGAIN with a non-blocking pipe */
+/* Check that fgets with a non-blocking pipe returns partial lines and sets
+ * EAGAIN, returns full lines and sets no error, and returns NULL on EOF and
+ * sets no error */
static void
test_util_fgets_eagain(void *ptr)
{
@@ -2463,17 +2506,19 @@ test_util_fgets_eagain(void *ptr)
ssize_t retlen;
char *retptr;
FILE *test_stream = NULL;
- char buf[10];
+ char buf[4] = { 0 };
(void)ptr;
+ errno = 0;
+
/* Set up a pipe to test on */
retval = pipe(test_pipe);
- tt_int_op(retval, >=, 0);
+ 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);
+ tt_int_op(retval, ==, 0);
/* Open it as a stdio stream */
test_stream = fdopen(test_pipe[0], "r");
@@ -2483,51 +2528,69 @@ test_util_fgets_eagain(void *ptr)
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);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "A");
+ errno = 0;
/* 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_int_op(errno, ==, 0);
tt_ptr_op(retptr, ==, buf);
- tt_str_op(buf, ==, "AB\n");
+ tt_str_op(buf, ==, "B\n");
+ errno = 0;
/* 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_int_op(errno, ==, 0);
tt_ptr_op(retptr, ==, buf);
tt_str_op(buf, ==, "CD\n");
+ errno = 0;
/* 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);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "E");
+ errno = 0;
/* 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_int_op(errno, ==, 0);
tt_ptr_op(retptr, ==, buf);
- tt_str_op(buf, ==, "EF\n");
+ tt_str_op(buf, ==, "F\n");
+ errno = 0;
/* 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);
+ test_pipe[1] = -1;
retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_int_op(errno, ==, 0);
tt_ptr_op(retptr, ==, buf);
tt_str_op(buf, ==, "GH");
+ errno = 0;
/* Check for EOF */
retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_int_op(errno, ==, 0);
tt_ptr_op(retptr, ==, NULL);
- tt_int_op(feof(test_stream), >, 0);
+ retval = feof(test_stream);
+ tt_int_op(retval, !=, 0);
+ errno = 0;
+
+ /* Check that buf is unchanged according to C99 and C11 */
+ tt_str_op(buf, ==, "GH");
done:
if (test_stream != NULL)
@@ -3783,12 +3846,13 @@ struct testcase_t util_tests[] = {
UTIL_TEST(asprintf, 0),
UTIL_TEST(listdir, 0),
UTIL_TEST(parent_dir, 0),
+ UTIL_TEST(ftruncate, 0),
#ifdef _WIN32
UTIL_TEST(load_win_lib, 0),
#endif
#ifndef _WIN32
UTIL_TEST(exit_status, 0),
- UTIL_TEST(fgets_eagain, TT_SKIP),
+ UTIL_TEST(fgets_eagain, 0),
#endif
UTIL_TEST(spawn_background_ok, 0),
UTIL_TEST(spawn_background_fail, 0),
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 8c2472c323..030341af34 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -14,8 +14,6 @@
/* Define to 1 if you have the <ctype.h> header file. */
#define HAVE_CTYPE_H
-#define ENABLE_THREADS
-
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H
@@ -86,18 +84,11 @@
#define HAVE_STRING_H
/* Define to 1 if you have the `strlcat' function. */
-#if defined (WINCE)
-#define HAVE_STRLCAT
-#else
#undef HAVE_STRLCAT
-#endif
/* Define to 1 if you have the `strlcpy' function. */
-#if defined (WINCE)
-#define HAVE_STRLCPY
-#else
#undef HAVE_STRLCPY
-#endif
+
/* Define to 1 if you have the `strptime' function. */
#undef HAVE_STRPTIME
@@ -241,7 +232,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.2.5.6-alpha"
+#define VERSION "0.2.6.0-alpha-dev"