diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/channel.c | 11 | ||||
-rw-r--r-- | src/or/channel.h | 6 | ||||
-rw-r--r-- | src/or/channeltls.c | 2 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 72 | ||||
-rw-r--r-- | src/or/circuitlist.c | 38 | ||||
-rw-r--r-- | src/or/circuitlist.h | 2 | ||||
-rw-r--r-- | src/or/circuitmux.c | 36 | ||||
-rw-r--r-- | src/or/circuitmux.h | 4 | ||||
-rw-r--r-- | src/or/circuituse.c | 99 | ||||
-rw-r--r-- | src/or/circuituse.h | 1 | ||||
-rw-r--r-- | src/or/command.c | 53 | ||||
-rw-r--r-- | src/or/config.c | 57 | ||||
-rw-r--r-- | src/or/connection.c | 64 | ||||
-rw-r--r-- | src/or/connection_or.c | 46 | ||||
-rw-r--r-- | src/or/connection_or.h | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | src/or/control.c | 0 | ||||
-rw-r--r-- | src/or/cpuworker.c | 10 | ||||
-rw-r--r-- | src/or/directory.c | 6 | ||||
-rw-r--r-- | src/or/dirserv.c | 2 | ||||
-rw-r--r-- | src/or/main.c | 103 | ||||
-rw-r--r-- | src/or/ntmain.h | 2 | ||||
-rw-r--r-- | src/or/or.h | 12 | ||||
-rw-r--r-- | src/or/relay.c | 21 | ||||
-rw-r--r-- | src/or/relay.h | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | src/or/router.c | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 25 | ||||
-rw-r--r-- | src/or/routerlist.h | 3 |
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>->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 |