summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/channel.c11
-rw-r--r--src/or/channel.h6
-rw-r--r--src/or/channeltls.c2
-rw-r--r--src/or/circuitbuild.c72
-rw-r--r--src/or/circuitlist.c38
-rw-r--r--src/or/circuitlist.h2
-rw-r--r--src/or/circuitmux.c36
-rw-r--r--src/or/circuitmux.h4
-rw-r--r--src/or/circuituse.c99
-rw-r--r--src/or/circuituse.h1
-rw-r--r--src/or/command.c53
-rw-r--r--src/or/config.c57
-rw-r--r--src/or/connection.c64
-rw-r--r--src/or/connection_or.c46
-rw-r--r--src/or/connection_or.h2
-rw-r--r--[-rwxr-xr-x]src/or/control.c0
-rw-r--r--src/or/cpuworker.c10
-rw-r--r--src/or/directory.c6
-rw-r--r--src/or/dirserv.c2
-rw-r--r--src/or/main.c103
-rw-r--r--src/or/ntmain.h2
-rw-r--r--src/or/or.h12
-rw-r--r--src/or/relay.c21
-rw-r--r--src/or/relay.h2
-rw-r--r--[-rwxr-xr-x]src/or/router.c3
-rw-r--r--src/or/routerlist.c25
-rw-r--r--src/or/routerlist.h3
27 files changed, 467 insertions, 215 deletions
diff --git a/src/or/channel.c b/src/or/channel.c
index 63af2f91c0..1cc786487a 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -112,7 +112,9 @@ HT_GENERATE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
static cell_queue_entry_t * cell_queue_entry_dup(cell_queue_entry_t *q);
static void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off);
+#if 0
static int cell_queue_entry_is_padding(cell_queue_entry_t *q);
+#endif
static cell_queue_entry_t *
cell_queue_entry_new_fixed(cell_t *cell);
static cell_queue_entry_t *
@@ -726,7 +728,7 @@ channel_init(channel_t *chan)
chan->global_identifier = n_channels_allocated++;
/* Init timestamp */
- chan->timestamp_last_added_nonpadding = time(NULL);
+ chan->timestamp_last_had_circuits = time(NULL);
/* Warn about exhausted circuit IDs no more than hourly. */
chan->last_warned_circ_ids_exhausted.rate = 3600;
@@ -1595,6 +1597,7 @@ cell_queue_entry_free(cell_queue_entry_t *q, int handed_off)
tor_free(q);
}
+#if 0
/**
* Check whether a cell queue entry is padding; this is a helper function
* for channel_write_cell_queue_entry()
@@ -1623,6 +1626,7 @@ cell_queue_entry_is_padding(cell_queue_entry_t *q)
return 0;
}
+#endif
/**
* Allocate a new cell queue entry for a fixed-size cell
@@ -1681,11 +1685,6 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
chan->state == CHANNEL_STATE_OPEN ||
chan->state == CHANNEL_STATE_MAINT);
- /* Increment the timestamp unless it's padding */
- if (!cell_queue_entry_is_padding(q)) {
- chan->timestamp_last_added_nonpadding = approx_time();
- }
-
{
circid_t circ_id;
if (is_destroy_cell(chan, q, &circ_id)) {
diff --git a/src/or/channel.h b/src/or/channel.h
index bd9a02f323..3e164c6892 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -187,8 +187,10 @@ struct channel_s {
time_t timestamp_recv; /* Cell received from lower layer */
time_t timestamp_xmit; /* Cell sent to lower layer */
- /* Timestamp for relay.c */
- time_t timestamp_last_added_nonpadding;
+ /** Timestamp for run_connection_housekeeping(). We update this once a
+ * second when we run housekeeping and find a circuit on this channel, and
+ * whenever we add a circuit to the channel. */
+ time_t timestamp_last_had_circuits;
/** Unique ID for measuring direct network status requests;vtunneled ones
* come over a circuit_t, which has a dirreq_id field as well, but is a
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 539ead193e..632bc328b7 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1554,7 +1554,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
return;
}
if (tor_addr_eq(&addr, &(chan->conn->real_addr))) {
- chan->conn->is_canonical = 1;
+ connection_or_set_canonical(chan->conn, 1);
break;
}
cp = next;
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 9d06759dec..283afee31f 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -96,10 +96,12 @@ get_unique_circ_id_by_chan(channel_t *chan)
* N=256. */
#define MAX_CIRCID_ATTEMPTS 64
int in_use;
- unsigned n_with_circ = 0, n_pending_destroy = 0;
+ unsigned n_with_circ = 0, n_pending_destroy = 0, n_weird_pending_destroy = 0;
circid_t test_circ_id;
circid_t attempts=0;
circid_t high_bit, max_range, mask;
+ int64_t pending_destroy_time_total = 0;
+ int64_t pending_destroy_time_max = 0;
tor_assert(chan);
@@ -130,15 +132,59 @@ get_unique_circ_id_by_chan(channel_t *chan)
* whole circuit ID space every time we extend a circuit, which is
* not so great either.
*/
- log_fn_ratelim(&chan->last_warned_circ_ids_exhausted, LOG_WARN,
- LD_CIRC,"No unused circIDs found on channel %s wide "
+ int64_t queued_destroys;
+ char *m = rate_limit_log(&chan->last_warned_circ_ids_exhausted,
+ approx_time());
+ if (m == NULL)
+ return 0; /* This message has been rate-limited away. */
+ if (n_pending_destroy)
+ pending_destroy_time_total /= n_pending_destroy;
+ log_warn(LD_CIRC,"No unused circIDs found on channel %s wide "
"circID support, with %u inbound and %u outbound circuits. "
"Found %u circuit IDs in use by circuits, and %u with "
- "pending destroy cells."
- "Failing a circuit.",
+ "pending destroy cells. (%u of those were marked bogusly.) "
+ "The ones with pending destroy cells "
+ "have been marked unusable for an average of %ld seconds "
+ "and a maximum of %ld seconds. This channel is %ld seconds "
+ "old. Failing a circuit.%s",
chan->wide_circ_ids ? "with" : "without",
chan->num_p_circuits, chan->num_n_circuits,
- n_with_circ, n_pending_destroy);
+ n_with_circ, n_pending_destroy, n_weird_pending_destroy,
+ (long)pending_destroy_time_total,
+ (long)pending_destroy_time_max,
+ (long)(approx_time() - chan->timestamp_created),
+ m);
+ tor_free(m);
+
+ if (!chan->cmux) {
+ /* This warning should be impossible. */
+ log_warn(LD_BUG, " This channel somehow has no cmux on it!");
+ return 0;
+ }
+
+ /* analysis so far on 12184 suggests that we're running out of circuit
+ IDs because it looks like we have too many pending destroy
+ cells. Let's see how many we really have pending.
+ */
+ queued_destroys = circuitmux_count_queued_destroy_cells(chan,
+ chan->cmux);
+
+ log_warn(LD_CIRC, " Circuitmux on this channel has %u circuits, "
+ "of which %u are active. It says it has "I64_FORMAT
+ " destroy cells queued.",
+ circuitmux_num_circuits(chan->cmux),
+ circuitmux_num_active_circuits(chan->cmux),
+ I64_PRINTF_ARG(queued_destroys));
+
+ /* Change this into "if (1)" in order to get more information about
+ * possible failure modes here. You'll need to know how to use gdb with
+ * Tor: this will make Tor exit with an assertion failure if the cmux is
+ * corrupt. */
+ if (0)
+ circuitmux_assert_okay(chan->cmux);
+
+ channel_dump_statistics(chan, LOG_WARN);
+
return 0;
}
@@ -152,8 +198,20 @@ get_unique_circ_id_by_chan(channel_t *chan)
in_use = circuit_id_in_use_on_channel(test_circ_id, chan);
if (in_use == 1)
++n_with_circ;
- else if (in_use == 2)
+ else if (in_use == 2) {
+ time_t since_when;
++n_pending_destroy;
+ since_when =
+ circuit_id_when_marked_unusable_on_channel(test_circ_id, chan);
+ if (since_when) {
+ time_t waiting = approx_time() - since_when;
+ pending_destroy_time_total += waiting;
+ if (waiting > pending_destroy_time_max)
+ pending_destroy_time_max = waiting;
+ } else {
+ ++n_weird_pending_destroy;
+ }
+ }
} while (in_use);
return test_circ_id;
}
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 6238e08e1e..f3a83503ef 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -59,6 +59,8 @@ typedef struct chan_circid_circuit_map_t {
channel_t *chan;
circid_t circ_id;
circuit_t *circuit;
+ /* For debugging 12184: when was this placeholder item added? */
+ time_t made_placeholder_at;
} chan_circid_circuit_map_t;
/** Helper for hash tables: compare the channel and circuit ID for a and
@@ -184,6 +186,7 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
if (found) {
found->circuit = circ;
+ found->made_placeholder_at = 0;
} else {
found = tor_malloc_zero(sizeof(chan_circid_circuit_map_t));
found->circ_id = id;
@@ -241,11 +244,14 @@ channel_mark_circid_unusable(channel_t *chan, circid_t id)
"a circuit there.", (unsigned)id, chan);
} else if (ent) {
/* It's already marked. */
+ if (!ent->made_placeholder_at)
+ ent->made_placeholder_at = approx_time();
} else {
ent = tor_malloc_zero(sizeof(chan_circid_circuit_map_t));
ent->chan = chan;
ent->circ_id = id;
- /* leave circuit at NULL */
+ /* leave circuit at NULL. */
+ ent->made_placeholder_at = approx_time();
HT_INSERT(chan_circid_map, &chan_circid_map, ent);
}
}
@@ -328,10 +334,13 @@ circuit_set_p_circid_chan(or_circuit_t *or_circ, circid_t id,
circuit_set_circid_chan_helper(circ, CELL_DIRECTION_IN, id, chan);
- if (chan)
+ if (chan) {
tor_assert(bool_eq(or_circ->p_chan_cells.n,
or_circ->next_active_on_p_chan));
+ chan->timestamp_last_had_circuits = approx_time();
+ }
+
if (circ->p_delete_pending && old_chan) {
channel_mark_circid_unusable(old_chan, old_id);
circ->p_delete_pending = 0;
@@ -350,9 +359,12 @@ circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
circuit_set_circid_chan_helper(circ, CELL_DIRECTION_OUT, id, chan);
- if (chan)
+ if (chan) {
tor_assert(bool_eq(circ->n_chan_cells.n, circ->next_active_on_n_chan));
+ chan->timestamp_last_had_circuits = approx_time();
+ }
+
if (circ->n_delete_pending && old_chan) {
channel_mark_circid_unusable(old_chan, old_id);
circ->n_delete_pending = 0;
@@ -1090,6 +1102,26 @@ circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan)
return 0;
}
+/** Helper for debugging 12184. Returns the time since which 'circ_id' has
+ * been marked unusable on 'chan'. */
+time_t
+circuit_id_when_marked_unusable_on_channel(circid_t circ_id, channel_t *chan)
+{
+ chan_circid_circuit_map_t search;
+ chan_circid_circuit_map_t *found;
+
+ memset(&search, 0, sizeof(search));
+ search.circ_id = circ_id;
+ search.chan = chan;
+
+ found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
+
+ if (! found || found->circuit)
+ return 0;
+
+ return found->made_placeholder_at;
+}
+
/** Return the circuit that a given edge connection is using. */
circuit_t *
circuit_get_by_edge_conn(edge_connection_t *conn)
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index 916afba215..d48d7c3963 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -28,6 +28,8 @@ void circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
channel_t *chan);
void channel_mark_circid_unusable(channel_t *chan, circid_t id);
void channel_mark_circid_usable(channel_t *chan, circid_t id);
+time_t circuit_id_when_marked_unusable_on_channel(circid_t circ_id,
+ channel_t *chan);
void circuit_set_state(circuit_t *circ, uint8_t state);
void circuit_close_all_marked(void);
int32_t circuit_initial_package_window(void);
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index 52ebfef084..55580d5c29 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -1909,3 +1909,39 @@ circuitmux_append_destroy_cell(channel_t *chan,
}
}
+/*DOCDOC; for debugging 12184. This runs slowly. */
+int64_t
+circuitmux_count_queued_destroy_cells(const channel_t *chan,
+ const circuitmux_t *cmux)
+{
+ int64_t n_destroy_cells = cmux->destroy_ctr;
+ int64_t destroy_queue_size = cmux->destroy_cell_queue.n;
+
+ int64_t manual_total = 0;
+ int64_t manual_total_in_map = 0;
+ packed_cell_t *cell;
+
+ TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
+ circid_t id;
+ ++manual_total;
+
+ id = packed_cell_get_circid(cell, chan->wide_circ_ids);
+ if (circuit_id_in_use_on_channel(id, (channel_t*)chan))
+ ++manual_total_in_map;
+ }
+
+ if (n_destroy_cells != destroy_queue_size ||
+ n_destroy_cells != manual_total ||
+ n_destroy_cells != manual_total_in_map) {
+ log_warn(LD_BUG, " Discrepancy in counts for queued destroy cells on "
+ "circuitmux. n="I64_FORMAT". queue_size="I64_FORMAT". "
+ "manual_total="I64_FORMAT". manual_total_in_map="I64_FORMAT".",
+ I64_PRINTF_ARG(n_destroy_cells),
+ I64_PRINTF_ARG(destroy_queue_size),
+ I64_PRINTF_ARG(manual_total),
+ I64_PRINTF_ARG(manual_total_in_map));
+ }
+
+ return n_destroy_cells;
+}
+
diff --git a/src/or/circuitmux.h b/src/or/circuitmux.h
index c4c0649c6c..2b5fb7e51e 100644
--- a/src/or/circuitmux.h
+++ b/src/or/circuitmux.h
@@ -121,6 +121,10 @@ unsigned int circuitmux_num_cells(circuitmux_t *cmux);
unsigned int circuitmux_num_circuits(circuitmux_t *cmux);
unsigned int circuitmux_num_active_circuits(circuitmux_t *cmux);
+/* Debuging interface - slow. */
+int64_t circuitmux_count_queued_destroy_cells(const channel_t *chan,
+ const circuitmux_t *cmux);
+
/* Channel interface */
circuit_t * circuitmux_get_first_active_circuit(circuitmux_t *cmux,
cell_queue_t **destroy_queue_out);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 467bef652f..714754a672 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -783,6 +783,10 @@ circuit_expire_building(void)
}
}
+/** For debugging #8387: track when we last called
+ * circuit_expire_old_circuits_clientside. */
+static time_t last_expired_clientside_circuits = 0;
+
/**
* As a diagnostic for bug 8387, log information about how many one-hop
* circuits we have around that have been there for at least <b>age</b>
@@ -792,7 +796,8 @@ void
circuit_log_ancient_one_hop_circuits(int age)
{
#define MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG 10
- time_t cutoff = time(NULL) - age;
+ time_t now = time(NULL);
+ time_t cutoff = now - age;
int n_found = 0;
smartlist_t *log_these = smartlist_new();
const circuit_t *circ;
@@ -823,20 +828,80 @@ circuit_log_ancient_one_hop_circuits(int age)
SMARTLIST_FOREACH_BEGIN(log_these, const origin_circuit_t *, ocirc) {
char created[ISO_TIME_LEN+1];
+ int stream_num;
+ const edge_connection_t *conn;
+ char *dirty = NULL;
circ = TO_CIRCUIT(ocirc);
+
format_local_iso_time(created,
(time_t)circ->timestamp_created.tv_sec);
+ if (circ->timestamp_dirty) {
+ char dirty_since[ISO_TIME_LEN+1];
+ format_local_iso_time(dirty_since, circ->timestamp_dirty);
+
+ tor_asprintf(&dirty, "Dirty since %s (%ld seconds vs %ld-second cutoff)",
+ dirty_since, (long)(now - circ->timestamp_dirty),
+ (long) get_options()->MaxCircuitDirtiness);
+ } else {
+ dirty = tor_strdup("Not marked dirty");
+ }
+
log_notice(LD_HEARTBEAT, " #%d created at %s. %s, %s. %s for close. "
- "%s for new conns.",
+ "%s for new conns. %s.",
ocirc_sl_idx,
created,
circuit_state_to_string(circ->state),
circuit_purpose_to_string(circ->purpose),
circ->marked_for_close ? "Marked" : "Not marked",
- ocirc->unusable_for_new_conns ? "Not usable" : "usable");
+ ocirc->unusable_for_new_conns ? "Not usable" : "usable",
+ dirty);
+ tor_free(dirty);
+
+ stream_num = 0;
+ for (conn = ocirc->p_streams; conn; conn = conn->next_stream) {
+ const connection_t *c = TO_CONN(conn);
+ char stream_created[ISO_TIME_LEN+1];
+ if (++stream_num >= 5)
+ break;
+
+ format_local_iso_time(stream_created, c->timestamp_created);
+
+ log_notice(LD_HEARTBEAT, " Stream#%d created at %s. "
+ "%s conn in state %s. "
+ "%s for close (%s:%d). Hold-open is %sset. "
+ "Has %ssent RELAY_END. %s on circuit.",
+ stream_num,
+ stream_created,
+ conn_type_to_string(c->type),
+ conn_state_to_string(c->type, c->state),
+ c->marked_for_close ? "Marked" : "Not marked",
+ c->marked_for_close_file ? c->marked_for_close_file : "--",
+ c->marked_for_close,
+ c->hold_open_until_flushed ? "" : "not ",
+ conn->edge_has_sent_end ? "" : "not ",
+ conn->edge_blocked_on_circ ? "Blocked" : "Not blocked");
+ if (! c->linked_conn)
+ continue;
+
+ c = c->linked_conn;
+
+ log_notice(LD_HEARTBEAT, " Linked to %s connection in state %s "
+ "(Purpose %d). %s for close (%s:%d). Hold-open is %sset. ",
+ conn_type_to_string(c->type),
+ conn_state_to_string(c->type, c->state),
+ c->purpose,
+ c->marked_for_close ? "Marked" : "Not marked",
+ c->marked_for_close_file ? c->marked_for_close_file : "--",
+ c->marked_for_close,
+ c->hold_open_until_flushed ? "" : "not ");
+ }
} SMARTLIST_FOREACH_END(ocirc);
+ log_notice(LD_HEARTBEAT, "It has been %ld seconds since I last called "
+ "circuit_expire_old_circuits_clientside().",
+ (long)(now - last_expired_clientside_circuits));
+
done:
smartlist_free(log_these);
}
@@ -1032,7 +1097,6 @@ circuit_predict_and_launch_new(void)
void
circuit_build_needed_circs(time_t now)
{
- static time_t time_to_new_circuit = 0;
const or_options_t *options = get_options();
/* launch a new circ for any pending streams that need one */
@@ -1041,14 +1105,34 @@ circuit_build_needed_circs(time_t now)
/* make sure any hidden services have enough intro points */
rend_services_introduce();
- if (time_to_new_circuit < now) {
+ circuit_expire_old_circs_as_needed(now);
+
+ if (!options->DisablePredictedCircuits)
+ circuit_predict_and_launch_new();
+}
+
+/**
+ * Called once a second either directly or from
+ * circuit_build_needed_circs(). As appropriate (once per NewCircuitPeriod)
+ * resets failure counts and expires old circuits.
+ */
+void
+circuit_expire_old_circs_as_needed(time_t now)
+{
+ static time_t time_to_expire_and_reset = 0;
+
+ if (time_to_expire_and_reset < now) {
circuit_reset_failure_count(1);
- time_to_new_circuit = now + options->NewCircuitPeriod;
+ time_to_expire_and_reset = now + get_options()->NewCircuitPeriod;
if (proxy_mode(get_options()))
addressmap_clean(now);
circuit_expire_old_circuits_clientside();
#if 0 /* disable for now, until predict-and-launch-new can cull leftovers */
+
+ /* If we ever re-enable, this has to move into
+ * circuit_build_needed_circs */
+
circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL);
if (get_options()->RunTesting &&
circ &&
@@ -1058,8 +1142,6 @@ circuit_build_needed_circs(time_t now)
}
#endif
}
- if (!options->DisablePredictedCircuits)
- circuit_predict_and_launch_new();
}
/** If the stream <b>conn</b> is a member of any of the linked
@@ -1146,6 +1228,7 @@ circuit_expire_old_circuits_clientside(void)
tor_gettimeofday(&now);
cutoff = now;
+ last_expired_clientside_circuits = now.tv_sec;
if (! circuit_build_times_disabled() &&
circuit_build_times_needs_circuits(get_circuit_build_times())) {
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index f228a67585..4c5977bee0 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -22,6 +22,7 @@ int circuit_conforms_to_options(const origin_circuit_t *circ,
const or_options_t *options);
#endif
void circuit_build_needed_circs(time_t now);
+void circuit_expire_old_circs_as_needed(time_t now);
void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn);
void circuit_expire_old_circuits_serverside(time_t now);
diff --git a/src/or/command.c b/src/or/command.c
index 105bdc637e..fa2a0e74e7 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -227,6 +227,34 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
(unsigned)cell->circ_id,
U64_PRINTF_ARG(chan->global_identifier), chan);
+ /* We check for the conditions that would make us drop the cell before
+ * we check for the conditions that would make us send a DESTROY back,
+ * since those conditions would make a DESTROY nonsensical. */
+ if (cell->circ_id == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received a create cell (type %d) from %s with zero circID; "
+ " ignoring.", (int)cell->command,
+ channel_get_actual_remote_descr(chan));
+ return;
+ }
+
+ if (circuit_id_in_use_on_channel(cell->circ_id, chan)) {
+ const node_t *node = node_get_by_id(chan->identity_digest);
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received CREATE cell (circID %u) for known circ. "
+ "Dropping (age %d).",
+ (unsigned)cell->circ_id,
+ (int)(time(NULL) - channel_when_created(chan)));
+ if (node) {
+ char *p = esc_for_log(node_get_platform(node));
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Details: router %s, platform %s.",
+ node_describe(node), p);
+ tor_free(p);
+ }
+ return;
+ }
+
if (we_are_hibernating()) {
log_info(LD_OR,
"Received create cell but we're shutting down. Sending back "
@@ -248,14 +276,6 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
return;
}
- if (cell->circ_id == 0) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received a create cell (type %d) from %s with zero circID; "
- " ignoring.", (int)cell->command,
- channel_get_actual_remote_descr(chan));
- return;
- }
-
/* If the high bit of the circuit ID is not as expected, close the
* circ. */
if (chan->wide_circ_ids)
@@ -274,23 +294,6 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
return;
}
- if (circuit_id_in_use_on_channel(cell->circ_id, chan)) {
- const node_t *node = node_get_by_id(chan->identity_digest);
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received CREATE cell (circID %u) for known circ. "
- "Dropping (age %d).",
- (unsigned)cell->circ_id,
- (int)(time(NULL) - channel_when_created(chan)));
- if (node) {
- char *p = esc_for_log(node_get_platform(node));
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Details: router %s, platform %s.",
- node_describe(node), p);
- tor_free(p);
- }
- return;
- }
-
circ = or_circuit_new(cell->circ_id, chan);
circ->base_.purpose = CIRCUIT_PURPOSE_OR;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
diff --git a/src/or/config.c b/src/or/config.c
index 10df83975f..310cef8e2e 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -302,6 +302,7 @@ static config_var_t option_vars_[] = {
OBSOLETE("LogLevel"),
OBSOLETE("LogFile"),
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
+ V(TruncateLogFile, BOOL, "0"),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -557,7 +558,8 @@ static int check_server_ports(const smartlist_t *ports,
static int validate_data_directory(or_options_t *options);
static int write_configuration_file(const char *fname,
const or_options_t *options);
-static int options_init_logs(or_options_t *options, int validate_only);
+static int options_init_logs(const or_options_t *old_options,
+ or_options_t *options, int validate_only);
static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
@@ -1145,7 +1147,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)
mark_logs_temp(); /* Close current logs once new logs are open. */
logs_marked = 1;
- if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */
+ /* Configure the tor_log(s) */
+ if (options_init_logs(old_options, options, 0)<0) {
*msg = tor_strdup("Failed to init Log options. See logs for details.");
goto rollback;
}
@@ -1592,6 +1595,20 @@ options_act(const or_options_t *old_options)
return -1;
}
+ config_maybe_load_geoip_files_(options, old_options);
+
+ if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
+ /* ExcludeUnknown is true or "auto" */
+ const int is_auto = options->GeoIPExcludeUnknown == -1;
+ int changed;
+
+ changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto);
+ changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto);
+
+ if (changed)
+ routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto);
+ }
+
/* Check for transitions that need action. */
if (old_options) {
int revise_trackexithosts = 0;
@@ -1687,20 +1704,6 @@ options_act(const or_options_t *old_options)
connection_or_update_token_buckets(get_connection_array(), options);
}
- config_maybe_load_geoip_files_(options, old_options);
-
- if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
- /* ExcludeUnknown is true or "auto" */
- const int is_auto = options->GeoIPExcludeUnknown == -1;
- int changed;
-
- changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto);
- changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto);
-
- if (changed)
- routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto);
- }
-
if (options->CellStatistics || options->DirReqStatistics ||
options->EntryStatistics || options->ExitPortStatistics ||
options->ConnDirectionStatistics ||
@@ -2547,7 +2550,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
config_line_append(&options->Logs, "Log", "warn stdout");
}
- if (options_init_logs(options, 1)<0) /* Validate the tor_log(s) */
+ /* Validate the tor_log(s) */
+ if (options_init_logs(old_options, options, 1)<0)
REJECT("Failed to validate Log options. See logs for details.");
if (authdir_mode(options)) {
@@ -4449,7 +4453,8 @@ addressmap_register_auto(const char *from, const char *to,
* Initialize the logs based on the configuration file.
*/
static int
-options_init_logs(or_options_t *options, int validate_only)
+options_init_logs(const or_options_t *old_options, or_options_t *options,
+ int validate_only)
{
config_line_t *opt;
int ok;
@@ -4542,7 +4547,21 @@ options_init_logs(or_options_t *options, int validate_only)
!strcasecmp(smartlist_get(elts,0), "file")) {
if (!validate_only) {
char *fname = expand_filename(smartlist_get(elts, 1));
- if (add_file_log(severity, fname) < 0) {
+ /* Truncate if TruncateLogFile is set and we haven't seen this option
+ line before. */
+ int truncate = 0;
+ if (options->TruncateLogFile) {
+ truncate = 1;
+ if (old_options) {
+ config_line_t *opt2;
+ for (opt2 = old_options->Logs; opt2; opt2 = opt2->next)
+ if (!strcmp(opt->value, opt2->value)) {
+ truncate = 0;
+ break;
+ }
+ }
+ }
+ if (add_file_log(severity, fname, truncate) < 0) {
log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
opt->value, strerror(errno));
ok = 0;
diff --git a/src/or/connection.c b/src/or/connection.c
index cef9172ff1..4788bdf950 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -269,8 +269,6 @@ dir_connection_new(int socket_family)
/** Allocate and return a new or_connection_t, initialized as by
* connection_init().
*
- * Set timestamp_last_added_nonpadding to now.
- *
* Initialize active_circuit_pqueue.
*
* Set active_circuit_pqueue_last_recalibrated to current cell_ewma tick.
@@ -283,7 +281,7 @@ or_connection_new(int type, int socket_family)
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
connection_init(now, TO_CONN(or_conn), type, socket_family);
- or_conn->timestamp_last_added_nonpadding = time(NULL);
+ connection_or_set_canonical(or_conn, 0);
if (type == CONN_TYPE_EXT_OR)
connection_or_set_ext_or_identifier(or_conn);
@@ -2652,14 +2650,6 @@ record_num_bytes_transferred(connection_t *conn,
}
#endif
-#ifndef USE_BUFFEREVENTS
-/** Last time at which the global or relay buckets were emptied in msec
- * since midnight. */
-static uint32_t global_relayed_read_emptied = 0,
- global_relayed_write_emptied = 0,
- global_read_emptied = 0,
- global_write_emptied = 0;
-
/** Helper: convert given <b>tvnow</b> time value to milliseconds since
* midnight. */
static uint32_t
@@ -2669,6 +2659,28 @@ msec_since_midnight(const struct timeval *tvnow)
((uint32_t)tvnow->tv_usec / (uint32_t)1000L));
}
+/** Helper: return the time in milliseconds since <b>last_empty_time</b>
+ * when a bucket ran empty that previously had <b>tokens_before</b> tokens
+ * now has <b>tokens_after</b> tokens after refilling at timestamp
+ * <b>tvnow</b>, capped at <b>milliseconds_elapsed</b> milliseconds since
+ * last refilling that bucket. Return 0 if the bucket has not been empty
+ * since the last refill or has not been refilled. */
+uint32_t
+bucket_millis_empty(int tokens_before, uint32_t last_empty_time,
+ int tokens_after, int milliseconds_elapsed,
+ const struct timeval *tvnow)
+{
+ uint32_t result = 0, refilled;
+ if (tokens_before <= 0 && tokens_after > tokens_before) {
+ refilled = msec_since_midnight(tvnow);
+ result = (uint32_t)((refilled + 86400L * 1000L - last_empty_time) %
+ (86400L * 1000L));
+ if (result > (uint32_t)milliseconds_elapsed)
+ result = (uint32_t)milliseconds_elapsed;
+ }
+ return result;
+}
+
/** Check if a bucket which had <b>tokens_before</b> tokens and which got
* <b>tokens_removed</b> tokens removed at timestamp <b>tvnow</b> has run
* out of tokens, and if so, note the milliseconds since midnight in
@@ -2682,6 +2694,14 @@ connection_buckets_note_empty_ts(uint32_t *timestamp_var,
*timestamp_var = msec_since_midnight(tvnow);
}
+#ifndef USE_BUFFEREVENTS
+/** Last time at which the global or relay buckets were emptied in msec
+ * since midnight. */
+static uint32_t global_relayed_read_emptied = 0,
+ global_relayed_write_emptied = 0,
+ global_read_emptied = 0,
+ global_write_emptied = 0;
+
/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes
* onto <b>conn</b>. Decrement buckets appropriately. */
static void
@@ -2840,28 +2860,6 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst,
}
}
-/** Helper: return the time in milliseconds since <b>last_empty_time</b>
- * when a bucket ran empty that previously had <b>tokens_before</b> tokens
- * now has <b>tokens_after</b> tokens after refilling at timestamp
- * <b>tvnow</b>, capped at <b>milliseconds_elapsed</b> milliseconds since
- * last refilling that bucket. Return 0 if the bucket has not been empty
- * since the last refill or has not been refilled. */
-uint32_t
-bucket_millis_empty(int tokens_before, uint32_t last_empty_time,
- int tokens_after, int milliseconds_elapsed,
- const struct timeval *tvnow)
-{
- uint32_t result = 0, refilled;
- if (tokens_before <= 0 && tokens_after > tokens_before) {
- refilled = msec_since_midnight(tvnow);
- result = (uint32_t)((refilled + 86400L * 1000L - last_empty_time) %
- (86400L * 1000L));
- if (result > (uint32_t)milliseconds_elapsed)
- result = (uint32_t)milliseconds_elapsed;
- }
- return result;
-}
-
/** Time has passed; increment buckets appropriately. */
void
connection_bucket_refill(int milliseconds_elapsed, time_t now)
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 6572a918e6..16f87349fc 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -826,6 +826,45 @@ connection_or_update_token_buckets(smartlist_t *conns,
});
}
+/** How long do we wait before killing non-canonical OR connections with no
+ * circuits? In Tor versions up to 0.2.1.25 and 0.2.2.12-alpha, we waited 15
+ * minutes before cancelling these connections, which caused fast relays to
+ * accrue many many idle connections. Hopefully 3-4.5 minutes is low enough
+ * that it kills most idle connections, without being so low that we cause
+ * clients to bounce on and off.
+ *
+ * For canonical connections, the limit is higher, at 15-22.5 minutes.
+ *
+ * For each OR connection, we randomly add up to 50% extra to its idle_timeout
+ * field, to avoid exposing when exactly the last circuit closed. Since we're
+ * storing idle_timeout in a uint16_t, don't let these values get higher than
+ * 12 hours or so without revising connection_or_set_canonical and/or expanding
+ * idle_timeout.
+ */
+#define IDLE_OR_CONN_TIMEOUT_NONCANONICAL 180
+#define IDLE_OR_CONN_TIMEOUT_CANONICAL 900
+
+/* Mark <b>or_conn</b> as canonical if <b>is_canonical</b> is set, and
+ * non-canonical otherwise. Adjust idle_timeout accordingly.
+ */
+void
+connection_or_set_canonical(or_connection_t *or_conn,
+ int is_canonical)
+{
+ const unsigned int timeout_base = is_canonical ?
+ IDLE_OR_CONN_TIMEOUT_CANONICAL : IDLE_OR_CONN_TIMEOUT_NONCANONICAL;
+
+ if (bool_eq(is_canonical, or_conn->is_canonical) &&
+ or_conn->idle_timeout != 0) {
+ /* Don't recalculate an existing idle_timeout unless the canonical
+ * status changed. */
+ return;
+ }
+
+ or_conn->is_canonical = !! is_canonical; /* force to a 1-bit boolean */
+ or_conn->idle_timeout = timeout_base + crypto_rand_int(timeout_base / 2);
+}
+
/** If we don't necessarily know the router we're connecting to, but we
* have an addr/port/id_digest, then fill in as much as we can. Start
* by checking to see if this describes a router we know.
@@ -850,7 +889,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
/* XXXX proposal 186 is making this more complex. For now, a conn
is canonical when it uses the _preferred_ address. */
if (tor_addr_eq(&conn->base_.addr, &node_ap.addr))
- conn->is_canonical = 1;
+ connection_or_set_canonical(conn, 1);
if (!started_here) {
/* Override the addr/port, so our log messages will make sense.
* This is dangerous, since if we ever try looking up a conn by
@@ -1966,9 +2005,6 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
or_handshake_state_record_cell(conn, conn->handshake_state, cell, 0);
-
- if (cell->command != CELL_PADDING)
- conn->timestamp_last_added_nonpadding = approx_time();
}
/** Pack a variable-length <b>cell</b> into wire-format, and write it onto
@@ -1989,8 +2025,6 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell,
cell->payload_len, TO_CONN(conn));
if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
or_handshake_state_record_var_cell(conn, conn->handshake_state, cell, 0);
- if (cell->command != CELL_PADDING)
- conn->timestamp_last_added_nonpadding = approx_time();
/* Touch the channel's active timestamp if there is one */
if (conn->chan)
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 8d93028932..143540edd9 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -48,6 +48,8 @@ void connection_or_report_broken_states(int severity, int domain);
MOCK_DECL(int,connection_tls_start_handshake,(or_connection_t *conn,
int receiving));
int connection_tls_continue_handshake(or_connection_t *conn);
+void connection_or_set_canonical(or_connection_t *or_conn,
+ int is_canonical);
int connection_init_or_handshake_state(or_connection_t *conn,
int started_here);
diff --git a/src/or/control.c b/src/or/control.c
index 21504e685e..21504e685e 100755..100644
--- a/src/or/control.c
+++ b/src/or/control.c
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 61b2c29b38..62af8e2f50 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -414,12 +414,6 @@ cpuworker_main(void *data)
cpuworker_reply_t rpl;
fd = fdarray[1]; /* this side is ours */
-#ifndef TOR_IS_MULTITHREADED
- tor_close_socket(fdarray[0]); /* this is the side of the socketpair the
- * parent uses */
- tor_free_all(1); /* so the child doesn't hold the parent's fd's open */
- handle_signals(0); /* ignore interrupts from the keyboard, etc */
-#endif
tor_free(data);
setup_server_onion_keys(&onion_keys);
@@ -535,10 +529,6 @@ spawn_cpuworker(void)
return -1;
}
log_debug(LD_OR,"just spawned a cpu worker.");
-#ifndef TOR_IS_MULTITHREADED
- tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */
- tor_free(fdarray);
-#endif
conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX);
diff --git a/src/or/directory.c b/src/or/directory.c
index 22ba056ee1..77f8f310b1 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -197,9 +197,9 @@ dir_conn_purpose_to_string(int purpose)
return "(unknown)";
}
-/** Return true iff <b>identity_digest</b> is the digest of a router we
- * believe to support extrainfo downloads. (If <b>is_authority</b> we do
- * additional checking that's only valid for authorities.) */
+/** Return true iff <b>identity_digest</b> is the digest of a router which
+ * says that it caches extrainfos. (If <b>is_authority</b> we always
+ * believe that to be true.) */
int
router_supports_extrainfo(const char *identity_digest, int is_authority)
{
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index aedd092522..a033f8be6d 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1468,7 +1468,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
* to fix the bug was 0.2.2.25-alpha. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
- node->is_running);
+ router_is_active(router, node, now));
}
/** Don't consider routers with less bandwidth than this when computing
diff --git a/src/or/main.c b/src/or/main.c
index 3c661cd121..c7b532bbab 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -54,6 +54,7 @@
#include "routerparse.h"
#include "statefile.h"
#include "status.h"
+#include "util_process.h"
#include "ext_orport.h"
#ifdef USE_DMALLOC
#include <dmalloc.h>
@@ -1001,15 +1002,6 @@ directory_info_has_arrived(time_t now, int from_cache)
consider_testing_reachability(1, 1);
}
-/** How long do we wait before killing OR connections with no circuits?
- * In Tor versions up to 0.2.1.25 and 0.2.2.12-alpha, we waited 15 minutes
- * before cancelling these connections, which caused fast relays to accrue
- * many many idle connections. Hopefully 3 minutes is low enough that
- * it kills most idle connections, without being so low that we cause
- * clients to bounce on and off.
- */
-#define IDLE_OR_CONN_TIMEOUT 180
-
/** Perform regular maintenance tasks for a single connection. This
* function gets run once per second per connection by run_scheduled_events.
*/
@@ -1020,6 +1012,8 @@ run_connection_housekeeping(int i, time_t now)
connection_t *conn = smartlist_get(connection_array, i);
const or_options_t *options = get_options();
or_connection_t *or_conn;
+ channel_t *chan = NULL;
+ int have_any_circuits;
int past_keepalive =
now >= conn->timestamp_lastwritten + options->KeepalivePeriod;
@@ -1069,8 +1063,18 @@ run_connection_housekeeping(int i, time_t now)
tor_assert(conn->outbuf);
#endif
+ chan = TLS_CHAN_TO_BASE(or_conn->chan);
+ tor_assert(chan);
+
+ if (channel_num_circuits(chan) != 0) {
+ have_any_circuits = 1;
+ chan->timestamp_last_had_circuits = now;
+ } else {
+ have_any_circuits = 0;
+ }
+
if (channel_is_bad_for_new_circs(TLS_CHAN_TO_BASE(or_conn->chan)) &&
- !connection_or_get_num_circuits(or_conn)) {
+ ! have_any_circuits) {
/* It's bad for new circuits, and has no unmarked circuits on it:
* mark it now. */
log_info(LD_OR,
@@ -1089,19 +1093,22 @@ run_connection_housekeeping(int i, time_t now)
connection_or_close_normally(TO_OR_CONN(conn), 0);
}
} else if (we_are_hibernating() &&
- !connection_or_get_num_circuits(or_conn) &&
+ ! have_any_circuits &&
!connection_get_outbuf_len(conn)) {
/* We're hibernating, there's no circuits, and nothing to flush.*/
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
(int)conn->s,conn->address, conn->port);
connection_or_close_normally(TO_OR_CONN(conn), 1);
- } else if (!connection_or_get_num_circuits(or_conn) &&
- now >= or_conn->timestamp_last_added_nonpadding +
- IDLE_OR_CONN_TIMEOUT) {
+ } else if (!have_any_circuits &&
+ now - or_conn->idle_timeout >=
+ chan->timestamp_last_had_circuits) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
- "[idle %d].", (int)conn->s,conn->address, conn->port,
- (int)(now - or_conn->timestamp_last_added_nonpadding));
+ "[no circuits for %d; timeout %d; %scanonical].",
+ (int)conn->s, conn->address, conn->port,
+ (int)(now - chan->timestamp_last_had_circuits),
+ or_conn->idle_timeout,
+ or_conn->is_canonical ? "" : "non");
connection_or_close_normally(TO_OR_CONN(conn), 0);
} else if (
now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
@@ -1505,8 +1512,11 @@ run_scheduled_events(time_t now)
* and we make a new circ if there are no clean circuits.
*/
have_dir_info = router_have_minimum_dir_info();
- if (have_dir_info && !net_is_disabled())
+ if (have_dir_info && !net_is_disabled()) {
circuit_build_needed_circs(now);
+ } else {
+ circuit_expire_old_circs_as_needed(now);
+ }
/* every 10 seconds, but not at the same second as other such events */
if (now % 10 == 5)
@@ -1851,6 +1861,10 @@ do_hup(void)
return -1;
}
options = get_options(); /* they have changed now */
+ /* Logs are only truncated the first time they are opened, but were
+ probably intended to be cleaned up on signal. */
+ if (options->TruncateLogFile)
+ truncate_logs();
} else {
char *msg = NULL;
log_notice(LD_GENERAL, "Not reloading config file: the controller told "
@@ -2103,8 +2117,7 @@ process_signal(uintptr_t sig)
break;
#ifdef SIGCHLD
case SIGCHLD:
- while (waitpid(-1,NULL,WNOHANG) > 0) ; /* keep reaping until no more
- zombies */
+ notify_pending_waitpid_callbacks();
break;
#endif
case SIGNEWNYM: {
@@ -2545,6 +2558,7 @@ tor_free_all(int postfork)
microdesc_free_all();
ext_orport_free_all();
control_free_all();
+ sandbox_free_getaddrinfo_cache();
if (!postfork) {
config_free_all();
or_state_free_all();
@@ -2699,31 +2713,6 @@ do_dump_config(void)
return 0;
}
-#if defined (WINCE)
-int
-find_flashcard_path(PWCHAR path, size_t size)
-{
- WIN32_FIND_DATA d = {0};
- HANDLE h = NULL;
-
- if (!path)
- return -1;
-
- h = FindFirstFlashCard(&d);
- if (h == INVALID_HANDLE_VALUE)
- return -1;
-
- if (wcslen(d.cFileName) == 0) {
- FindClose(h);
- return -1;
- }
-
- wcsncpy(path,d.cFileName,size);
- FindClose(h);
- return 0;
-}
-#endif
-
static void
init_addrinfo(void)
{
@@ -2934,6 +2923,7 @@ sandbox_init_filter(void)
sandbox_cfg_allow_stat_filename_array(&cfg,
get_datadir_fname("keys"),
+ get_datadir_fname("stats"),
get_datadir_fname2("stats", "dirreq-stats"),
NULL, 0
);
@@ -2951,31 +2941,6 @@ int
tor_main(int argc, char *argv[])
{
int result = 0;
-#if defined (WINCE)
- WCHAR path [MAX_PATH] = {0};
- WCHAR fullpath [MAX_PATH] = {0};
- PWCHAR p = NULL;
- FILE* redir = NULL;
- FILE* redirdbg = NULL;
-
- // this is to facilitate debugging by opening
- // a file on a folder shared by the wm emulator.
- // if no flashcard (real or emulated) is present,
- // log files will be written in the root folder
- if (find_flashcard_path(path,MAX_PATH) == -1) {
- redir = _wfreopen( L"\\stdout.log", L"w", stdout );
- redirdbg = _wfreopen( L"\\stderr.log", L"w", stderr );
- } else {
- swprintf(fullpath,L"\\%s\\tor",path);
- CreateDirectory(fullpath,NULL);
-
- swprintf(fullpath,L"\\%s\\tor\\stdout.log",path);
- redir = _wfreopen( fullpath, L"w", stdout );
-
- swprintf(fullpath,L"\\%s\\tor\\stderr.log",path);
- redirdbg = _wfreopen( fullpath, L"w", stderr );
- }
-#endif
#ifdef _WIN32
/* Call SetProcessDEPPolicy to permanently enable DEP.
diff --git a/src/or/ntmain.h b/src/or/ntmain.h
index d3027936cd..d09a413aee 100644
--- a/src/or/ntmain.h
+++ b/src/or/ntmain.h
@@ -13,10 +13,8 @@
#define TOR_NTMAIN_H
#ifdef _WIN32
-#if !defined (WINCE)
#define NT_SERVICE
#endif
-#endif
#ifdef NT_SERVICE
int nt_service_parse_options(int argc, char **argv, int *should_exit);
diff --git a/src/or/or.h b/src/or/or.h
index 6aa6b59e8e..0419111a4e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -42,9 +42,6 @@
#include <sys/param.h> /* FreeBSD needs this to know what version it is */
#endif
#include "torint.h"
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
@@ -1488,13 +1485,14 @@ typedef struct or_connection_t {
uint16_t link_proto; /**< What protocol version are we using? 0 for
* "none negotiated yet." */
-
+ uint16_t idle_timeout; /**< How long can this connection sit with no
+ * circuits on it before we close it? Based on
+ * IDLE_CIRCUIT_TIMEOUT_{NON,}CANONICAL and
+ * on is_canonical, randomized. */
or_handshake_state_t *handshake_state; /**< If we are setting this connection
* up, state information to do so. */
time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
- time_t timestamp_last_added_nonpadding; /** When did we last add a
- * non-padding cell to the outbuf? */
/* bandwidth* and *_bucket only used by ORs in OPEN state: */
int bandwidthrate; /**< Bytes/s added to the bucket. (OPEN ORs only.) */
@@ -3404,6 +3402,8 @@ typedef struct {
int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
* each log message occurs? */
+ int TruncateLogFile; /**< Boolean: Should we truncate the log file
+ before we start writing? */
char *DebugLogFile; /**< Where to send verbose log messages. */
char *DataDirectory; /**< OR only: where to store long-term data. */
diff --git a/src/or/relay.c b/src/or/relay.c
index 509d7ced04..f42602d412 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1437,7 +1437,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
switch (rh.command) {
case RELAY_COMMAND_BEGIN:
case RELAY_COMMAND_CONNECTED:
- case RELAY_COMMAND_DATA:
case RELAY_COMMAND_END:
case RELAY_COMMAND_RESOLVE:
case RELAY_COMMAND_RESOLVED:
@@ -1462,6 +1461,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
* EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
* This speeds up HTTP, for example. */
optimistic_data = 1;
+ } else if (rh.stream_id == 0 && rh.command == RELAY_COMMAND_DATA) {
+ log_warn(LD_BUG, "Somehow I had a connection that matched a "
+ "data cell with stream ID 0.");
} else {
return connection_edge_process_relay_cell_not_open(
&rh, cell, circ, conn, layer_hint);
@@ -1522,7 +1524,11 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
circuit_consider_sending_sendme(circ, layer_hint);
- if (!conn) {
+ if (rh.stream_id == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero "
+ "stream_id. Dropping.");
+ return 0;
+ } else if (!conn) {
log_info(domain,"data cell dropped, unknown stream (streamid %d).",
rh.stream_id);
return 0;
@@ -2563,6 +2569,17 @@ packed_cell_get_command(const packed_cell_t *cell, int wide_circ_ids)
}
}
+/** Extract the circuit ID from a packed cell. */
+circid_t
+packed_cell_get_circid(const packed_cell_t *cell, int wide_circ_ids)
+{
+ if (wide_circ_ids) {
+ return ntohl(get_uint32(cell->body));
+ } else {
+ return ntohs(get_uint16(cell->body));
+ }
+}
+
/** Pull as many cells as possible (but no more than <b>max</b>) from the
* queue of the first active circuit on <b>chan</b>, and write them to
* <b>chan</b>-&gt;outbuf. Return the number of cells written. Advance
diff --git a/src/or/relay.h b/src/or/relay.h
index 479d474b35..969c6fb61d 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -82,6 +82,8 @@ void stream_choice_seed_weak_rng(void);
int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
crypt_path_t **layer_hint, char *recognized);
+circid_t packed_cell_get_circid(const packed_cell_t *cell, int wide_circ_ids);
+
#ifdef RELAY_PRIVATE
STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
tor_addr_t *addr_out, int *ttl_out);
diff --git a/src/or/router.c b/src/or/router.c
index 2cdbb0c8bb..4fcd4a5b89 100755..100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -2371,7 +2371,8 @@ router_dump_router_to_string(routerinfo_t *router,
has_extra_info_digest ? "extra-info-digest " : "",
has_extra_info_digest ? extra_info_digest : "",
has_extra_info_digest ? "\n" : "",
- options->DownloadExtraInfo ? "caches-extra-info\n" : "",
+ (options->DownloadExtraInfo || options->V3AuthoritativeDir) ?
+ "caches-extra-info\n" : "",
onion_pkey, identity_pkey,
family_line,
we_are_hibernating() ? "hibernating 1\n" : "",
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index bf4aff3b55..5bad2b2e5c 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -448,9 +448,10 @@ trusted_dirs_flush_certs_to_disk(void)
trusted_dir_servers_certs_changed = 0;
}
-/** Remove all v3 authority certificates that have been superseded for more
- * than 48 hours. (If the most recent cert was published more than 48 hours
- * ago, then we aren't going to get any consensuses signed with older
+/** Remove all expired v3 authority certificates that have been superseded for
+ * more than 48 hours or, if not expired, that were published more than 7 days
+ * before being superseded. (If the most recent cert was published more than 48
+ * hours ago, then we aren't going to get any consensuses signed with older
* keys.) */
static void
trusted_dirs_remove_old_certs(void)
@@ -488,6 +489,7 @@ trusted_dirs_remove_old_certs(void)
} SMARTLIST_FOREACH_END(cert);
}
} DIGESTMAP_FOREACH_END;
+#undef DEAD_CERT_LIFETIME
#undef OLD_CERT_LIFETIME
trusted_dirs_flush_certs_to_disk();
@@ -1438,7 +1440,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
/* Find all the running dirservers we know about. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
- int is_trusted;
+ int is_trusted, is_trusted_extrainfo;
int is_overloaded;
tor_addr_t addr;
const routerstatus_t *status = node->rs;
@@ -1453,8 +1455,10 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
if (requireother && router_digest_is_me(node->identity))
continue;
is_trusted = router_digest_is_trusted_dir(node->identity);
+ is_trusted_extrainfo = router_digest_is_trusted_dir_type(
+ node->identity, EXTRAINFO_DIRINFO);
if ((type & EXTRAINFO_DIRINFO) &&
- !router_supports_extrainfo(node->identity, 0))
+ !router_supports_extrainfo(node->identity, is_trusted_extrainfo))
continue;
if ((type & MICRODESC_DIRINFO) && !is_trusted &&
!node->rs->version_supports_microdesc_cache)
@@ -3292,12 +3296,12 @@ routerlist_reset_warnings(void)
networkstatus_reset_warnings();
}
-/** Return 1 if the signed descriptor of this router is too old to be used.
- * Otherwise return 0. */
+/** Return 1 if the signed descriptor of this router is older than
+ * <b>seconds</b> seconds. Otherwise return 0. */
MOCK_IMPL(int,
-router_descriptor_is_too_old,(const routerinfo_t *router))
+router_descriptor_is_older_than,(const routerinfo_t *router, int seconds))
{
- return router->cache_info.published_on < time(NULL)-OLD_ROUTER_DESC_MAX_AGE;
+ return router->cache_info.published_on < time(NULL) - seconds;
}
/** Add <b>router</b> to the routerlist, if we don't already have it. Replace
@@ -3468,7 +3472,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
}
}
- if (!in_consensus && from_cache && router_descriptor_is_too_old(router)) {
+ if (!in_consensus && from_cache &&
+ router_descriptor_is_older_than(router, OLD_ROUTER_DESC_MAX_AGE)) {
*msg = "Router descriptor was really old.";
routerinfo_free(router);
return ROUTER_WAS_NOT_NEW;
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index adf5d32209..52f2303c7c 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -213,7 +213,8 @@ STATIC int choose_array_element_by_weight(const u64_dbl_t *entries,
STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
uint64_t *total_out);
-MOCK_DECL(int, router_descriptor_is_too_old, (const routerinfo_t *router));
+MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
+ int seconds));
#endif
#endif