summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Makefile.am4
-rw-r--r--src/common/compat.c32
-rw-r--r--src/common/compat.h23
-rw-r--r--src/common/compat_libevent.c2
-rw-r--r--src/common/compat_libevent.h4
-rw-r--r--src/common/container.c2
-rw-r--r--src/common/crypto.c12
-rw-r--r--src/common/crypto.h1
-rw-r--r--src/common/log.c2
-rw-r--r--src/common/procmon.c336
-rw-r--r--src/common/procmon.h30
-rw-r--r--src/common/torlog.h1
-rw-r--r--src/common/util.c28
-rw-r--r--src/common/util.h4
-rw-r--r--src/or/buffers.c8
-rw-r--r--src/or/buffers.h4
-rw-r--r--src/or/circuitbuild.c9
-rw-r--r--src/or/circuituse.c11
-rw-r--r--src/or/command.c1
-rw-r--r--src/or/config.c58
-rw-r--r--src/or/connection.c98
-rw-r--r--src/or/control.c142
-rw-r--r--src/or/control.h4
-rw-r--r--src/or/cpuworker.c10
-rw-r--r--src/or/directory.c7
-rw-r--r--src/or/dirvote.c3
-rw-r--r--src/or/dns.c9
-rw-r--r--src/or/dnsserv.c2
-rw-r--r--src/or/eventdns.c7
-rw-r--r--src/or/eventdns.h2
-rw-r--r--src/or/main.c74
-rw-r--r--src/or/or.h17
-rw-r--r--src/or/rendclient.c11
-rw-r--r--src/or/rendcommon.c22
-rw-r--r--src/or/rendcommon.h3
-rw-r--r--src/or/router.c29
-rw-r--r--src/or/router.h2
-rw-r--r--src/or/routerparse.c22
-rw-r--r--src/test/test_crypto.c4
-rw-r--r--src/tools/tor-resolve.c4
40 files changed, 848 insertions, 196 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 2d009bd4fa..6952591d67 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -12,11 +12,11 @@ libor_extra_source=
endif
libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
- memarea.c di_ops.c util_codedigest.c $(libor_extra_source)
+ memarea.c di_ops.c procmon.c util_codedigest.c $(libor_extra_source)
libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
libor_event_a_SOURCES = compat_libevent.c
-noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h
+noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h procmon.h
common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
if test "@SHA1SUM@" != none; then \
diff --git a/src/common/compat.c b/src/common/compat.c
index fc066da681..9377959eb4 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -841,7 +841,7 @@ socket_accounting_unlock(void)
* Windows, where close()ing a socket doesn't work. Returns 0 on success, -1
* on failure. */
int
-tor_close_socket(int s)
+tor_close_socket(tor_socket_t s)
{
int r = 0;
@@ -894,8 +894,10 @@ tor_close_socket(int s)
/** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is
* now an open socket. */
static INLINE void
-mark_socket_open(int s)
+mark_socket_open(tor_socket_t s)
{
+ /* XXXX This bitarray business will NOT work on windows: sockets aren't
+ small ints there. */
if (s > max_socket) {
if (max_socket == -1) {
open_sockets = bitarray_init_zero(s+128);
@@ -917,11 +919,11 @@ mark_socket_open(int s)
/** @} */
/** As socket(), but counts the number of open sockets. */
-int
+tor_socket_t
tor_open_socket(int domain, int type, int protocol)
{
- int s = socket(domain, type, protocol);
- if (s >= 0) {
+ tor_socket_t s = socket(domain, type, protocol);
+ if (SOCKET_OK(s)) {
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -931,11 +933,11 @@ tor_open_socket(int domain, int type, int protocol)
}
/** As socket(), but counts the number of open sockets. */
-int
+tor_socket_t
tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
{
- int s = accept(sockfd, addr, len);
- if (s >= 0) {
+ tor_socket_t s = accept(sockfd, addr, len);
+ if (SOCKET_OK(s)) {
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -958,7 +960,7 @@ get_n_open_sockets(void)
/** Turn <b>socket</b> into a nonblocking socket.
*/
void
-set_socket_nonblocking(int socket)
+set_socket_nonblocking(tor_socket_t socket)
{
#if defined(MS_WINDOWS)
unsigned long nonblocking = 1;
@@ -986,7 +988,7 @@ set_socket_nonblocking(int socket)
**/
/* It would be nicer just to set errno, but that won't work for windows. */
int
-tor_socketpair(int family, int type, int protocol, int fd[2])
+tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
{
//don't use win32 socketpairs (they are always bad)
#if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
@@ -1011,9 +1013,9 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
* for now, and really, when localhost is down sometimes, we
* have other problems too.
*/
- int listener = -1;
- int connector = -1;
- int acceptor = -1;
+ tor_socket_t listener = -1;
+ tor_socket_t connector = -1;
+ tor_socket_t acceptor = -1;
struct sockaddr_in listen_addr;
struct sockaddr_in connect_addr;
int size;
@@ -2577,11 +2579,11 @@ in_main_thread(void)
*/
#if defined(MS_WINDOWS)
int
-tor_socket_errno(int sock)
+tor_socket_errno(tor_socket_t sock)
{
int optval, optvallen=sizeof(optval);
int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK && sock >= 0) {
+ if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
return err;
if (optval)
diff --git a/src/common/compat.h b/src/common/compat.h
index eff51ab30c..eb79b04449 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -390,15 +390,24 @@ int tor_fd_seekend(int fd);
typedef int socklen_t;
#endif
-int tor_close_socket(int s);
-int tor_open_socket(int domain, int type, int protocol);
-int tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len);
+#ifdef MS_WINDOWS
+#define tor_socket_t intptr_t
+#define SOCKET_OK(s) ((s) != INVALID_SOCKET)
+#else
+#define tor_socket_t int
+#define SOCKET_OK(s) ((s) >= 0)
+#endif
+
+int tor_close_socket(tor_socket_t s);
+tor_socket_t tor_open_socket(int domain, int type, int protocol);
+tor_socket_t tor_accept_socket(int sockfd, struct sockaddr *addr,
+ socklen_t *len);
int get_n_open_sockets(void);
#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
-/** Implementatino of struct in6_addr for platforms that do not have it.
+/** Implementation of struct in6_addr for platforms that do not have it.
* Generally, these platforms are ones without IPv6 support, but we want to
* have a working in6_addr there anyway, so we can use it to parse IPv6
* addresses. */
@@ -464,8 +473,8 @@ int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
-void set_socket_nonblocking(int socket);
-int tor_socketpair(int family, int type, int protocol, int fd[2]);
+void set_socket_nonblocking(tor_socket_t socket);
+int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
int network_init(void);
/* For stupid historical reasons, windows sockets have an independent
@@ -492,7 +501,7 @@ int network_init(void);
((e) == WSAEMFILE || (e) == WSAENOBUFS)
/** Return true if e is EADDRINUSE or the local equivalent. */
#define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE)
-int tor_socket_errno(int sock);
+int tor_socket_errno(tor_socket_t sock);
const char *tor_socket_strerror(int e);
#else
#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN)
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 3ad9be145d..6d89be804b 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -48,7 +48,7 @@ typedef uint32_t le_version_t;
* it is. */
#define LE_OLD V(0,0,0)
/** Represents a version of libevent so weird we can't figure out what version
- * it it. */
+ * it is. */
#define LE_OTHER V(0,0,99)
static le_version_t tor_get_libevent_version(const char **v_out);
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index fdf5e0a18f..1decc8d5f9 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -9,11 +9,15 @@
struct event;
struct event_base;
+
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/util.h>
#else
+#ifndef EVUTIL_SOCKET_DEFINED
+#define EVUTIL_SOCKET_DEFINED
#define evutil_socket_t int
#endif
+#endif
void configure_libevent_logging(void);
void suppress_libevent_log_msg(const char *msg);
diff --git a/src/common/container.c b/src/common/container.c
index ca49cbb170..da44b7fe68 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -210,7 +210,7 @@ smartlist_string_isin_case(const smartlist_t *sl, const char *element)
int
smartlist_string_num_isin(const smartlist_t *sl, int num)
{
- char buf[16];
+ char buf[32]; /* long enough for 64-bit int, and then some. */
tor_snprintf(buf,sizeof(buf),"%d", num);
return smartlist_string_isin(sl, buf);
}
diff --git a/src/common/crypto.c b/src/common/crypto.c
index ff117e929f..1ecc24ce23 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -733,6 +733,18 @@ crypto_pk_key_is_private(const crypto_pk_env_t *key)
return PRIVATE_KEY_OK(key);
}
+/** Return true iff <b>env</b> contains a public key whose public exponent
+ * equals 65537.
+ */
+int
+crypto_pk_public_exponent_ok(crypto_pk_env_t *env)
+{
+ tor_assert(env);
+ tor_assert(env->key);
+
+ return BN_is_word(env->key->e, 65537);
+}
+
/** Compare the public-key components of a and b. Return -1 if a\<b, 0
* if a==b, and 1 if a\>b.
*/
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 05185f3f18..54c7a67a3b 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -122,6 +122,7 @@ size_t crypto_pk_keysize(crypto_pk_env_t *env);
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
crypto_pk_env_t *crypto_pk_copy_full(crypto_pk_env_t *orig);
int crypto_pk_key_is_private(const crypto_pk_env_t *key);
+int crypto_pk_public_exponent_ok(crypto_pk_env_t *env);
int crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, size_t tolen,
const char *from, size_t fromlen, int padding);
diff --git a/src/common/log.c b/src/common/log.c
index d14563c885..ac98f13539 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -390,7 +390,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
/** Output a message to the log. It gets logged to all logfiles that
* care about messages with <b>severity</b> in <b>domain</b>. The content
- * is formatted printf style basedc on <b>format</b> and extra arguments.
+ * is formatted printf-style based on <b>format</b> and extra arguments.
* */
void
tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
diff --git a/src/common/procmon.c b/src/common/procmon.c
new file mode 100644
index 0000000000..8fcc1afb7c
--- /dev/null
+++ b/src/common/procmon.c
@@ -0,0 +1,336 @@
+
+/**
+ * \file procmon.c
+ * \brief Process-termination monitor functions
+ **/
+
+#include "procmon.h"
+
+#include "util.h"
+
+#ifdef HAVE_EVENT2_EVENT_H
+#include <event2/event.h>
+#else
+#include <event.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef MS_WINDOWS
+#include <windows.h>
+
+/* Windows does not define pid_t, but _getpid() returns an int. */
+typedef int pid_t;
+#endif
+
+/* Define to 1 if process-termination monitors on this OS and Libevent
+ version must poll for process termination themselves. */
+#define PROCMON_POLLS 1
+/* Currently we need to poll in some way on all systems. */
+
+#ifdef PROCMON_POLLS
+static void tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
+ void *procmon_);
+#endif
+
+/* This struct may contain pointers into the original process
+ * specifier string, but it should *never* contain anything which
+ * needs to be freed. */
+struct parsed_process_specifier_t {
+ pid_t pid;
+};
+
+/** Parse the process specifier given in <b>process_spec</b> into
+ * *<b>ppspec</b>. Return 0 on success; return -1 and store an error
+ * message into *<b>msg</b> on failure. The caller must not free the
+ * returned error message. */
+static int
+parse_process_specifier(const char *process_spec,
+ struct parsed_process_specifier_t *ppspec,
+ const char **msg)
+{
+ long pid_l;
+ int pid_ok = 0;
+ char *pspec_next;
+
+ /* If we're lucky, long will turn out to be large enough to hold a
+ * PID everywhere that Tor runs. */
+ pid_l = tor_parse_long(process_spec, 0, 1, LONG_MAX, &pid_ok, &pspec_next);
+
+ /* Reserve room in the ‘process specifier’ for additional
+ * (platform-specific) identifying information beyond the PID, to
+ * make our process-existence checks a bit less racy in a future
+ * version. */
+ if ((*pspec_next != 0) && (*pspec_next != ' ') && (*pspec_next != ':')) {
+ pid_ok = 0;
+ }
+
+ ppspec->pid = (pid_t)(pid_l);
+ if (!pid_ok || (pid_l != (long)(ppspec->pid))) {
+ *msg = "invalid PID";
+ goto err;
+ }
+
+ return 0;
+ err:
+ return -1;
+}
+
+struct tor_process_monitor_t {
+ /** Log domain for warning messages. */
+ log_domain_mask_t log_domain;
+
+ /** All systems: The best we can do in general is poll for the
+ * process's existence by PID periodically, and hope that the kernel
+ * doesn't reassign the same PID to another process between our
+ * polls. */
+ pid_t pid;
+
+#ifdef MS_WINDOWS
+ /** Windows-only: Should we poll hproc? If false, poll pid
+ * instead. */
+ int poll_hproc;
+
+ /** Windows-only: Get a handle to the process (if possible) and
+ * periodically check whether the process we have a handle to has
+ * ended. */
+ HANDLE hproc;
+ /* XXX023 We can and should have Libevent watch hproc for us,
+ * if/when some version of Libevent 2.x can be told to do so. */
+#endif
+
+ /* XXX023 On Linux, we can and should receive the 22nd
+ * (space-delimited) field (‘starttime’) of /proc/$PID/stat from the
+ * owning controller and store it, and poll once in a while to see
+ * whether it has changed -- if so, the kernel has *definitely*
+ * reassigned the owning controller's PID and we should exit. On
+ * FreeBSD, we can do the same trick using either the 8th
+ * space-delimited field of /proc/$PID/status on the seven FBSD
+ * systems whose admins have mounted procfs, or the start-time field
+ * of the process-information structure returned by kvmgetprocs() on
+ * any system. The latter is ickier. */
+ /* XXX023 On FreeBSD (and possibly other kqueue systems), we can and
+ * should arrange to receive EVFILT_PROC NOTE_EXIT notifications for
+ * pid, so we don't have to do such a heavyweight poll operation in
+ * order to avoid the PID-reassignment race condition. (We would
+ * still need to poll our own kqueue periodically until some version
+ * of Libevent 2.x learns to receive these events for us.) */
+
+ /** A Libevent event structure, to either poll for the process's
+ * existence or receive a notification when the process ends. */
+ struct event *e;
+
+ /** A callback to be called when the process ends. */
+ tor_procmon_callback_t cb;
+ void *cb_arg; /**< A user-specified pointer to be passed to cb. */
+};
+
+/** Verify that the process specifier given in <b>process_spec</b> is
+ * syntactically valid. Return 0 on success; return -1 and store an
+ * error message into *<b>msg</b> on failure. The caller must not
+ * free the returned error message. */
+int
+tor_validate_process_specifier(const char *process_spec,
+ const char **msg)
+{
+ struct parsed_process_specifier_t ppspec;
+
+ tor_assert(msg != NULL);
+ *msg = NULL;
+
+ return parse_process_specifier(process_spec, &ppspec, msg);
+}
+
+#ifdef HAVE_EVENT2_EVENT_H
+#define PERIODIC_TIMER_FLAGS EV_PERSIST
+#else
+#define PERIODIC_TIMER_FLAGS (0)
+#endif
+
+static struct timeval poll_interval_tv = {15, 0};
+/* Note: If you port this file to plain Libevent 2, you can make
+ * poll_interval_tv const. It has to be non-const here because in
+ * libevent 1.x, event_add expects a pointer to a non-const struct
+ * timeval. */
+
+/** Create a process-termination monitor for the process specifier
+ * given in <b>process_spec</b>. Return a newly allocated
+ * tor_process_monitor_t on success; return NULL and store an error
+ * message into *<b>msg</b> on failure. The caller must not free
+ * the returned error message.
+ *
+ * When the monitored process terminates, call
+ * <b>cb</b>(<b>cb_arg</b>).
+ */
+tor_process_monitor_t *
+tor_process_monitor_new(struct event_base *base,
+ const char *process_spec,
+ log_domain_mask_t log_domain,
+ tor_procmon_callback_t cb, void *cb_arg,
+ const char **msg)
+{
+ tor_process_monitor_t *procmon = tor_malloc(sizeof(tor_process_monitor_t));
+ struct parsed_process_specifier_t ppspec;
+
+ tor_assert(msg != NULL);
+ *msg = NULL;
+
+ if (procmon == NULL) {
+ *msg = "out of memory";
+ goto err;
+ }
+
+ procmon->log_domain = log_domain;
+
+ if (parse_process_specifier(process_spec, &ppspec, msg))
+ goto err;
+
+ procmon->pid = ppspec.pid;
+
+#ifdef MS_WINDOWS
+ procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
+ FALSE,
+ procmon->pid);
+
+ if (procmon->hproc != NULL) {
+ procmon->poll_hproc = 1;
+ log_info(procmon->log_domain, "Successfully opened handle to process %d; "
+ "monitoring it.",
+ (int)(procmon->pid));
+ } else {
+ /* If we couldn't get a handle to the process, we'll try again the
+ * first time we poll. */
+ log_info(procmon->log_domain, "Failed to open handle to process %d; will "
+ "try again later.",
+ (int)(procmon->pid));
+ }
+#endif
+
+ procmon->cb = cb;
+ procmon->cb_arg = cb_arg;
+
+#ifdef PROCMON_POLLS
+ procmon->e = tor_event_new(base, -1 /* no FD */, PERIODIC_TIMER_FLAGS,
+ tor_process_monitor_poll_cb, procmon);
+ /* Note: If you port this file to plain Libevent 2, check that
+ * procmon->e is non-NULL. We don't need to here because
+ * tor_evtimer_new never returns NULL. */
+
+ evtimer_add(procmon->e, &poll_interval_tv);
+#else
+#error OOPS?
+#endif
+
+ return procmon;
+ err:
+ tor_process_monitor_free(procmon);
+ return NULL;
+}
+
+#ifdef PROCMON_POLLS
+/** Libevent callback to poll for the existence of the process
+ * monitored by <b>procmon_</b>. */
+static void
+tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
+ void *procmon_)
+{
+ tor_process_monitor_t *procmon = (tor_process_monitor_t *)(procmon_);
+ int its_dead_jim;
+
+ (void)unused1; (void)unused2;
+
+ tor_assert(procmon != NULL);
+
+#ifdef MS_WINDOWS
+ if (procmon->poll_hproc) {
+ DWORD exit_code;
+ if (!GetExitCodeProcess(procmon->hproc, &exit_code)) {
+ char *errmsg = format_win32_error(GetLastError());
+ log_warn(procmon->log_domain, "Error \"%s\" occurred while polling "
+ "handle for monitored process %d; assuming it's dead."
+ errmsg, procmon->pid);
+ tor_free(errmsg);
+ its_dead_jim = 1;
+ } else {
+ its_dead_jim = (exit_code != STILL_ACTIVE);
+ }
+ } else {
+ /* All we can do is try to open the process, and look at the error
+ * code if it fails again. */
+ procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
+ FALSE,
+ procmon->pid);
+
+ if (procmon->hproc != NULL) {
+ log_info(procmon->log_domain, "Successfully opened handle to monitored "
+ "process %d.",
+ procmon->pid);
+ its_dead_jim = 0;
+ procmon->poll_hproc = 1;
+ } else {
+ DWORD err_code = GetLastError();
+ char *errmsg = format_win32_error(err_code);
+
+ /* When I tested OpenProcess's error codes on Windows 7, I
+ * received error code 5 (ERROR_ACCESS_DENIED) for PIDs of
+ * existing processes that I could not open and error code 87
+ * (ERROR_INVALID_PARAMETER) for PIDs that were not in use.
+ * Since the nonexistent-process error code is sane, I'm going
+ * to assume that all errors other than ERROR_INVALID_PARAMETER
+ * mean that the process we are monitoring is still alive. */
+ its_dead_jim = (err_code == ERROR_INVALID_PARAMETER);
+
+ if (!its_dead_jim)
+ log_info(procmon->log_domain, "Failed to open handle to monitored "
+ "process %d, and error code %d (%s) is not 'invalid "
+ "parameter' -- assuming the process is still alive.",
+ procmon->pid,
+ err_code, err_msg);
+
+ tor_free(err_msg);
+ }
+ }
+#else
+ /* Unix makes this part easy, if a bit racy. */
+ its_dead_jim = kill(procmon->pid, 0);
+ its_dead_jim = its_dead_jim && (errno == ESRCH);
+#endif
+
+ log(its_dead_jim ? LOG_NOTICE : LOG_INFO,
+ procmon->log_domain, "Monitored process %d is %s.",
+ (int)procmon->pid,
+ its_dead_jim ? "dead" : "still alive");
+
+ if (its_dead_jim) {
+ procmon->cb(procmon->cb_arg);
+#ifndef HAVE_EVENT2_EVENT_H
+ } else {
+ evtimer_add(procmon->e, &poll_interval_tv);
+#endif
+ }
+}
+#endif
+
+/** Free the process-termination monitor <b>procmon</b>. */
+void
+tor_process_monitor_free(tor_process_monitor_t *procmon)
+{
+ if (procmon == NULL)
+ return;
+
+#ifdef MS_WINDOWS
+ if (procmon->hproc != NULL)
+ CloseHandle(procmon->hproc);
+#endif
+
+ if (procmon->e != NULL)
+ tor_event_free(procmon->e);
+
+ tor_free(procmon);
+}
+
diff --git a/src/common/procmon.h b/src/common/procmon.h
new file mode 100644
index 0000000000..02eb2da61c
--- /dev/null
+++ b/src/common/procmon.h
@@ -0,0 +1,30 @@
+
+/**
+ * \file procmon.h
+ * \brief Headers for procmon.c
+ **/
+
+#ifndef TOR_PROCMON_H
+#define TOR_PROCMON_H
+
+#include "compat.h"
+#include "compat_libevent.h"
+
+#include "torlog.h"
+
+typedef struct tor_process_monitor_t tor_process_monitor_t;
+
+typedef void (*tor_procmon_callback_t)(void *);
+
+int tor_validate_process_specifier(const char *process_spec,
+ const char **msg);
+tor_process_monitor_t *tor_process_monitor_new(struct event_base *base,
+ const char *process_spec,
+ log_domain_mask_t log_domain,
+ tor_procmon_callback_t cb,
+ void *cb_arg,
+ const char **msg);
+void tor_process_monitor_free(tor_process_monitor_t *procmon);
+
+#endif
+
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 000e32ddab..541a0d1738 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -146,7 +146,6 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
void flush_pending_log_callbacks(void);
void log_set_application_name(const char *name);
-/* Outputs a message to stdout */
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
CHECK_PRINTF(3,4);
#define log tor_log /* hack it so we don't conflict with log() as much */
diff --git a/src/common/util.c b/src/common/util.c
index 1bb116b212..6f323dd20c 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -775,13 +775,17 @@ tor_digest256_is_zero(const char *digest)
if (next) *next = endptr; \
return 0
-/** Extract a long from the start of s, in the given numeric base. If
- * there is unconverted data and next is provided, set *next to the
- * first unconverted character. An error has occurred if no characters
- * are converted; or if there are unconverted characters and next is NULL; or
- * if the parsed value is not between min and max. When no error occurs,
- * return the parsed value and set *ok (if provided) to 1. When an error
- * occurs, return 0 and set *ok (if provided) to 0.
+/** Extract a long from the start of <b>s</b>, in the given numeric
+ * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
+ * octal, or hex number in the syntax of a C integer literal. If
+ * there is unconverted data and <b>next</b> is provided, set
+ * *<b>next</b> to the first unconverted character. An error has
+ * occurred if no characters are converted; or if there are
+ * unconverted characters and <b>next</b> is NULL; or if the parsed
+ * value is not between <b>min</b> and <b>max</b>. When no error
+ * occurs, return the parsed value and set *<b>ok</b> (if provided) to
+ * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
+ * to 0.
*/
long
tor_parse_long(const char *s, int base, long min, long max,
@@ -1568,7 +1572,7 @@ rate_limit_log(ratelim_t *lim, time_t now)
* was returned by open(). Return the number of bytes written, or -1
* on error. Only use if fd is a blocking fd. */
ssize_t
-write_all(int fd, const char *buf, size_t count, int isSocket)
+write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket)
{
size_t written = 0;
ssize_t result;
@@ -1578,7 +1582,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket)
if (isSocket)
result = tor_socket_send(fd, buf+written, count-written, 0);
else
- result = write(fd, buf+written, count-written);
+ result = write((int)fd, buf+written, count-written);
if (result<0)
return -1;
written += result;
@@ -1592,7 +1596,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket)
* open(). Return the number of bytes read, or -1 on error. Only use
* if fd is a blocking fd. */
ssize_t
-read_all(int fd, char *buf, size_t count, int isSocket)
+read_all(tor_socket_t fd, char *buf, size_t count, int isSocket)
{
size_t numread = 0;
ssize_t result;
@@ -1604,7 +1608,7 @@ read_all(int fd, char *buf, size_t count, int isSocket)
if (isSocket)
result = tor_socket_recv(fd, buf+numread, count-numread, 0);
else
- result = read(fd, buf+numread, count-numread);
+ result = read((int)fd, buf+numread, count-numread);
if (result<0)
return -1;
else if (result == 0)
@@ -2092,7 +2096,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
int save_errno = errno;
if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
severity = LOG_INFO;
- log_fn(severity, LD_FS,"Could not open \"%s\": %s ",filename,
+ log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
strerror(errno));
errno = save_errno;
return NULL;
diff --git a/src/common/util.h b/src/common/util.h
index f32709accd..ebbcf78bdc 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -276,8 +276,8 @@ typedef struct ratelim_t {
char *rate_limit_log(ratelim_t *lim, time_t now);
/* File helpers */
-ssize_t write_all(int fd, const char *buf, size_t count, int isSocket);
-ssize_t read_all(int fd, char *buf, size_t count, int isSocket);
+ssize_t write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket);
+ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket);
/** Return values from file_status(); see that function's documentation
* for details. */
diff --git a/src/or/buffers.c b/src/or/buffers.c
index db926955b4..05163637f2 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -587,7 +587,7 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
* *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
* and the number of bytes read otherwise. */
static INLINE int
-read_to_chunk(buf_t *buf, chunk_t *chunk, int fd, size_t at_most,
+read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
int *reached_eof, int *socket_error)
{
ssize_t read_result;
@@ -668,7 +668,7 @@ read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
*/
/* XXXX023 indicate "read blocked" somehow? */
int
-read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof,
+read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
int *socket_error)
{
/* XXXX023 It's stupid to overload the return values for these functions:
@@ -767,7 +767,7 @@ read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf)
* written on success, 0 on blocking, -1 on failure.
*/
static INLINE int
-flush_chunk(int s, buf_t *buf, chunk_t *chunk, size_t sz,
+flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
size_t *buf_flushlen)
{
ssize_t write_result;
@@ -854,7 +854,7 @@ flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
* -1 on failure. Return 0 if write() would block.
*/
int
-flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen)
+flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen)
{
/* XXXX023 It's stupid to overload the return values for these functions:
* "error status" and "number of bytes flushed" are not mutually exclusive.
diff --git a/src/or/buffers.h b/src/or/buffers.h
index e50b9ff6fb..63fab4957a 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -24,11 +24,11 @@ size_t buf_datalen(const buf_t *buf);
size_t buf_allocation(const buf_t *buf);
size_t buf_slack(const buf_t *buf);
-int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof,
+int read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
int *socket_error);
int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf);
-int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen);
+int flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen);
int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen);
int write_to_buf(const char *string, size_t string_len, buf_t *buf);
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 469e180072..2f70b67d23 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -262,7 +262,7 @@ circuit_build_times_test_frequency(void)
}
/**
- * Retrieve and bounds-check the cbtmintimeout consensus paramter.
+ * Retrieve and bounds-check the cbtmintimeout consensus parameter.
*
* Effect: This is the minimum allowed timeout value in milliseconds.
* The minimum is to prevent rounding to 0 (we only check once
@@ -1753,7 +1753,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
if (!n_conn) {
/* not currently connected in a useful way. */
- log_info(LD_CIRC, "Next router is %s: %s ",
+ log_info(LD_CIRC, "Next router is %s: %s",
safe_str_client(extend_info_describe(firsthop->extend_info)),
msg?msg:"???");
circ->_base.n_hop = extend_info_dup(firsthop->extend_info);
@@ -3772,7 +3772,6 @@ void
entry_guards_compute_status(or_options_t *options, time_t now)
{
int changed = 0;
- int severity = LOG_DEBUG;
digestmap_t *reasons;
if (! entry_guards)
@@ -3799,8 +3798,6 @@ entry_guards_compute_status(or_options_t *options, time_t now)
if (remove_dead_entry_guards(now))
changed = 1;
- severity = changed ? LOG_DEBUG : LOG_INFO;
-
if (changed) {
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *reason = digestmap_get(reasons, entry->identity);
@@ -4546,7 +4543,7 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
!tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
bridge->port == port)
return bridge;
- if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
+ if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN))
return bridge;
}
SMARTLIST_FOREACH_END(bridge);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 4c29bf8359..138fff6f78 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -288,7 +288,6 @@ circuit_expire_building(void)
struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff,
cannibalize_cutoff, close_cutoff, extremely_old_cutoff;
struct timeval now;
- struct timeval introcirc_cutoff;
cpath_build_state_t *build_state;
tor_gettimeofday(&now);
@@ -307,8 +306,6 @@ circuit_expire_building(void)
SET_CUTOFF(close_cutoff, circ_times.close_ms);
SET_CUTOFF(extremely_old_cutoff, circ_times.close_ms*2 + 1000);
- introcirc_cutoff = begindir_cutoff;
-
while (next_circ) {
struct timeval cutoff;
victim = next_circ;
@@ -325,8 +322,6 @@ circuit_expire_building(void)
cutoff = fourhop_cutoff;
else if (TO_ORIGIN_CIRCUIT(victim)->has_opened)
cutoff = cannibalize_cutoff;
- else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING)
- cutoff = introcirc_cutoff;
else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
cutoff = close_cutoff;
else
@@ -337,12 +332,6 @@ circuit_expire_building(void)
#if 0
/* some debug logs, to help track bugs */
- if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
- victim->timestamp_created <= introcirc_cutoff &&
- victim->timestamp_created > general_cutoff)
- log_info(LD_REND|LD_CIRC, "Timing out introduction circuit which we "
- "would not have done if it had been a general circuit.");
-
if (victim->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING &&
victim->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
if (!victim->timestamp_dirty)
diff --git a/src/or/command.c b/src/or/command.c
index d25918b841..12b4c30f5c 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -645,6 +645,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
/* XXX maybe act on my_apparent_addr, if the source is sufficiently
* trustworthy. */
+ (void)my_apparent_addr;
if (connection_or_set_state_open(conn)<0)
connection_mark_for_close(TO_CONN(conn));
diff --git a/src/or/config.c b/src/or/config.c
index 614fc48c3e..117925549e 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -38,6 +38,8 @@
#include <shlobj.h>
#endif
+#include "procmon.h"
+
/** Enumeration of types which option values can take */
typedef enum config_type_t {
CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
@@ -398,6 +400,7 @@ static config_var_t _option_vars[] = {
VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
NULL),
+ VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"),
V(_UsingTestNetworkDefaults, BOOL, "0"),
@@ -1169,12 +1172,26 @@ options_act(or_options_t *old_options)
or_options_t *options = get_options();
int running_tor = options->command == CMD_RUN_TOR;
char *msg;
+ const int transition_affects_workers =
+ old_options && options_transition_affects_workers(old_options, options);
if (running_tor && !have_lockfile()) {
if (try_locking(options, 1) < 0)
return -1;
}
+ /* We want to reinit keys as needed before we do much of anything else:
+ keys are important, and other things can depend on them. */
+ if (running_tor &&
+ (transition_affects_workers ||
+ (options->V3AuthoritativeDir && (!old_options ||
+ !old_options->V3AuthoritativeDir)))) {
+ if (init_keys() < 0) {
+ log_warn(LD_BUG,"Error initializing keys; exiting");
+ return -1;
+ }
+ }
+
if (consider_adding_dir_authorities(options, old_options) < 0)
return -1;
@@ -1241,6 +1258,8 @@ options_act(or_options_t *old_options)
return -1;
}
+ monitor_owning_controller_process(options->OwningControllerProcess);
+
/* reload keys as needed for rendezvous services. */
if (rend_service_load_keys()<0) {
log_warn(LD_GENERAL,"Error loading rendezvous service keys");
@@ -1275,6 +1294,9 @@ options_act(or_options_t *old_options)
int revise_trackexithosts = 0;
int revise_automap_entries = 0;
if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
+ options->UseBridges != old_options->UseBridges ||
+ (options->UseBridges &&
+ !config_lines_eq(options->Bridges, old_options->Bridges)) ||
!routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) ||
!routerset_equal(old_options->ExcludeExitNodes,
options->ExcludeExitNodes) ||
@@ -1282,8 +1304,9 @@ options_act(or_options_t *old_options)
!routerset_equal(old_options->ExitNodes, options->ExitNodes) ||
options->StrictNodes != old_options->StrictNodes) {
log_info(LD_CIRC,
- "Changed to using entry guards, or changed preferred or "
- "excluded node lists. Abandoning previous circuits.");
+ "Changed to using entry guards or bridges, or changed "
+ "preferred or excluded node lists. "
+ "Abandoning previous circuits.");
circuit_mark_all_unused_circs();
circuit_expire_all_dirty_circs();
revise_trackexithosts = 1;
@@ -1337,14 +1360,10 @@ options_act(or_options_t *old_options)
}
}
- if (options_transition_affects_workers(old_options, options)) {
+ if (transition_affects_workers) {
log_info(LD_GENERAL,
"Worker-related options changed. Rotating workers.");
- if (init_keys() < 0) {
- log_warn(LD_BUG,"Error initializing keys; exiting");
- return -1;
- }
if (server_mode(options) && !server_mode(old_options)) {
ip_address_changed(0);
if (can_complete_circuit || !any_predicted_circuits(time(NULL)))
@@ -1358,9 +1377,6 @@ options_act(or_options_t *old_options)
return -1;
}
- if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir)
- init_keys();
-
if (options->PerConnBWRate != old_options->PerConnBWRate ||
options->PerConnBWBurst != old_options->PerConnBWBurst)
connection_or_update_token_buckets(get_connection_array(), options);
@@ -1455,7 +1471,7 @@ options_act(or_options_t *old_options)
*/
if (!old_options ||
options_transition_affects_descriptor(old_options, options))
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("config change");
/* We may need to reschedule some directory stuff if our status changed. */
if (old_options) {
@@ -3398,8 +3414,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->HTTPProxyAuthenticator) {
- if (strlen(options->HTTPProxyAuthenticator) >= 48)
- REJECT("HTTPProxyAuthenticator is too long (>= 48 chars).");
+ if (strlen(options->HTTPProxyAuthenticator) >= 512)
+ REJECT("HTTPProxyAuthenticator is too long (>= 512 chars).");
}
if (options->HTTPSProxy) { /* parse it now */
@@ -3412,8 +3428,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->HTTPSProxyAuthenticator) {
- if (strlen(options->HTTPSProxyAuthenticator) >= 48)
- REJECT("HTTPSProxyAuthenticator is too long (>= 48 chars).");
+ if (strlen(options->HTTPSProxyAuthenticator) >= 512)
+ REJECT("HTTPSProxyAuthenticator is too long (>= 512 chars).");
}
if (options->Socks4Proxy) { /* parse it now */
@@ -3476,6 +3492,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
+ if (options->OwningControllerProcess) {
+ const char *validate_pspec_msg = NULL;
+ if (tor_validate_process_specifier(options->OwningControllerProcess,
+ &validate_pspec_msg)) {
+ tor_asprintf(msg, "Bad OwningControllerProcess: %s",
+ validate_pspec_msg);
+ return -1;
+ }
+ }
+
if (options->ControlListenAddress) {
int all_are_local = 1;
config_line_t *ln;
@@ -3805,7 +3831,7 @@ options_transition_affects_workers(or_options_t *old_options,
old_options->ORPort != new_options->ORPort ||
old_options->ServerDNSSearchDomains !=
new_options->ServerDNSSearchDomains ||
- old_options->SafeLogging != new_options->SafeLogging ||
+ old_options->_SafeLogging != new_options->_SafeLogging ||
old_options->ClientOnly != new_options->ClientOnly ||
public_server_mode(old_options) != public_server_mode(new_options) ||
!config_lines_eq(old_options->Logs, new_options->Logs) ||
diff --git a/src/or/connection.c b/src/or/connection.c
index b7d6fe408d..6644b4cd76 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -54,8 +54,8 @@ static int connection_reached_eof(connection_t *conn);
static int connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
int *socket_error);
static int connection_process_inbuf(connection_t *conn, int package_partial);
-static void client_check_address_changed(int sock);
-static void set_constrained_socket_buffers(int sock, int size);
+static void client_check_address_changed(tor_socket_t sock);
+static void set_constrained_socket_buffers(tor_socket_t sock, int size);
static const char *connection_proxy_state_to_string(int state);
static int connection_read_https_proxy_response(connection_t *conn);
@@ -439,8 +439,8 @@ _connection_free(connection_t *conn)
rend_data_free(dir_conn->rend_data);
}
- if (conn->s >= 0) {
- log_debug(LD_NET,"closing fd %d.",conn->s);
+ if (SOCKET_OK(conn->s)) {
+ log_debug(LD_NET,"closing fd %d.",(int)conn->s);
tor_close_socket(conn->s);
conn->s = -1;
}
@@ -479,8 +479,7 @@ connection_free(connection_t *conn)
}
}
if (conn->type == CONN_TYPE_CONTROL) {
- TO_CONTROL_CONN(conn)->event_mask = 0;
- control_update_global_event_mask();
+ connection_control_closed(TO_CONTROL_CONN(conn));
}
connection_unregister_events(conn);
_connection_free(conn);
@@ -663,14 +662,14 @@ connection_close_immediate(connection_t *conn)
}
if (conn->outbuf_flushlen) {
log_info(LD_NET,"fd %d, type %s, state %s, %d bytes on outbuf.",
- conn->s, conn_type_to_string(conn->type),
+ (int)conn->s, conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
(int)conn->outbuf_flushlen);
}
connection_unregister_events(conn);
- if (conn->s >= 0)
+ if (SOCKET_OK(conn->s))
tor_close_socket(conn->s);
conn->s = -1;
if (conn->linked)
@@ -740,7 +739,7 @@ connection_expire_held_open(void)
log_fn(severity, LD_NET,
"Giving up on marked_for_close conn that's been flushing "
"for 15s (fd %d, type %s, state %s).",
- conn->s, conn_type_to_string(conn->type),
+ (int)conn->s, conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state));
conn->hold_open_until_flushed = 0;
}
@@ -890,6 +889,25 @@ check_location_for_unix_socket(or_options_t *options, const char *path)
}
#endif
+/** Tell the TCP stack that it shouldn't wait for a long time after
+ * <b>sock</b> has closed before reusing its port. */
+static void
+make_socket_reuseable(tor_socket_t sock)
+{
+#ifdef MS_WINDOWS
+ (void) sock;
+#else
+ int one=1;
+
+ /* REUSEADDR on normal places means you can rebind to the port
+ * right after somebody else has let it go. But REUSEADDR on win32
+ * means you can bind to the port _even when somebody else
+ * already has it bound_. So, don't do that on Win32. */
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
+ (socklen_t)sizeof(one));
+#endif
+}
+
/** Bind a new non-blocking socket listening to the socket described
* by <b>listensockaddr</b>.
*
@@ -902,7 +920,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
int type, char* address)
{
connection_t *conn;
- int s; /* the socket we're going to make */
+ tor_socket_t s; /* the socket we're going to make */
uint16_t usePort = 0, gotPort = 0;
int start_reading = 0;
@@ -914,9 +932,6 @@ connection_create_listener(const struct sockaddr *listensockaddr,
if (listensockaddr->sa_family == AF_INET) {
tor_addr_t addr;
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
-#ifndef MS_WINDOWS
- int one=1;
-#endif
if (is_tcp)
start_reading = 1;
@@ -928,19 +943,12 @@ connection_create_listener(const struct sockaddr *listensockaddr,
s = tor_open_socket(PF_INET,
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
- if (s < 0) {
+ if (!SOCKET_OK(s)) {
log_warn(LD_NET,"Socket creation failed.");
goto err;
}
-#ifndef MS_WINDOWS
- /* REUSEADDR on normal places means you can rebind to the port
- * right after somebody else has let it go. But REUSEADDR on win32
- * means you can bind to the port _even when somebody else
- * already has it bound_. So, don't do that on Win32. */
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
- (socklen_t)sizeof(one));
-#endif
+ make_socket_reuseable(s);
if (bind(s,listensockaddr,socklen) < 0) {
const char *helpfulhint = "";
@@ -1128,7 +1136,7 @@ check_sockaddr_family_match(sa_family_t got, connection_t *listener)
static int
connection_handle_listener_read(connection_t *conn, int new_type)
{
- int news; /* the new socket */
+ tor_socket_t news; /* the new socket */
connection_t *newconn;
/* information about the remote peer when connecting to other routers */
char addrbuf[256];
@@ -1141,7 +1149,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
memset(addrbuf, 0, sizeof(addrbuf));
news = tor_accept_socket(conn->s,remote,&remotelen);
- if (news < 0) { /* accept() error */
+ if (!SOCKET_OK(news)) { /* accept() error */
int e = tor_socket_errno(conn->s);
if (ERRNO_IS_ACCEPT_EAGAIN(e)) {
return 0; /* he hung up before we could accept(). that's fine. */
@@ -1157,8 +1165,9 @@ connection_handle_listener_read(connection_t *conn, int new_type)
}
log_debug(LD_NET,
"Connection accepted on socket %d (child of fd %d).",
- news,conn->s);
+ (int)news,(int)conn->s);
+ make_socket_reuseable(news);
set_socket_nonblocking(news);
if (options->ConstrainedSockets)
@@ -1309,7 +1318,8 @@ int
connection_connect(connection_t *conn, const char *address,
const tor_addr_t *addr, uint16_t port, int *socket_error)
{
- int s, inprogress = 0;
+ tor_socket_t s;
+ int inprogress = 0;
char addrbuf[256];
struct sockaddr *dest_addr;
socklen_t dest_addr_len;
@@ -1368,6 +1378,8 @@ connection_connect(connection_t *conn, const char *address,
log_debug(LD_NET, "Connecting to %s:%u.",
escaped_safe_str_client(address), port);
+ make_socket_reuseable(s);
+
if (connect(s, dest_addr, dest_addr_len) < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
@@ -2381,7 +2393,7 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
TO_OR_CONN(conn)->read_bucket > 0)) {
/* and either a non-cell conn or a cell conn with non-empty bucket */
LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,
- "waking up conn (fd %d) for read", conn->s));
+ "waking up conn (fd %d) for read", (int)conn->s));
conn->read_blocked_on_bw = 0;
connection_start_reading(conn);
}
@@ -2394,7 +2406,7 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
conn->state != OR_CONN_STATE_OPEN ||
TO_OR_CONN(conn)->write_bucket > 0)) {
LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,
- "waking up conn (fd %d) for write", conn->s));
+ "waking up conn (fd %d) for write", (int)conn->s));
conn->write_blocked_on_bw = 0;
connection_start_writing(conn);
}
@@ -2586,7 +2598,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
log_debug(LD_NET,
"%d: starting, inbuf_datalen %ld (%d pending in tls object)."
" at_most %ld.",
- conn->s,(long)buf_datalen(conn->inbuf),
+ (int)conn->s,(long)buf_datalen(conn->inbuf),
tor_tls_get_pending_bytes(or_conn->tls), (long)at_most);
initial_size = buf_datalen(conn->inbuf);
@@ -2757,7 +2769,7 @@ connection_handle_write_impl(connection_t *conn, int force)
tor_assert(!connection_is_listener(conn));
- if (conn->marked_for_close || conn->s < 0)
+ if (conn->marked_for_close || !SOCKET_OK(conn->s))
return 0; /* do nothing */
if (conn->in_flushed_some) {
@@ -2973,12 +2985,13 @@ _connection_write_to_buf_impl(const char *string, size_t len,
/* if it failed, it means we have our package/delivery windows set
wrong compared to our max outbuf size. close the whole circuit. */
log_warn(LD_NET,
- "write_to_buf failed. Closing circuit (fd %d).", conn->s);
+ "write_to_buf failed. Closing circuit (fd %d).", (int)conn->s);
circuit_mark_for_close(circuit_get_by_edge_conn(TO_EDGE_CONN(conn)),
END_CIRC_REASON_INTERNAL);
} else {
log_warn(LD_NET,
- "write_to_buf failed. Closing connection (fd %d).", conn->s);
+ "write_to_buf failed. Closing connection (fd %d).",
+ (int)conn->s);
connection_mark_for_close(conn);
}
return;
@@ -3018,7 +3031,7 @@ _connection_write_to_buf_impl(const char *string, size_t len,
/* this connection is broken. remove it. */
log_warn(LD_BUG, "unhandled error on write for "
"conn (type %d, fd %d); removing",
- conn->type, conn->s);
+ conn->type, (int)conn->s);
tor_fragile_assert();
/* do a close-immediate here, so we don't try to flush */
connection_close_immediate(conn);
@@ -3220,8 +3233,17 @@ alloc_http_authenticator(const char *authenticator)
authenticator, authenticator_length) < 0) {
tor_free(base64_authenticator); /* free and set to null */
} else {
- /* remove extra \n at end of encoding */
- base64_authenticator[strlen(base64_authenticator) - 1] = 0;
+ int i = 0, j = 0;
+ ssize_t len = strlen(base64_authenticator);
+
+ /* remove all newline occurrences within the string */
+ for (i=0; i < len; ++i) {
+ if ('\n' != base64_authenticator[i]) {
+ base64_authenticator[j] = base64_authenticator[i];
+ ++j;
+ }
+ }
+ base64_authenticator[j]='\0';
}
return base64_authenticator;
}
@@ -3232,7 +3254,7 @@ alloc_http_authenticator(const char *authenticator)
* call init_keys().
*/
static void
-client_check_address_changed(int sock)
+client_check_address_changed(tor_socket_t sock)
{
uint32_t iface_ip, ip_out; /* host order */
struct sockaddr_in out_addr;
@@ -3288,7 +3310,7 @@ client_check_address_changed(int sock)
* to the desired size to stay below system TCP buffer limits.
*/
static void
-set_constrained_socket_buffers(int sock, int size)
+set_constrained_socket_buffers(tor_socket_t sock, int size)
{
void *sz = (void*)&size;
socklen_t sz_sz = (socklen_t) sizeof(size);
@@ -3520,7 +3542,7 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn->linked);
}
if (conn->linked)
- tor_assert(conn->s < 0);
+ tor_assert(!SOCKET_OK(conn->s));
if (conn->outbuf_flushlen > 0) {
tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw ||
diff --git a/src/or/control.c b/src/or/control.c
index 384e579f93..c7e22f81e2 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -32,6 +32,8 @@
#include "routerlist.h"
#include "routerparse.h"
+#include "procmon.h"
+
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
* finished authentication and is accepting commands. */
#define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN)
@@ -1275,6 +1277,26 @@ handle_control_signal(control_connection_t *conn, uint32_t len,
return 0;
}
+/** Called when we get a TAKEOWNERSHIP command. Mark this connection
+ * as an owning connection, so that we will exit if the connection
+ * closes. */
+static int
+handle_control_takeownership(control_connection_t *conn, uint32_t len,
+ const char *body)
+{
+ (void)len;
+ (void)body;
+
+ conn->is_owning_control_connection = 1;
+
+ log_info(LD_CONTROL, "Control connection %d has taken ownership of this "
+ "Tor instance.",
+ (int)(conn->_base.s));
+
+ send_control_done(conn);
+ return 0;
+}
+
/** Called when we get a MAPADDRESS command; try to bind all listed addresses,
* and report success or failure. */
static int
@@ -1490,7 +1512,7 @@ getinfo_helper_listeners(control_connection_t *control_conn,
struct sockaddr_storage ss;
socklen_t ss_len = sizeof(ss);
- if (conn->type != type || conn->marked_for_close || conn->s < 0)
+ if (conn->type != type || conn->marked_for_close || !SOCKET_OK(conn->s))
continue;
if (getsockname(conn->s, (struct sockaddr *)&ss, &ss_len) < 0) {
@@ -2010,8 +2032,8 @@ static const getinfo_item_t getinfo_items[] = {
"v2 networkstatus docs as retrieved from a DirPort."),
ITEM("dir/status-vote/current/consensus", dir,
"v3 Networkstatus consensus as retrieved from a DirPort."),
- PREFIX("exit-policy/default", policies,
- "The default value appended to the configured exit policy."),
+ ITEM("exit-policy/default", policies,
+ "The default value appended to the configured exit policy."),
PREFIX("ip-to-country/", geoip, "Perform a GEOIP lookup"),
{ NULL, NULL, NULL, 0 }
};
@@ -2842,6 +2864,43 @@ connection_control_reached_eof(control_connection_t *conn)
return 0;
}
+/** Shut down this Tor instance in the same way that SIGINT would, but
+ * with a log message appropriate for the loss of an owning controller. */
+static void
+lost_owning_controller(const char *owner_type, const char *loss_manner)
+{
+ int shutdown_slowly = server_mode(get_options());
+
+ log_notice(LD_CONTROL, "Owning controller %s has %s -- %s.",
+ owner_type, loss_manner,
+ shutdown_slowly ? "shutting down" : "exiting now");
+
+ /* XXXX Perhaps this chunk of code should be a separate function,
+ * called here and by process_signal(SIGINT). */
+
+ if (!shutdown_slowly) {
+ tor_cleanup();
+ exit(0);
+ }
+ /* XXXX This will close all listening sockets except control-port
+ * listeners. Perhaps we should close those too. */
+ hibernate_begin_shutdown();
+}
+
+/** Called when <b>conn</b> is being freed. */
+void
+connection_control_closed(control_connection_t *conn)
+{
+ tor_assert(conn);
+
+ conn->event_mask = 0;
+ control_update_global_event_mask();
+
+ if (conn->is_owning_control_connection) {
+ lost_owning_controller("connection", "closed");
+ }
+}
+
/** Return true iff <b>cmd</b> is allowable (or at least forgivable) at this
* stage of the protocol. */
static int
@@ -2997,6 +3056,9 @@ connection_control_process_inbuf(control_connection_t *conn)
return 0;
}
+ /* XXXX Why is this not implemented as a table like the GETINFO
+ * items are? Even handling the plus signs at the beginnings of
+ * commands wouldn't be very hard with proper macros. */
cmd_data_len = (uint32_t)data_len;
if (!strcasecmp(conn->incoming_cmd, "SETCONF")) {
if (handle_control_setconf(conn, cmd_data_len, args))
@@ -3022,6 +3084,9 @@ connection_control_process_inbuf(control_connection_t *conn)
} else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) {
if (handle_control_signal(conn, cmd_data_len, args))
return -1;
+ } else if (!strcasecmp(conn->incoming_cmd, "TAKEOWNERSHIP")) {
+ if (handle_control_takeownership(conn, cmd_data_len, args))
+ return -1;
} else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) {
if (handle_control_mapaddress(conn, cmd_data_len, args))
return -1;
@@ -3077,7 +3142,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
{
const char *status;
char extended_buf[96];
- int providing_reason=0;
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
return 0;
tor_assert(circ);
@@ -3101,7 +3165,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
const char *reason_str = circuit_end_reason_to_control_string(reason_code);
char *reason = NULL;
size_t n=strlen(extended_buf);
- providing_reason=1;
if (!reason_str) {
reason = tor_malloc(16);
tor_snprintf(reason, 16, "UNKNOWN_%d", reason_code);
@@ -3884,6 +3947,75 @@ init_cookie_authentication(int enabled)
return 0;
}
+/** A copy of the process specifier of Tor's owning controller, or
+ * NULL if this Tor instance is not currently owned by a process. */
+static char *owning_controller_process_spec = NULL;
+
+/** A process-termination monitor for Tor's owning controller, or NULL
+ * if this Tor instance is not currently owned by a process. */
+static tor_process_monitor_t *owning_controller_process_monitor = NULL;
+
+/** Process-termination monitor callback for Tor's owning controller
+ * process. */
+static void
+owning_controller_procmon_cb(void *unused)
+{
+ (void)unused;
+
+ lost_owning_controller("process", "vanished");
+}
+
+/** Set <b>process_spec</b> as Tor's owning controller process.
+ * Exit on failure. */
+void
+monitor_owning_controller_process(const char *process_spec)
+{
+ const char *msg;
+
+ tor_assert((owning_controller_process_spec == NULL) ==
+ (owning_controller_process_monitor == NULL));
+
+ if (owning_controller_process_spec != NULL) {
+ if ((process_spec != NULL) && !strcmp(process_spec,
+ owning_controller_process_spec)) {
+ /* Same process -- return now, instead of disposing of and
+ * recreating the process-termination monitor. */
+ return;
+ }
+
+ /* We are currently owned by a process, and we should no longer be
+ * owned by it. Free the process-termination monitor. */
+ tor_process_monitor_free(owning_controller_process_monitor);
+ owning_controller_process_monitor = NULL;
+
+ tor_free(owning_controller_process_spec);
+ owning_controller_process_spec = NULL;
+ }
+
+ tor_assert((owning_controller_process_spec == NULL) &&
+ (owning_controller_process_monitor == NULL));
+
+ if (process_spec == NULL)
+ return;
+
+ owning_controller_process_spec = tor_strdup(process_spec);
+ owning_controller_process_monitor =
+ tor_process_monitor_new(tor_libevent_get_base(),
+ owning_controller_process_spec,
+ LD_CONTROL,
+ owning_controller_procmon_cb, NULL,
+ &msg);
+
+ if (owning_controller_process_monitor == NULL) {
+ log_err(LD_BUG, "Couldn't create process-termination monitor for "
+ "owning controller: %s. Exiting.",
+ msg);
+ owning_controller_process_spec = NULL;
+ tor_cleanup();
+ exit(0);
+ }
+}
+
/** Convert the name of a bootstrapping phase <b>s</b> into strings
* <b>tag</b> and <b>summary</b> suitable for display by the controller. */
static int
diff --git a/src/or/control.h b/src/or/control.h
index a73ed5d3c1..ddea4cd548 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -27,6 +27,8 @@ void control_ports_write_to_file(void);
int connection_control_finished_flushing(control_connection_t *conn);
int connection_control_reached_eof(control_connection_t *conn);
+void connection_control_closed(control_connection_t *conn);
+
int connection_control_process_inbuf(control_connection_t *conn);
#define EVENT_AUTHDIR_NEWDESCS 0x000D
@@ -72,6 +74,8 @@ smartlist_t *decode_hashed_passwords(config_line_t *passwords);
void disable_control_logging(void);
void enable_control_logging(void);
+void monitor_owning_controller_process(const char *process_spec);
+
void control_event_bootstrap(bootstrap_status_t status, int progress);
void control_event_bootstrap_problem(const char *warn, int reason);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 7cbc191333..c5e4863f7f 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -226,8 +226,8 @@ cpuworker_main(void *data)
{
char question[ONIONSKIN_CHALLENGE_LEN];
uint8_t question_type;
- int *fdarray = data;
- int fd;
+ tor_socket_t *fdarray = data;
+ tor_socket_t fd;
/* variables for onion processing */
char keys[CPATH_KEY_MATERIAL_LEN];
@@ -317,12 +317,12 @@ cpuworker_main(void *data)
static int
spawn_cpuworker(void)
{
- int *fdarray;
- int fd;
+ tor_socket_t *fdarray;
+ tor_socket_t fd;
connection_t *conn;
int err;
- fdarray = tor_malloc(sizeof(int)*2);
+ fdarray = tor_malloc(sizeof(tor_socket_t)*2);
if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fdarray)) < 0) {
log_warn(LD_NET, "Couldn't construct socketpair for cpuworker: %s",
tor_socket_strerror(-err));
diff --git a/src/or/directory.c b/src/or/directory.c
index b238be2abc..52fec6b61a 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -1901,7 +1901,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
router_get_trusteddirserver_by_digest(conn->identity_digest);
char *rejected_hdr = http_get_header(headers,
"X-Descriptor-Not-New: ");
- int rejected = 0;
if (rejected_hdr) {
if (!strcmp(rejected_hdr, "Yes")) {
log_info(LD_GENERAL,
@@ -1914,7 +1913,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
* last descriptor, not on the published time of the last
* descriptor. If those are different, that's a bad thing to
* do. -NM */
- rejected = 1;
}
tor_free(rejected_hdr);
}
@@ -2004,7 +2002,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
(int)body_len, status_code, escaped(reason));
switch (status_code) {
case 200:
- if (rend_cache_store(body, body_len, 0) < -1) {
+ if (rend_cache_store(body, body_len, 0,
+ conn->rend_data->onion_address) < -1) {
log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
/* Any pending rendezvous attempts will notice when
* connection_about_to_close_connection()
@@ -3272,7 +3271,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
!strcmpstart(url,"/tor/rendezvous/publish")) {
/* rendezvous descriptor post */
log_info(LD_REND, "Handling rendezvous descriptor post.");
- if (rend_cache_store(body, body_len, 1) < 0) {
+ if (rend_cache_store(body, body_len, 1, NULL) < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
"Rejected rend descriptor (length %d) from %s.",
(int)body_len, conn->_base.address);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 96e3df5cec..c6ce9f6776 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -1592,7 +1592,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
* is the same flag as votes[j]->known_flags[b]. */
int *named_flag; /* Index of the flag "Named" for votes[j] */
int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */
- int chosen_named_idx, chosen_unnamed_idx;
+ int chosen_named_idx;
strmap_t *name_to_id_map = strmap_new();
char conflict[DIGEST_LEN];
@@ -1610,7 +1610,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
for (i = 0; i < smartlist_len(votes); ++i)
unnamed_flag[i] = named_flag[i] = -1;
chosen_named_idx = smartlist_string_pos(flags, "Named");
- chosen_unnamed_idx = smartlist_string_pos(flags, "Unnamed");
/* Build the flag index. */
SMARTLIST_FOREACH(votes, networkstatus_t *, v,
diff --git a/src/or/dns.c b/src/or/dns.c
index 61c8f32c98..9b6b98afaf 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -1295,14 +1295,17 @@ configure_nameservers(int force)
nameservers_configured = 1;
if (nameserver_config_failed) {
nameserver_config_failed = 0;
- mark_my_descriptor_dirty();
+ /* XXX the three calls to republish the descriptor might be producing
+ * descriptors that are only cosmetically different, especially on
+ * non-exit relays! -RD */
+ mark_my_descriptor_dirty("dns resolvers back");
}
return 0;
err:
nameservers_configured = 0;
if (! nameserver_config_failed) {
nameserver_config_failed = 1;
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("dns resolvers failed");
}
return -1;
}
@@ -1522,7 +1525,7 @@ add_wildcarded_test_address(const char *address)
"broken.", address, n);
if (!dns_is_completely_invalid) {
dns_is_completely_invalid = 1;
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("dns hijacking confirmed");
}
if (!dns_wildcarded_test_address_notice_given)
control_event_server_status(LOG_WARN, "DNS_USELESS");
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index 243b730cbf..009ab5f344 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -306,7 +306,7 @@ void
dnsserv_configure_listener(connection_t *conn)
{
tor_assert(conn);
- tor_assert(conn->s >= 0);
+ tor_assert(SOCKET_OK(conn->s));
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
conn->dns_server_port =
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index fc005df2d7..42e16aec7a 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -1028,6 +1028,9 @@ request_parse(u8 *packet, ssize_t length, struct evdns_server_port *port, struct
GET16(answers);
GET16(authority);
GET16(additional);
+ (void)additional;
+ (void)authority;
+ (void)answers;
if (flags & 0x8000) return -1; /* Must not be an answer. */
flags &= 0x0110; /* Only RD and CD get preserved. */
@@ -1560,7 +1563,7 @@ evdns_request_data_build(const char *const name, const size_t name_len,
/* exported function */
struct evdns_server_port *
-evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data)
+evdns_add_server_port(tor_socket_t socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data)
{
struct evdns_server_port *port;
if (!(port = mm_malloc(sizeof(struct evdns_server_port))))
@@ -2288,7 +2291,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
+ ns->socket = socket(address->sa_family, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
#ifdef WIN32
{
diff --git a/src/or/eventdns.h b/src/or/eventdns.h
index 2fe4ac9371..3ff8bba4b6 100644
--- a/src/or/eventdns.h
+++ b/src/or/eventdns.h
@@ -319,7 +319,7 @@ typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, vo
#define EVDNS_CLASS_INET 1
-struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
+struct evdns_server_port *evdns_add_server_port(tor_socket_t socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
void evdns_close_server_port(struct evdns_server_port *port);
int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data);
diff --git a/src/or/main.c b/src/or/main.c
index d700f0e7a8..adbde9044f 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -62,8 +62,8 @@ void evdns_shutdown(int);
static void dumpmemusage(int severity);
static void dumpstats(int severity); /* log stats */
-static void conn_read_callback(int fd, short event, void *_conn);
-static void conn_write_callback(int fd, short event, void *_conn);
+static void conn_read_callback(evutil_socket_t fd, short event, void *_conn);
+static void conn_write_callback(evutil_socket_t fd, short event, void *_conn);
static void second_elapsed_callback(periodic_timer_t *timer, void *args);
static int conn_close_if_marked(int i);
static void connection_start_reading_from_linked_conn(connection_t *conn);
@@ -158,7 +158,7 @@ int
connection_add(connection_t *conn)
{
tor_assert(conn);
- tor_assert(conn->s >= 0 ||
+ tor_assert(SOCKET_OK(conn->s) ||
conn->linked ||
(conn->type == CONN_TYPE_AP &&
TO_EDGE_CONN(conn)->is_dns_request));
@@ -167,7 +167,7 @@ connection_add(connection_t *conn)
conn->conn_array_index = smartlist_len(connection_array);
smartlist_add(connection_array, conn);
- if (conn->s >= 0 || conn->linked) {
+ if (SOCKET_OK(conn->s) || conn->linked) {
conn->read_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
conn->write_event = tor_event_new(tor_libevent_get_base(),
@@ -175,7 +175,7 @@ connection_add(connection_t *conn)
}
log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
- conn_type_to_string(conn->type), conn->s, conn->address,
+ conn_type_to_string(conn->type), (int)conn->s, conn->address,
smartlist_len(connection_array));
return 0;
@@ -187,12 +187,12 @@ connection_unregister_events(connection_t *conn)
{
if (conn->read_event) {
if (event_del(conn->read_event))
- log_warn(LD_BUG, "Error removing read event for %d", conn->s);
+ log_warn(LD_BUG, "Error removing read event for %d", (int)conn->s);
tor_free(conn->read_event);
}
if (conn->write_event) {
if (event_del(conn->write_event))
- log_warn(LD_BUG, "Error removing write event for %d", conn->s);
+ log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s);
tor_free(conn->write_event);
}
if (conn->dns_server_port) {
@@ -213,7 +213,7 @@ connection_remove(connection_t *conn)
tor_assert(conn);
log_debug(LD_NET,"removing socket %d (type %s), n_conns now %d",
- conn->s, conn_type_to_string(conn->type),
+ (int)conn->s, conn_type_to_string(conn->type),
smartlist_len(connection_array));
tor_assert(conn->conn_array_index >= 0);
@@ -344,7 +344,7 @@ connection_stop_reading(connection_t *conn)
if (event_del(conn->read_event))
log_warn(LD_NET, "Error from libevent setting read event state for %d "
"to unwatched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -364,7 +364,7 @@ connection_start_reading(connection_t *conn)
if (event_add(conn->read_event, NULL))
log_warn(LD_NET, "Error from libevent setting read event state for %d "
"to watched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -394,7 +394,7 @@ connection_stop_writing(connection_t *conn)
if (event_del(conn->write_event))
log_warn(LD_NET, "Error from libevent setting write event state for %d "
"to unwatched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -415,7 +415,7 @@ connection_start_writing(connection_t *conn)
if (event_add(conn->write_event, NULL))
log_warn(LD_NET, "Error from libevent setting write event state for %d "
"to watched: %s",
- conn->s,
+ (int)conn->s,
tor_socket_strerror(tor_socket_errno(conn->s)));
}
}
@@ -501,13 +501,13 @@ close_closeable_connections(void)
/** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has
* some data to read. */
static void
-conn_read_callback(int fd, short event, void *_conn)
+conn_read_callback(evutil_socket_t fd, short event, void *_conn)
{
connection_t *conn = _conn;
(void)fd;
(void)event;
- log_debug(LD_NET,"socket %d wants to read.",conn->s);
+ log_debug(LD_NET,"socket %d wants to read.",(int)conn->s);
/* assert_connection_ok(conn, time(NULL)); */
@@ -516,7 +516,7 @@ conn_read_callback(int fd, short event, void *_conn)
#ifndef MS_WINDOWS
log_warn(LD_BUG,"Unhandled error on read for %s connection "
"(fd %d); removing",
- conn_type_to_string(conn->type), conn->s);
+ conn_type_to_string(conn->type), (int)conn->s);
tor_fragile_assert();
#endif
if (CONN_IS_EDGE(conn))
@@ -533,13 +533,14 @@ conn_read_callback(int fd, short event, void *_conn)
/** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has
* some data to write. */
static void
-conn_write_callback(int fd, short events, void *_conn)
+conn_write_callback(evutil_socket_t fd, short events, void *_conn)
{
connection_t *conn = _conn;
(void)fd;
(void)events;
- LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.",conn->s));
+ LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.",
+ (int)conn->s));
/* assert_connection_ok(conn, time(NULL)); */
@@ -548,7 +549,7 @@ conn_write_callback(int fd, short events, void *_conn)
/* this connection is broken. remove it. */
log_fn(LOG_WARN,LD_BUG,
"unhandled error on write for %s connection (fd %d); removing",
- conn_type_to_string(conn->type), conn->s);
+ conn_type_to_string(conn->type), (int)conn->s);
tor_fragile_assert();
if (CONN_IS_EDGE(conn)) {
/* otherwise we cry wolf about duplicate close */
@@ -589,8 +590,9 @@ conn_close_if_marked(int i)
assert_connection_ok(conn, now);
/* assert_all_pending_dns_resolves_ok(); */
- log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
- if ((conn->s >= 0 || conn->linked_conn) && connection_wants_to_flush(conn)) {
+ log_debug(LD_NET,"Cleaning up connection (fd %d).",(int)conn->s);
+ if ((SOCKET_OK(conn->s) || conn->linked_conn)
+ && connection_wants_to_flush(conn)) {
/* s == -1 means it's an incomplete edge connection, or that the socket
* has already been closed as unflushable. */
ssize_t sz = connection_bucket_write_limit(conn, now);
@@ -599,7 +601,7 @@ conn_close_if_marked(int i)
"Conn (addr %s, fd %d, type %s, state %d) marked, but wants "
"to flush %d bytes. (Marked at %s:%d)",
escaped_safe_str_client(conn->address),
- conn->s, conn_type_to_string(conn->type), conn->state,
+ (int)conn->s, conn_type_to_string(conn->type), conn->state,
(int)conn->outbuf_flushlen,
conn->marked_for_close_file, conn->marked_for_close);
if (conn->linked_conn) {
@@ -630,7 +632,7 @@ conn_close_if_marked(int i)
if (retval > 0) {
LOG_FN_CONN(conn, (LOG_INFO,LD_NET,
"Holding conn (fd %d) open for more flushing.",
- conn->s));
+ (int)conn->s));
conn->timestamp_lastwritten = now; /* reset so we can flush more */
}
return 0;
@@ -652,7 +654,7 @@ conn_close_if_marked(int i)
"(fd %d, type %s, state %d, marked at %s:%d).",
(int)buf_datalen(conn->outbuf),
escaped_safe_str_client(conn->address),
- conn->s, conn_type_to_string(conn->type), conn->state,
+ (int)conn->s, conn_type_to_string(conn->type), conn->state,
conn->marked_for_close_file,
conn->marked_for_close);
}
@@ -759,7 +761,7 @@ run_connection_housekeeping(int i, time_t now)
(!DIR_CONN_IS_SERVER(conn) &&
conn->timestamp_lastread + DIR_CONN_MAX_STALL < now))) {
log_info(LD_DIR,"Expiring wedged directory conn (fd %d, purpose %d)",
- conn->s, conn->purpose);
+ (int)conn->s, conn->purpose);
/* This check is temporary; it's to let us know whether we should consider
* parsing partial serverdesc responses. */
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
@@ -787,7 +789,7 @@ run_connection_housekeeping(int i, time_t now)
* mark it now. */
log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Too old].",
- conn->s, conn->address, conn->port);
+ (int)conn->s, conn->address, conn->port);
if (conn->state == OR_CONN_STATE_CONNECTING)
connection_or_connect_failed(TO_OR_CONN(conn),
END_OR_CONN_REASON_TIMEOUT,
@@ -798,7 +800,7 @@ run_connection_housekeeping(int i, time_t now)
if (past_keepalive) {
/* We never managed to actually get this connection open and happy. */
log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
- conn->s,conn->address, conn->port);
+ (int)conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
}
} else if (we_are_hibernating() && !or_conn->n_circuits &&
@@ -806,14 +808,14 @@ run_connection_housekeeping(int i, time_t now)
/* We're hibernating, there's no circuits, and nothing to flush.*/
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
- conn->s,conn->address, conn->port);
+ (int)conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
} else if (!or_conn->n_circuits &&
now >= or_conn->timestamp_last_added_nonpadding +
IDLE_OR_CONN_TIMEOUT) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
- "[idle %d].", conn->s,conn->address, conn->port,
+ "[idle %d].", (int)conn->s,conn->address, conn->port,
(int)(now - or_conn->timestamp_last_added_nonpadding));
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
@@ -823,7 +825,7 @@ run_connection_housekeeping(int i, time_t now)
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
"Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
"flush; %d seconds since last write)",
- conn->s, conn->address, conn->port,
+ (int)conn->s, conn->address, conn->port,
(int)buf_datalen(conn->outbuf),
(int)(now-conn->timestamp_lastwritten));
connection_mark_for_close(conn);
@@ -924,8 +926,6 @@ run_scheduled_events(time_t now)
if (time_to_try_getting_descriptors < now) {
update_router_descriptor_downloads(now);
update_extrainfo_downloads(now);
- if (options->UseBridges)
- fetch_bridge_descriptors(options, now);
if (router_have_minimum_dir_info())
time_to_try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL;
else
@@ -938,6 +938,9 @@ run_scheduled_events(time_t now)
now + DESCRIPTOR_FAILURE_RESET_INTERVAL;
}
+ if (options->UseBridges)
+ fetch_bridge_descriptors(options, now);
+
/** 1b. Every MAX_SSL_KEY_LIFETIME seconds, we change our TLS context. */
if (!last_rotated_x509_certificate)
last_rotated_x509_certificate = now;
@@ -1161,7 +1164,10 @@ run_scheduled_events(time_t now)
* it's not comfortable with the number of available circuits.
*/
/* XXXX022 If our circuit build timeout is much lower than a second, maybe
- we should do this more often? */
+ * we should do this more often? -NM
+ * It can't be lower than 1.5 seconds currently; see
+ * circuit_build_times_min_timeout(). -RD
+ */
circuit_expire_building();
/** 3b. Also look at pending streams and prune the ones that 'began'
@@ -1380,7 +1386,7 @@ ip_address_changed(int at_interface)
reset_bandwidth_test();
stats_n_seconds_working = 0;
router_reset_reachability();
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("IP address changed");
}
}
@@ -1699,7 +1705,7 @@ dumpstats(int severity)
int i = conn_sl_idx;
log(severity, LD_GENERAL,
"Conn %d (socket %d) type %d (%s), state %d (%s), created %d secs ago",
- i, conn->s, conn->type, conn_type_to_string(conn->type),
+ i, (int)conn->s, conn->type, conn_type_to_string(conn->type),
conn->state, conn_state_to_string(conn->type, conn->state),
(int)(now - conn->timestamp_created));
if (!connection_is_listener(conn)) {
diff --git a/src/or/or.h b/src/or/or.h
index b9d8319ba5..97fecd1500 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -970,7 +970,7 @@ typedef struct connection_t {
unsigned int proxy_state:4;
/** Our socket; -1 if this connection is closed, or has no socket. */
- evutil_socket_t s;
+ tor_socket_t s;
int conn_array_index; /**< Index into the global connection array. */
struct event *read_event; /**< Libevent event structure. */
struct event *write_event; /**< Libevent event structure. */
@@ -1009,7 +1009,7 @@ typedef struct connection_t {
/* XXXX023 move this field, and all the listener-only fields (just
socket_family, I think), into a new listener_connection_t subtype. */
/** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
- * to the evdns_server_port is uses to listen to and answer connections. */
+ * to the evdns_server_port it uses to listen to and answer connections. */
struct evdns_server_port *dns_server_port;
/** Unique ID for measuring tunneled network status requests. */
@@ -1242,6 +1242,9 @@ typedef struct control_connection_t {
/** True if we have sent a protocolinfo reply on this connection. */
unsigned int have_sent_protocolinfo:1;
+ /** True if we have received a takeownership command on this
+ * connection. */
+ unsigned int is_owning_control_connection:1;
/** Amount of space allocated in incoming_cmd. */
uint32_t incoming_cmd_len;
@@ -2140,6 +2143,11 @@ typedef struct circuit_t {
* in time in order to indicate that a circuit shouldn't be used for new
* streams, but that it can stay alive as long as it has streams on it.
* That's a kludge we should fix.
+ *
+ * XXX023 The CBT code uses this field to record when HS-related
+ * circuits entered certain states. This usage probably won't
+ * interfere with this field's primary purpose, but we should
+ * document it more thoroughly to make sure of that.
*/
time_t timestamp_dirty;
@@ -2674,6 +2682,11 @@ typedef struct {
int DisablePredictedCircuits; /**< Boolean: does Tor preemptively
* make circuits in the background (0),
* or not (1)? */
+
+ /** Process specifier for a controller that ‘owns’ this Tor
+ * instance. Tor will terminate if its owning controller does. */
+ char *OwningControllerProcess;
+
int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how
* long do we wait before exiting? */
char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index af6f43aa28..29b9d260ed 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -278,6 +278,10 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
/* Now, we wait for an ACK or NAK on this circuit. */
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
+ /* Set timestamp_dirty, because circuit_expire_building expects it
+ * to specify when a circuit entered the _C_INTRODUCE_ACK_WAIT
+ * state. */
+ introcirc->_base.timestamp_dirty = time(NULL);
return 0;
perm_err:
@@ -332,6 +336,10 @@ rend_client_introduction_acked(origin_circuit_t *circ,
circ->rend_data->onion_address, CIRCUIT_PURPOSE_C_REND_READY);
if (rendcirc) { /* remember the ack */
rendcirc->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
+ /* Set timestamp_dirty, because circuit_expire_building expects
+ * it to specify when a circuit entered the
+ * _C_REND_READY_INTRO_ACKED state. */
+ rendcirc->_base.timestamp_dirty = time(NULL);
} else {
log_info(LD_REND,"...Found no rend circ. Dropping on the floor.");
}
@@ -677,6 +685,9 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request,
log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
"rendezvous.");
circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY;
+ /* Set timestamp_dirty, because circuit_expire_building expects it
+ * to specify when a circuit entered the _C_REND_READY state. */
+ circ->_base.timestamp_dirty = time(NULL);
/* XXXX023 This is a pretty brute-force approach. It'd be better to
* attach only the connections that are waiting on this circuit, rather
* than trying to attach them all. See comments bug 743. */
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index da33feccbc..4d4a90f61a 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -1015,9 +1015,14 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
*
* The published flag tells us if we store the descriptor
* in our role as directory (1) or if we cache it as client (0).
+ *
+ * If <b>service_id</b> is non-NULL and the descriptor is not for that
+ * service ID, reject it. <b>service_id</b> must be specified if and
+ * only if <b>published</b> is 0 (we fetched this descriptor).
*/
int
-rend_cache_store(const char *desc, size_t desc_len, int published)
+rend_cache_store(const char *desc, size_t desc_len, int published,
+ const char *service_id)
{
rend_cache_entry_t *e;
rend_service_descriptor_t *parsed;
@@ -1035,6 +1040,12 @@ rend_cache_store(const char *desc, size_t desc_len, int published)
rend_service_descriptor_free(parsed);
return -2;
}
+ if ((service_id != NULL) && strcmp(query, service_id)) {
+ log_warn(LD_REND, "Received service descriptor for service ID %s; "
+ "expected descriptor for service ID %s.",
+ query, safe_str(service_id));
+ return -2;
+ }
now = time(NULL);
if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
log_fn(LOG_PROTOCOL_WARN, LD_REND,
@@ -1215,6 +1226,8 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
* If we have an older descriptor with the same ID, replace it.
* If we have any v0 descriptor with the same ID, reject this one in order
* to not get confused with having both versions for the same service.
+ * If the descriptor's service ID does not match
+ * <b>rend_query</b>-\>onion_address, reject it.
* Return -2 if it's malformed or otherwise rejected; return -1 if we
* already have a v0 descriptor here; return 0 if it's the same or older
* than one we've already got; return 1 if it's novel.
@@ -1265,6 +1278,13 @@ rend_cache_store_v2_desc_as_client(const char *desc,
retval = -2;
goto err;
}
+ if (strcmp(rend_query->onion_address, service_id)) {
+ log_warn(LD_REND, "Received service descriptor for service ID %s; "
+ "expected descriptor for service ID %s.",
+ service_id, safe_str(rend_query->onion_address));
+ retval = -2;
+ goto err;
+ }
/* Decode/decrypt introduction points. */
if (intro_content) {
if (rend_query->auth_type != REND_NO_AUTH &&
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index 44b5227cf5..c51039f1f2 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -44,7 +44,8 @@ int rend_cache_lookup_desc(const char *query, int version, const char **desc,
int rend_cache_lookup_entry(const char *query, int version,
rend_cache_entry_t **entry_out);
int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);
-int rend_cache_store(const char *desc, size_t desc_len, int published);
+int rend_cache_store(const char *desc, size_t desc_len, int published,
+ const char *service_id);
int rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query);
int rend_cache_store_v2_desc_as_dir(const char *desc);
diff --git a/src/or/router.c b/src/or/router.c
index 0bd4c55026..874d234ffb 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -85,9 +85,8 @@ set_onion_key(crypto_pk_env_t *k)
tor_mutex_acquire(key_lock);
crypto_free_pk_env(onionkey);
onionkey = k;
- onionkey_set_at = time(NULL);
tor_mutex_release(key_lock);
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("set onion key");
}
/** Return the current onion key. Requires that the onion key has been
@@ -274,7 +273,7 @@ rotate_onion_key(void)
now = time(NULL);
state->LastRotatedOnionKey = onionkey_set_at = now;
tor_mutex_release(key_lock);
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("rotated onion key");
or_state_mark_dirty(state, get_options()->AvoidDiskWrites ? now+3600 : 0);
goto done;
error:
@@ -491,8 +490,8 @@ init_keys(void)
char fingerprint_line[MAX_NICKNAME_LEN+FINGERPRINT_LEN+3];
const char *mydesc;
crypto_pk_env_t *prkey;
- char digest[20];
- char v3_digest[20];
+ char digest[DIGEST_LEN];
+ char v3_digest[DIGEST_LEN];
char *cp;
or_options_t *options = get_options();
authority_type_t type;
@@ -504,7 +503,8 @@ init_keys(void)
if (!key_lock)
key_lock = tor_mutex_new();
- /* There are a couple of paths that put us here before */
+ /* There are a couple of paths that put us here before we've asked
+ * openssl to initialize itself. */
if (crypto_global_init(get_options()->HardwareAccel,
get_options()->AccelName,
get_options()->AccelDir)) {
@@ -908,7 +908,7 @@ router_orport_found_reachable(void)
get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("ORPort found reachable");
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
me->address, me->or_port);
@@ -925,7 +925,7 @@ router_dirport_found_reachable(void)
"from the outside. Excellent.");
can_reach_dir_port = 1;
if (decide_to_advertise_dirport(get_options(), me->dir_port))
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("DirPort found reachable");
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
me->address, me->dir_port);
@@ -1232,6 +1232,10 @@ router_upload_dir_desc_to_dirservers(int force)
return;
if (!force && !desc_needs_upload)
return;
+
+ log_info(LD_OR, "Uploading relay descriptor to directory authorities%s",
+ force ? " (forced)" : "");
+
desc_needs_upload = 0;
desc_len = ri->cache_info.signed_descriptor_len;
@@ -1423,6 +1427,8 @@ router_rebuild_descriptor(int force)
return -1;
}
+ log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : "");
+
ri = tor_malloc_zero(sizeof(routerinfo_t));
ri->cache_info.routerlist_index = -1;
ri->address = tor_dup_ip(addr);
@@ -1597,14 +1603,15 @@ void
mark_my_descriptor_dirty_if_older_than(time_t when)
{
if (desc_clean_since < when)
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("time for new descriptor");
}
/** Call when the current descriptor is out of date. */
void
-mark_my_descriptor_dirty(void)
+mark_my_descriptor_dirty(const char *reason)
{
desc_clean_since = 0;
+ log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
}
/** How frequently will we republish our descriptor because of large (factor
@@ -1629,7 +1636,7 @@ check_descriptor_bandwidth_changed(time_t now)
if (last_changed+MAX_BANDWIDTH_CHANGE_FREQ < now) {
log_info(LD_GENERAL,
"Measured bandwidth has changed; rebuilding descriptor.");
- mark_my_descriptor_dirty();
+ mark_my_descriptor_dirty("bandwidth has changed");
last_changed = now;
}
}
diff --git a/src/or/router.h b/src/or/router.h
index a285a3e773..a27c1d92c5 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -62,7 +62,7 @@ int should_refuse_unknown_exits(or_options_t *options);
void router_upload_dir_desc_to_dirservers(int force);
void mark_my_descriptor_dirty_if_older_than(time_t when);
-void mark_my_descriptor_dirty(void);
+void mark_my_descriptor_dirty(const char *reason);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
void router_new_address_suggestion(const char *suggestion,
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index a877cdff84..1dcbc6a184 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1463,6 +1463,11 @@ router_parse_entry_from_string(const char *s, const char *end,
goto err;
tok = find_by_keyword(tokens, K_ONION_KEY);
+ if (!crypto_pk_public_exponent_ok(tok->key)) {
+ log_warn(LD_DIR,
+ "Relay's onion key had invalid exponent.");
+ goto err;
+ }
router->onion_pkey = tok->key;
tok->key = NULL; /* Prevent free */
@@ -4332,6 +4337,11 @@ microdescs_parse_from_string(const char *s, const char *eos,
}
tok = find_by_keyword(tokens, K_ONION_KEY);
+ if (!crypto_pk_public_exponent_ok(tok->key)) {
+ log_warn(LD_DIR,
+ "Relay's onion key had invalid exponent.");
+ goto next;
+ }
md->onion_pkey = tok->key;
tok->key = NULL;
@@ -4983,10 +4993,22 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
}
/* Parse onion key. */
tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
+ if (!crypto_pk_public_exponent_ok(tok->key)) {
+ log_warn(LD_REND,
+ "Introduction point's onion key had invalid exponent.");
+ rend_intro_point_free(intro);
+ goto err;
+ }
info->onion_key = tok->key;
tok->key = NULL; /* Prevent free */
/* Parse service key. */
tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
+ if (!crypto_pk_public_exponent_ok(tok->key)) {
+ log_warn(LD_REND,
+ "Introduction point key had invalid exponent.");
+ rend_intro_point_free(intro);
+ goto err;
+ }
intro->intro_key = tok->key;
tok->key = NULL; /* Prevent free */
/* Add extend info to list of introduction points. */
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 781081a4ad..bf2cc48174 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -69,7 +69,7 @@ test_crypto_rng(void)
uint64_t big;
char *host;
j = crypto_rand_int(100);
- if (i < 0 || i >= 100)
+ if (j < 0 || j >= 100)
allok = 0;
big = crypto_rand_uint64(U64_LITERAL(1)<<40);
if (big >= (U64_LITERAL(1)<<40))
@@ -240,11 +240,13 @@ test_crypto_sha(void)
/* Test SHA-1 with a test vector from the specification. */
i = crypto_digest(data, "abc", 3);
test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D");
+ tt_int_op(i, ==, 0);
/* Test SHA-256 with a test vector from the specification. */
i = crypto_digest256(data, "abc", 3, DIGEST_SHA256);
test_memeq_hex(data, "BA7816BF8F01CFEA414140DE5DAE2223B00361A3"
"96177A9CB410FF61F20015AD");
+ tt_int_op(i, ==, 0);
/* Test HMAC-SHA-1 with test cases from RFC2202. */
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 12349d9d12..8c4d3f6483 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -319,7 +319,7 @@ main(int argc, char **argv)
{
uint32_t sockshost;
uint16_t socksport = 0, port_option = 0;
- int isSocks4 = 0, isVerbose = 0, isReverse = 0, force = 0;
+ int isSocks4 = 0, isVerbose = 0, isReverse = 0;
char **arg;
int n_args;
struct in_addr a;
@@ -349,8 +349,6 @@ main(int argc, char **argv)
isSocks4 = 0;
else if (!strcmp("-x", arg[0]))
isReverse = 1;
- else if (!strcmp("-F", arg[0]))
- force = 1;
else if (!strcmp("-p", arg[0])) {
int p;
if (n_args < 2) {