summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/buffers.c11
-rw-r--r--src/or/channelpadding.c16
-rw-r--r--src/or/connection_or.c4
-rw-r--r--src/or/consdiffmgr.c24
-rw-r--r--src/or/consdiffmgr.h3
-rw-r--r--src/or/control.c2
-rw-r--r--src/or/cpuworker.c2
-rw-r--r--src/or/directory.c56
-rw-r--r--src/or/dirserv.c6
-rw-r--r--src/or/entrynodes.c36
-rw-r--r--src/or/main.c4
11 files changed, 140 insertions, 24 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 3692ed4d08..12a6c0239b 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -2092,7 +2092,7 @@ fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
int
write_to_buf_compress(buf_t *buf, tor_compress_state_t *state,
const char *data, size_t data_len,
- int done)
+ const int done)
{
char *next;
size_t old_avail, avail;
@@ -2114,8 +2114,10 @@ write_to_buf_compress(buf_t *buf, tor_compress_state_t *state,
case TOR_COMPRESS_ERROR:
return -1;
case TOR_COMPRESS_OK:
- if (data_len == 0)
+ if (data_len == 0) {
+ tor_assert_nonfatal(!done);
over = 1;
+ }
break;
case TOR_COMPRESS_BUFFER_FULL:
if (avail) {
@@ -2124,6 +2126,11 @@ write_to_buf_compress(buf_t *buf, tor_compress_state_t *state,
* whether were going to or not. */
need_new_chunk = 1;
}
+ if (data_len == 0 && !done) {
+ /* We've consumed all the input data, though, so there's no
+ * point in forging ahead right now. */
+ over = 1;
+ }
break;
}
buf->datalen += old_avail - avail;
diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c
index f5248e8960..bed2489837 100644
--- a/src/or/channelpadding.c
+++ b/src/or/channelpadding.c
@@ -530,10 +530,20 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan)
>= chan->next_padding_time_ms) {
int64_t ms_until_pad_for_netflow = chan->next_padding_time_ms -
long_now;
+ /* If the padding time is in the past, that means that libevent delayed
+ * calling the once-per-second callback due to other work taking too long.
+ * See https://bugs.torproject.org/22212 and
+ * https://bugs.torproject.org/16585. This is a systemic problem
+ * with being single-threaded, but let's emit a notice if this
+ * is long enough in the past that we might have missed a netflow window,
+ * and allowed a router to emit a netflow frame, just so we don't forget
+ * about it entirely.. */
+#define NETFLOW_MISSED_WINDOW (150000 - DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH)
if (ms_until_pad_for_netflow < 0) {
- log_warn(LD_BUG,
- "Channel padding timeout scheduled "I64_FORMAT"ms in the past. "
- "Did the monotonic clock just jump?",
+ int severity = (ms_until_pad_for_netflow < -NETFLOW_MISSED_WINDOW)
+ ? LOG_NOTICE : LOG_INFO;
+ log_fn(severity, LD_OR,
+ "Channel padding timeout scheduled "I64_FORMAT"ms in the past. ",
I64_PRINTF_ARG(-ms_until_pad_for_netflow));
return 0; /* Clock jumped: Send padding now */
}
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index ab0f411cc5..753148291c 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -420,9 +420,11 @@ cell_pack(packed_cell_t *dst, const cell_t *src, int wide_circ_ids)
set_uint32(dest, htonl(src->circ_id));
dest += 4;
} else {
+ /* Clear the last two bytes of dest, in case we can accidentally
+ * send them to the network somehow. */
+ memset(dest+CELL_MAX_NETWORK_SIZE-2, 0, 2);
set_uint16(dest, htons(src->circ_id));
dest += 2;
- memset(dest+CELL_MAX_NETWORK_SIZE-2, 0, 2); /*make sure it's clear */
}
set_uint8(dest, src->command);
memcpy(dest+1, src->payload, CELL_PAYLOAD_SIZE);
diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c
index 2af104733b..638fcd6794 100644
--- a/src/or/consdiffmgr.c
+++ b/src/or/consdiffmgr.c
@@ -325,7 +325,8 @@ cdm_diff_ht_purge(consensus_flavor_t flav,
if ((*diff)->cdm_diff_status == CDM_DIFF_PRESENT &&
flav == (*diff)->flavor) {
- if (consensus_cache_entry_handle_get((*diff)->entry) == NULL) {
+ if (BUG((*diff)->entry == NULL) ||
+ consensus_cache_entry_handle_get((*diff)->entry) == NULL) {
/* the underlying entry has gone away; drop this. */
next = HT_NEXT_RMV(cdm_diff_ht, &cdm_diff_ht, diff);
cdm_diff_free(this);
@@ -622,6 +623,9 @@ consdiffmgr_find_diff_from(consensus_cache_entry_t **entry_out,
return CONSDIFF_IN_PROGRESS;
}
+ if (BUG(ent->entry == NULL)) {
+ return CONSDIFF_NOT_FOUND;
+ }
*entry_out = consensus_cache_entry_handle_get(ent->entry);
return (*entry_out) ? CONSDIFF_AVAILABLE : CONSDIFF_NOT_FOUND;
@@ -1840,3 +1844,21 @@ consensus_cache_entry_get_valid_until(const consensus_cache_entry_t *ent,
return 0;
}
+/** Read the valid after timestamp from the cached object <b>ent</b> into
+ * *<b>out</b> and return 0, or return -1 if no such time was recorded. */
+int
+consensus_cache_entry_get_valid_after(const consensus_cache_entry_t *ent,
+ time_t *out)
+{
+ tor_assert(ent);
+ tor_assert(out);
+
+ const char *s;
+ s = consensus_cache_entry_get_value(ent, LABEL_VALID_AFTER);
+
+ if (s == NULL || parse_iso_time_nospace(s, out) < 0)
+ return -1;
+ else
+ return 0;
+}
+
diff --git a/src/or/consdiffmgr.h b/src/or/consdiffmgr.h
index fe4f9ee239..079f9fe2d2 100644
--- a/src/or/consdiffmgr.h
+++ b/src/or/consdiffmgr.h
@@ -44,6 +44,9 @@ int consensus_cache_entry_get_fresh_until(
int consensus_cache_entry_get_valid_until(
const struct consensus_cache_entry_t *ent,
time_t *out);
+int consensus_cache_entry_get_valid_after(
+ const struct consensus_cache_entry_t *ent,
+ time_t *out);
void consdiffmgr_rescan(void);
int consdiffmgr_cleanup(void);
diff --git a/src/or/control.c b/src/or/control.c
index 9454a7ab67..9bcf1ee364 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -6506,7 +6506,7 @@ monitor_owning_controller_process(const char *process_spec)
msg);
owning_controller_process_spec = NULL;
tor_cleanup();
- exit(0);
+ exit(1);
}
}
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index af79fafaa6..1013fa555e 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -475,7 +475,7 @@ queue_pending_tasks(void)
return;
if (assign_onionskin_to_cpuworker(circ, onionskin))
- log_warn(LD_OR,"assign_to_cpuworker failed. Ignoring.");
+ log_info(LD_OR,"assign_to_cpuworker failed. Ignoring.");
}
}
diff --git a/src/or/directory.c b/src/or/directory.c
index ac40e54ceb..45fbd1dd33 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3920,6 +3920,30 @@ find_best_compression_method(unsigned compression_methods, int stream)
return NO_METHOD;
}
+/** Check if any of the digests in <b>digests</b> matches the latest consensus
+ * flavor (given in <b>flavor</b>) that we have available. */
+static int
+digest_list_contains_best_consensus(consensus_flavor_t flavor,
+ const smartlist_t *digests)
+{
+ const networkstatus_t *ns = NULL;
+
+ if (digests == NULL)
+ return 0;
+
+ ns = networkstatus_get_latest_consensus_by_flavor(flavor);
+
+ if (ns == NULL)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, digest) {
+ if (tor_memeq(ns->digest_sha3_as_signed, digest, DIGEST256_LEN))
+ return 1;
+ } SMARTLIST_FOREACH_END(digest);
+
+ return 0;
+}
+
/** Check if the given compression method is allowed for a connection that is
* supposed to be anonymous. Returns 1 if the compression method is allowed,
* otherwise 0. */
@@ -4089,6 +4113,13 @@ handle_get_current_consensus(dir_connection_t *conn,
goto done;
}
+ if (digest_list_contains_best_consensus(req.flav,
+ req.diff_from_digests)) {
+ write_http_status_line(conn, 304, "Not modified");
+ geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
+ goto done;
+ }
+
struct consensus_cache_entry_t *cached_consensus = NULL;
compress_method_t compression_used = NO_METHOD;
@@ -4227,13 +4258,14 @@ static int
handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
{
const char *url = args->url;
- const compress_method_t compress_method =
- find_best_compression_method(args->compression_supported, 1);
{
int current;
ssize_t body_len = 0;
ssize_t estimated_len = 0;
+ /* This smartlist holds strings that we can compress on the fly. */
smartlist_t *items = smartlist_new();
+ /* This smartlist holds cached_dir_t objects that have a precompressed
+ * deflated version. */
smartlist_t *dir_items = smartlist_new();
int lifetime = 60; /* XXXX?? should actually use vote intervals. */
url += strlen("/tor/status-vote/");
@@ -4284,6 +4316,26 @@ handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
write_http_status_line(conn, 404, "Not found");
goto vote_done;
}
+
+ /* We're sending items from at most one kind of source */
+ tor_assert_nonfatal(smartlist_len(items) == 0 ||
+ smartlist_len(dir_items) == 0);
+
+ int streaming;
+ unsigned mask;
+ if (smartlist_len(items)) {
+ /* We're taking strings and compressing them on the fly. */
+ streaming = 1;
+ mask = ~0u;
+ } else {
+ /* We're taking cached_dir_t objects. We only have them uncompressed
+ * or deflated. */
+ streaming = 0;
+ mask = (1u<<NO_METHOD) | (1u<<ZLIB_METHOD);
+ }
+ const compress_method_t compress_method = find_best_compression_method(
+ args->compression_supported&mask, streaming);
+
SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
body_len += compress_method != NO_METHOD ?
d->dir_compressed_len : d->dir_len);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 408f58b22b..4954471c6a 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -14,6 +14,7 @@
#include "connection.h"
#include "connection_or.h"
#include "conscache.h"
+#include "consdiffmgr.h"
#include "control.h"
#include "directory.h"
#include "dirserv.h"
@@ -3518,6 +3519,11 @@ spooled_resource_estimate_size(const spooled_resource_t *spooled,
} else {
cached_dir_t *cached;
if (spooled->consensus_cache_entry) {
+ if (published_out) {
+ consensus_cache_entry_get_valid_after(
+ spooled->consensus_cache_entry, published_out);
+ }
+
return spooled->cce_len;
}
if (spooled->cached_dir_ref) {
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index dc2cab28f7..be9f85a89f 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1093,6 +1093,18 @@ select_and_add_guard_item_for_sample(guard_selection_t *gs,
return added_guard;
}
+/** Return true iff we need a consensus to maintain our */
+static int
+live_consensus_is_missing(const guard_selection_t *gs)
+{
+ tor_assert(gs);
+ if (gs->type == GS_TYPE_BRIDGE) {
+ /* We don't update bridges from the consensus; they aren't there. */
+ return 0;
+ }
+ return networkstatus_get_live_consensus(approx_time()) == NULL;
+}
+
/**
* Add new guards to the sampled guards in <b>gs</b> until there are
* enough usable filtered guards, but never grow the sample beyond its
@@ -1104,6 +1116,13 @@ entry_guards_expand_sample(guard_selection_t *gs)
{
tor_assert(gs);
const or_options_t *options = get_options();
+
+ if (live_consensus_is_missing(gs)) {
+ log_info(LD_GUARD, "Not expanding the sample guard set; we have "
+ "no live consensus.");
+ return NULL;
+ }
+
int n_sampled = smartlist_len(gs->sampled_entry_guards);
entry_guard_t *added_guard = NULL;
int n_usable_filtered_guards = num_reachable_filtered_guards(gs, NULL);
@@ -1212,18 +1231,13 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
// It's important to use only a live consensus here; we don't want to
// make changes based on anything expired or old.
- if (gs->type != GS_TYPE_BRIDGE) {
- networkstatus_t *ns = networkstatus_get_live_consensus(approx_time());
-
- if (! ns) {
- log_info(LD_GUARD, "No live consensus; can't update "
- "sampled entry guards.");
- return;
- } else {
- log_info(LD_GUARD, "Updating sampled guard status based on received "
- "consensus.");
- }
+ if (live_consensus_is_missing(gs)) {
+ log_info(LD_GUARD, "Not updating the sample guard set; we have "
+ "no live consensus.");
+ return;
}
+ log_info(LD_GUARD, "Updating sampled guard status based on received "
+ "consensus.");
int n_changes = 0;
diff --git a/src/or/main.c b/src/or/main.c
index 9699c8d381..cb24fd18c8 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1556,7 +1556,7 @@ check_ed_keys_callback(time_t now, const or_options_t *options)
generate_ed_link_cert(options, now, new_signing_key > 0)) {
log_err(LD_OR, "Unable to update Ed25519 keys! Exiting.");
tor_cleanup();
- exit(0);
+ exit(1);
}
}
return 30;
@@ -3168,7 +3168,7 @@ try_locking(const or_options_t *options, int err_if_locked)
r = try_locking(options, 0);
if (r<0) {
log_err(LD_GENERAL, "No, it's still there. Exiting.");
- exit(0);
+ exit(1);
}
return r;
}