diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/circpathbias.c | 4 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 2 | ||||
-rw-r--r-- | src/or/circuitlist.c | 248 | ||||
-rw-r--r-- | src/or/circuitlist.h | 4 | ||||
-rw-r--r-- | src/or/circuitstats.c | 14 | ||||
-rw-r--r-- | src/or/circuituse.c | 46 | ||||
-rw-r--r-- | src/or/config.c | 68 | ||||
-rw-r--r-- | src/or/connection.c | 12 | ||||
-rw-r--r-- | src/or/control.c | 24 | ||||
-rw-r--r-- | src/or/cpuworker.c | 12 | ||||
-rw-r--r-- | src/or/directory.c | 6 | ||||
-rw-r--r-- | src/or/dirserv.c | 23 | ||||
-rw-r--r-- | src/or/dirvote.c | 438 | ||||
-rw-r--r-- | src/or/dirvote.h | 22 | ||||
-rw-r--r-- | src/or/entrynodes.c | 261 | ||||
-rw-r--r-- | src/or/entrynodes.h | 32 | ||||
-rw-r--r-- | src/or/geoip.c | 4 | ||||
-rw-r--r-- | src/or/main.c | 217 | ||||
-rw-r--r-- | src/or/ntmain.h | 2 | ||||
-rw-r--r-- | src/or/or.h | 6 | ||||
-rw-r--r-- | src/or/policies.c | 6 | ||||
-rw-r--r-- | src/or/reasons.c | 4 | ||||
-rw-r--r-- | src/or/relay.c | 13 | ||||
-rw-r--r-- | src/or/rendclient.c | 4 | ||||
-rw-r--r-- | src/or/rendcommon.c | 2 | ||||
-rw-r--r-- | src/or/rendservice.c | 27 | ||||
-rw-r--r-- | src/or/rephist.c | 15 | ||||
-rw-r--r-- | src/or/router.c | 5 | ||||
-rw-r--r-- | src/or/routerlist.c | 38 | ||||
-rw-r--r-- | src/or/routerlist.h | 3 | ||||
-rw-r--r-- | src/or/routerparse.c | 9 | ||||
-rw-r--r-- | src/or/status.c | 8 |
32 files changed, 735 insertions, 844 deletions
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c index 51a75cf502..59024abd12 100644 --- a/src/or/circpathbias.c +++ b/src/or/circpathbias.c @@ -1140,11 +1140,10 @@ pathbias_count_circs_in_states(entry_guard_t *guard, path_state_t from, path_state_t to) { - circuit_t *circ; int open_circuits = 0; /* Count currently open circuits. Give them the benefit of the doubt. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { origin_circuit_t *ocirc = NULL; if (!CIRCUIT_IS_ORIGIN(circ) || /* didn't originate here */ circ->marked_for_close) /* already counted */ @@ -1167,6 +1166,7 @@ pathbias_count_circs_in_states(entry_guard_t *guard, open_circuits++; } } + SMARTLIST_FOREACH_END(circ); return open_circuits; } diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 897f90fe4c..edf7d2863e 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1564,7 +1564,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) * -1 means "Don't use this router at all." */ the_nodes = nodelist_get_list(); - n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes)); + n_supported = tor_calloc(sizeof(int), smartlist_len(the_nodes)); SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) { const int i = node_sl_idx; if (router_digest_is_me(node->identity)) { diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index f3a83503ef..35c52362d2 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -21,6 +21,7 @@ #include "connection_edge.h" #include "connection_or.h" #include "control.h" +#include "main.h" #include "networkstatus.h" #include "nodelist.h" #include "onion.h" @@ -38,8 +39,7 @@ /********* START VARIABLES **********/ /** A global list of all circuits at this hop. */ -struct global_circuitlist_s global_circuitlist = - TOR_LIST_HEAD_INITIALIZER(global_circuitlist); +static smartlist_t *global_circuitlist = NULL; /** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */ static smartlist_t *circuits_pending_chans = NULL; @@ -451,17 +451,25 @@ circuit_count_pending_on_channel(channel_t *chan) void circuit_close_all_marked(void) { - circuit_t *circ, *tmp; - TOR_LIST_FOREACH_SAFE(circ, &global_circuitlist, head, tmp) - if (circ->marked_for_close) + smartlist_t *lst = circuit_get_global_list(); + SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, circ) { + /* Fix up index if SMARTLIST_DEL_CURRENT just moved this one. */ + circ->global_circuitlist_idx = circ_sl_idx; + if (circ->marked_for_close) { + circ->global_circuitlist_idx = -1; circuit_free(circ); + SMARTLIST_DEL_CURRENT(lst, circ); + } + } SMARTLIST_FOREACH_END(circ); } /** Return the head of the global linked list of circuits. */ -MOCK_IMPL(struct global_circuitlist_s *, +MOCK_IMPL(smartlist_t *, circuit_get_global_list,(void)) { - return &global_circuitlist; + if (NULL == global_circuitlist) + global_circuitlist = smartlist_new(); + return global_circuitlist; } /** Function to make circ-\>state human-readable */ @@ -678,7 +686,8 @@ init_circuit_base(circuit_t *circ) circ->deliver_window = CIRCWINDOW_START; cell_queue_init(&circ->n_chan_cells); - TOR_LIST_INSERT_HEAD(&global_circuitlist, circ, head); + smartlist_add(circuit_get_global_list(), circ); + circ->global_circuitlist_idx = smartlist_len(circuit_get_global_list()) - 1; } /** Allocate space for a new circuit, initializing with <b>p_circ_id</b> @@ -799,7 +808,16 @@ circuit_free(circuit_t *circ) extend_info_free(circ->n_hop); tor_free(circ->n_chan_create_cell); - TOR_LIST_REMOVE(circ, head); + if (circ->global_circuitlist_idx != -1) { + int idx = circ->global_circuitlist_idx; + circuit_t *c2 = smartlist_get(global_circuitlist, idx); + tor_assert(c2 == circ); + smartlist_del(global_circuitlist, idx); + if (idx < smartlist_len(global_circuitlist)) { + c2 = smartlist_get(global_circuitlist, idx); + c2->global_circuitlist_idx = idx; + } + } /* Remove from map. */ circuit_set_n_circid_chan(circ, 0, NULL); @@ -841,9 +859,9 @@ circuit_clear_cpath(origin_circuit_t *circ) void circuit_free_all(void) { - circuit_t *tmp, *tmp2; + smartlist_t *lst = circuit_get_global_list(); - TOR_LIST_FOREACH_SAFE(tmp, &global_circuitlist, head, tmp2) { + SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, tmp) { if (! CIRCUIT_IS_ORIGIN(tmp)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(tmp); while (or_circ->resolving_streams) { @@ -853,8 +871,13 @@ circuit_free_all(void) or_circ->resolving_streams = next_conn; } } + tmp->global_circuitlist_idx = -1; circuit_free(tmp); - } + SMARTLIST_DEL_CURRENT(lst, tmp); + } SMARTLIST_FOREACH_END(tmp); + + smartlist_free(lst); + global_circuitlist = NULL; smartlist_free(circuits_pending_chans); circuits_pending_chans = NULL; @@ -932,10 +955,9 @@ circuit_dump_conn_details(int severity, void circuit_dump_by_conn(connection_t *conn, int severity) { - circuit_t *circ; edge_connection_t *tmpconn; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; if (circ->marked_for_close) { @@ -966,6 +988,7 @@ circuit_dump_by_conn(connection_t *conn, int severity) } } } + SMARTLIST_FOREACH_END(circ); } /** Return the circuit whose global ID is <b>id</b>, or NULL if no @@ -973,8 +996,7 @@ circuit_dump_by_conn(connection_t *conn, int severity) origin_circuit_t * circuit_get_by_global_id(uint32_t id) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) { if (circ->marked_for_close) @@ -983,6 +1005,7 @@ circuit_get_by_global_id(uint32_t id) return TO_ORIGIN_CIRCUIT(circ); } } + SMARTLIST_FOREACH_END(circ); return NULL; } @@ -1151,17 +1174,17 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason) #ifdef DEBUG_CIRCUIT_UNLINK_ALL { - circuit_t *circ; smartlist_t *detached_2 = smartlist_new(); int mismatch = 0, badlen = 0; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->n_chan == chan || (!CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_chan == chan)) { smartlist_add(detached_2, circ); } } + SMARTLIST_FOREACH_END(circ); if (smartlist_len(detached) != smartlist_len(detached_2)) { log_warn(LD_BUG, "List of detached circuits had the wrong length! " @@ -1235,8 +1258,7 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason) origin_circuit_t * circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); @@ -1249,6 +1271,7 @@ circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data) return ocirc; } } + SMARTLIST_FOREACH_END(circ); return NULL; } @@ -1261,14 +1284,17 @@ origin_circuit_t * circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, const char *digest, uint8_t purpose) { - circuit_t *circ; + int idx; + smartlist_t *lst = circuit_get_global_list(); tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose)); if (start == NULL) - circ = TOR_LIST_FIRST(&global_circuitlist); + idx = 0; else - circ = TOR_LIST_NEXT(TO_CIRCUIT(start), head); + idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1; + + for ( ; idx < smartlist_len(lst); ++idx) { + circuit_t *circ = smartlist_get(lst, idx); - for ( ; circ; circ = TOR_LIST_NEXT(circ, head)) { if (circ->marked_for_close) continue; if (circ->purpose != purpose) @@ -1469,7 +1495,6 @@ origin_circuit_t * circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int flags) { - circuit_t *circ_; origin_circuit_t *best=NULL; int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0; int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; @@ -1485,7 +1510,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, "capacity %d, internal %d", purpose, need_uptime, need_capacity, internal); - TOR_LIST_FOREACH(circ_, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) { if (CIRCUIT_IS_ORIGIN(circ_) && circ_->state == CIRCUIT_STATE_OPEN && !circ_->marked_for_close && @@ -1535,6 +1560,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, } } } + SMARTLIST_FOREACH_END(circ_); return best; } @@ -1574,13 +1600,13 @@ circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum) void circuit_mark_all_unused_circs(void) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && !circ->timestamp_dirty) circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } + SMARTLIST_FOREACH_END(circ); } /** Go through the circuitlist; for each circuit that starts at us @@ -1593,14 +1619,14 @@ circuit_mark_all_unused_circs(void) void circuit_mark_all_dirty_circs_as_unusable(void) { - circuit_t *circ; - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && circ->timestamp_dirty) { mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ)); } } + SMARTLIST_FOREACH_END(circ); } /** Mark <b>circ</b> to be closed next time we call @@ -1799,6 +1825,29 @@ marked_circuit_free_cells(circuit_t *circ) cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_chan_cells); } +static size_t +single_conn_free_bytes(connection_t *conn) +{ + size_t result = 0; + if (conn->inbuf) { + result += buf_allocation(conn->inbuf); + buf_clear(conn->inbuf); + } + if (conn->outbuf) { + result += buf_allocation(conn->outbuf); + buf_clear(conn->outbuf); + } + if (conn->type == CONN_TYPE_DIR) { + dir_connection_t *dir_conn = TO_DIR_CONN(conn); + if (dir_conn->zlib_state) { + result += tor_zlib_state_size(dir_conn->zlib_state); + tor_zlib_free(dir_conn->zlib_state); + dir_conn->zlib_state = NULL; + } + } + return result; +} + /** Aggressively free buffer contents on all the buffers of all streams in the * list starting at <b>stream</b>. Return the number of bytes recovered. */ static size_t @@ -1807,13 +1856,9 @@ marked_circuit_streams_free_bytes(edge_connection_t *stream) size_t result = 0; for ( ; stream; stream = stream->next_stream) { connection_t *conn = TO_CONN(stream); - if (conn->inbuf) { - result += buf_allocation(conn->inbuf); - buf_clear(conn->inbuf); - } - if (conn->outbuf) { - result += buf_allocation(conn->outbuf); - buf_clear(conn->outbuf); + result += single_conn_free_bytes(conn); + if (conn->linked_conn) { + result += single_conn_free_bytes(conn->linked_conn); } } return result; @@ -1871,6 +1916,28 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) return age; } +/** Return the age in milliseconds of the oldest buffer chunk on <b>conn</b>, + * where age is taken in milliseconds before the time <b>now</b> (in truncated + * milliseconds since the epoch). If the connection has no data, treat + * it as having age zero. + **/ +static uint32_t +conn_get_buffer_age(const connection_t *conn, uint32_t now) +{ + uint32_t age = 0, age2; + if (conn->outbuf) { + age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now); + if (age2 > age) + age = age2; + } + if (conn->inbuf) { + age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now); + if (age2 > age) + age = age2; + } + return age; +} + /** Return the age in milliseconds of the oldest buffer chunk on any stream in * the linked list <b>stream</b>, where age is taken in milliseconds before * the time <b>now</b> (in truncated milliseconds since the epoch). */ @@ -1880,18 +1947,15 @@ circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) uint32_t age = 0, age2; for (; stream; stream = stream->next_stream) { const connection_t *conn = TO_CONN(stream); - if (conn->outbuf) { - age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now); - if (age2 > age) - age = age2; - } - if (conn->inbuf) { - age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now); + age2 = conn_get_buffer_age(conn, now); + if (age2 > age) + age = age2; + if (conn->linked_conn) { + age2 = conn_get_buffer_age(conn->linked_conn, now); if (age2 > age) age = age2; } } - return age; } @@ -1942,6 +2006,26 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) return -1; } +static uint32_t now_ms_for_buf_cmp; + +/** Helper to sort a list of circuit_t by age of oldest item, in descending + * order. */ +static int +conns_compare_by_buffer_age_(const void **a_, const void **b_) +{ + const connection_t *a = *a_; + const connection_t *b = *b_; + time_t age_a = conn_get_buffer_age(a, now_ms_for_buf_cmp); + time_t age_b = conn_get_buffer_age(b, now_ms_for_buf_cmp); + + if (age_a < age_b) + return 1; + else if (age_a == age_b) + return 0; + else + return -1; +} + #define FRACTION_OF_DATA_TO_RETAIN_ON_OOM 0.90 /** We're out of memory for cells, having allocated <b>current_allocation</b> @@ -1950,12 +2034,13 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) void circuits_handle_oom(size_t current_allocation) { - /* Let's hope there's enough slack space for this allocation here... */ - smartlist_t *circlist = smartlist_new(); - circuit_t *circ; + smartlist_t *circlist; + smartlist_t *connection_array = get_connection_array(); + int conn_idx; size_t mem_to_recover; size_t mem_recovered=0; int n_circuits_killed=0; + int n_dirconns_killed=0; struct timeval now; uint32_t now_ms; log_notice(LD_GENERAL, "We're low on memory. Killing circuits with " @@ -1984,22 +2069,61 @@ circuits_handle_oom(size_t current_allocation) tor_gettimeofday_cached_monotonic(&now); now_ms = (uint32_t)tv_to_msec(&now); - /* This algorithm itself assumes that you've got enough memory slack - * to actually run it. */ - TOR_LIST_FOREACH(circ, &global_circuitlist, head) { + circlist = circuit_get_global_list(); + SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { circ->age_tmp = circuit_max_queued_item_age(circ, now_ms); - smartlist_add(circlist, circ); - } + } SMARTLIST_FOREACH_END(circ); /* This is O(n log n); there are faster algorithms we could use instead. * Let's hope this doesn't happen enough to be in the critical path. */ smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_); - /* Okay, now the worst circuits are at the front of the list. Let's mark - * them, and reclaim their storage aggressively. */ + /* Fix up the indices before we run into trouble */ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { - size_t n = n_cells_in_circ_queues(circ); + circ->global_circuitlist_idx = circ_sl_idx; + } SMARTLIST_FOREACH_END(circ); + + /* Now sort the connection array ... */ + now_ms_for_buf_cmp = now_ms; + smartlist_sort(connection_array, conns_compare_by_buffer_age_); + now_ms_for_buf_cmp = 0; + + /* Fix up the connection array to its new order. */ + SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { + conn->conn_array_index = conn_sl_idx; + } SMARTLIST_FOREACH_END(conn); + + /* Okay, now the worst circuits and connections are at the front of their + * respective lists. Let's mark them, and reclaim their storage + * aggressively. */ + conn_idx = 0; + SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { + size_t n; size_t freed; + + /* Free storage in any non-linked directory connections that have buffered + * data older than this circuit. */ + while (conn_idx < smartlist_len(connection_array)) { + connection_t *conn = smartlist_get(connection_array, conn_idx); + uint32_t conn_age = conn_get_buffer_age(conn, now_ms); + if (conn_age < circ->age_tmp) { + break; + } + if (conn->type == CONN_TYPE_DIR && conn->linked_conn == NULL) { + if (!conn->marked_for_close) + connection_mark_for_close(conn); + mem_recovered += single_conn_free_bytes(conn); + + ++n_dirconns_killed; + + if (mem_recovered >= mem_to_recover) + goto done_recovering_mem; + } + ++conn_idx; + } + + /* Now, kill the circuit. */ + n = n_cells_in_circ_queues(circ); if (! circ->marked_for_close) { circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); } @@ -2012,9 +2136,11 @@ circuits_handle_oom(size_t current_allocation) mem_recovered += freed; if (mem_recovered >= mem_to_recover) - break; + goto done_recovering_mem; } SMARTLIST_FOREACH_END(circ); + done_recovering_mem: + #ifdef ENABLE_MEMPOOLS clean_cell_pool(); /* In case this helps. */ #endif /* ENABLE_MEMPOOLS */ @@ -2022,12 +2148,12 @@ circuits_handle_oom(size_t current_allocation) chunks. */ log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits; " - "%d circuits remain alive.", + "%d circuits remain alive. Also killed %d non-linked directory " + "connections.", U64_PRINTF_ARG(mem_recovered), n_circuits_killed, - smartlist_len(circlist) - n_circuits_killed); - - smartlist_free(circlist); + smartlist_len(circlist) - n_circuits_killed, + n_dirconns_killed); } /** Verify that cpath layer <b>cp</b> has all of its invariants diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h index d48d7c3963..03934f971e 100644 --- a/src/or/circuitlist.h +++ b/src/or/circuitlist.h @@ -14,9 +14,7 @@ #include "testsupport.h" -TOR_LIST_HEAD(global_circuitlist_s, circuit_t); - -MOCK_DECL(struct global_circuitlist_s*, circuit_get_global_list, (void)); +MOCK_DECL(smartlist_t *, circuit_get_global_list, (void)); const char *circuit_state_to_string(int state); const char *circuit_purpose_to_controller_string(uint8_t purpose); const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose); diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c index e362b1b49e..88a1f9b46c 100644 --- a/src/or/circuitstats.c +++ b/src/or/circuitstats.c @@ -404,7 +404,7 @@ circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, * distress anyway, so memory correctness here is paramount over * doing acrobatics to preserve the array. */ - recent_circs = tor_malloc_zero(sizeof(int8_t)*num); + recent_circs = tor_calloc(sizeof(int8_t), num); if (cbt->liveness.timeouts_after_firsthop && cbt->liveness.num_recent_circs > 0) { memcpy(recent_circs, cbt->liveness.timeouts_after_firsthop, @@ -508,7 +508,7 @@ circuit_build_times_init(circuit_build_times_t *cbt) cbt->liveness.num_recent_circs = circuit_build_times_recent_circuit_count(NULL); cbt->liveness.timeouts_after_firsthop = - tor_malloc_zero(sizeof(int8_t)*cbt->liveness.num_recent_circs); + tor_calloc(sizeof(int8_t), cbt->liveness.num_recent_circs); } else { cbt->liveness.num_recent_circs = 0; cbt->liveness.timeouts_after_firsthop = NULL; @@ -649,7 +649,7 @@ circuit_build_times_create_histogram(const circuit_build_times_t *cbt, int i, c; *nbins = 1 + (max_build_time / CBT_BIN_WIDTH); - histogram = tor_malloc_zero(*nbins * sizeof(build_time_t)); + histogram = tor_calloc(*nbins, sizeof(build_time_t)); // calculate histogram for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { @@ -691,7 +691,7 @@ circuit_build_times_get_xm(circuit_build_times_t *cbt) if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE) num_modes = 1; - nth_max_bin = (build_time_t*)tor_malloc_zero(num_modes*sizeof(build_time_t)); + nth_max_bin = (build_time_t*)tor_calloc(num_modes, sizeof(build_time_t)); /* Determine the N most common build times */ for (i = 0; i < nbins; i++) { @@ -873,7 +873,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt, } /* build_time_t 0 means uninitialized */ - loaded_times = tor_malloc_zero(sizeof(build_time_t)*state->TotalBuildTimes); + loaded_times = tor_calloc(sizeof(build_time_t), state->TotalBuildTimes); for (line = state->BuildtimeHistogram; line; line = line->next) { smartlist_t *args = smartlist_new(); @@ -1371,10 +1371,11 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt) } cbt->liveness.after_firsthop_idx = 0; +#define MAX_TIMEOUT ((int32_t) (INT32_MAX/2)) /* Check to see if this has happened before. If so, double the timeout * to give people on abysmally bad network connections a shot at access */ if (cbt->timeout_ms >= circuit_build_times_get_initial_timeout()) { - if (cbt->timeout_ms > INT32_MAX/2 || cbt->close_ms > INT32_MAX/2) { + if (cbt->timeout_ms > MAX_TIMEOUT || cbt->close_ms > MAX_TIMEOUT) { log_warn(LD_CIRC, "Insanely large circuit build timeout value. " "(timeout = %fmsec, close = %fmsec)", cbt->timeout_ms, cbt->close_ms); @@ -1386,6 +1387,7 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt) cbt->close_ms = cbt->timeout_ms = circuit_build_times_get_initial_timeout(); } +#undef MAX_TIMEOUT cbt_control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 714754a672..bd42bd39cb 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -268,7 +268,6 @@ circuit_get_best(const entry_connection_t *conn, int must_be_open, uint8_t purpose, int need_uptime, int need_internal) { - circuit_t *circ; origin_circuit_t *best=NULL; struct timeval now; int intro_going_on_but_too_old = 0; @@ -281,7 +280,7 @@ circuit_get_best(const entry_connection_t *conn, tor_gettimeofday(&now); - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { origin_circuit_t *origin_circ; if (!CIRCUIT_IS_ORIGIN(circ)) continue; @@ -305,6 +304,7 @@ circuit_get_best(const entry_connection_t *conn, if (!best || circuit_is_better(origin_circ,best,conn)) best = origin_circ; } + SMARTLIST_FOREACH_END(circ); if (!best && intro_going_on_but_too_old) log_info(LD_REND|LD_CIRC, "There is an intro circuit being created " @@ -318,11 +318,9 @@ circuit_get_best(const entry_connection_t *conn, static int count_pending_general_client_circuits(void) { - const circuit_t *circ; - int count = 0; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->marked_for_close || circ->state == CIRCUIT_STATE_OPEN || circ->purpose != CIRCUIT_PURPOSE_C_GENERAL || @@ -331,6 +329,7 @@ count_pending_general_client_circuits(void) ++count; } + SMARTLIST_FOREACH_END(circ); return count; } @@ -370,7 +369,6 @@ circuit_conforms_to_options(const origin_circuit_t *circ, void circuit_expire_building(void) { - circuit_t *victim, *next_circ; /* circ_times.timeout_ms and circ_times.close_ms are from * circuit_build_times_get_initial_timeout() if we haven't computed * custom timeouts yet */ @@ -388,7 +386,7 @@ circuit_expire_building(void) * we want to be more lenient with timeouts, in case the * user has relocated and/or changed network connections. * See bug #3443. */ - TOR_LIST_FOREACH(next_circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, next_circ) { if (!CIRCUIT_IS_ORIGIN(next_circ) || /* didn't originate here */ next_circ->marked_for_close) { /* don't mess with marked circs */ continue; @@ -402,7 +400,7 @@ circuit_expire_building(void) any_opened_circs = 1; break; } - } + } SMARTLIST_FOREACH_END(next_circ); #define SET_CUTOFF(target, msec) do { \ long ms = tor_lround(msec); \ @@ -473,9 +471,8 @@ circuit_expire_building(void) MAX(get_circuit_build_close_time_ms()*2 + 1000, options->SocksTimeout * 1000)); - TOR_LIST_FOREACH(next_circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *,victim) { struct timeval cutoff; - victim = next_circ; if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */ victim->marked_for_close) /* don't mess with marked circs */ continue; @@ -780,7 +777,7 @@ circuit_expire_building(void) circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim)); - } + } SMARTLIST_FOREACH_END(victim); } /** For debugging #8387: track when we last called @@ -800,9 +797,8 @@ circuit_log_ancient_one_hop_circuits(int age) time_t cutoff = now - age; int n_found = 0; smartlist_t *log_these = smartlist_new(); - const circuit_t *circ; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { const origin_circuit_t *ocirc; if (! CIRCUIT_IS_ORIGIN(circ)) continue; @@ -817,6 +813,7 @@ circuit_log_ancient_one_hop_circuits(int age) smartlist_add(log_these, (origin_circuit_t*) ocirc); } } + SMARTLIST_FOREACH_END(circ); if (n_found == 0) goto done; @@ -831,7 +828,7 @@ circuit_log_ancient_one_hop_circuits(int age) int stream_num; const edge_connection_t *conn; char *dirty = NULL; - circ = TO_CIRCUIT(ocirc); + const circuit_t *circ = TO_CIRCUIT(ocirc); format_local_iso_time(created, (time_t)circ->timestamp_created.tv_sec); @@ -938,7 +935,6 @@ int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port, int min) { - circuit_t *circ; const node_t *exitnode; int num=0; time_t now = time(NULL); @@ -946,7 +942,7 @@ circuit_stream_is_being_handled(entry_connection_t *conn, get_options()->LongLivedPorts, conn ? conn->socks_request->port : port); - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && @@ -976,6 +972,7 @@ circuit_stream_is_being_handled(entry_connection_t *conn, } } } + SMARTLIST_FOREACH_END(circ); return 0; } @@ -989,7 +986,6 @@ circuit_stream_is_being_handled(entry_connection_t *conn, static void circuit_predict_and_launch_new(void) { - circuit_t *circ; int num=0, num_internal=0, num_uptime_internal=0; int hidserv_needs_uptime=0, hidserv_needs_capacity=1; int port_needs_uptime=0, port_needs_capacity=1; @@ -997,7 +993,7 @@ circuit_predict_and_launch_new(void) int flags = 0; /* First, count how many of each type of circuit we have already. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { cpath_build_state_t *build_state; origin_circuit_t *origin_circ; if (!CIRCUIT_IS_ORIGIN(circ)) @@ -1020,6 +1016,7 @@ circuit_predict_and_launch_new(void) if (build_state->need_uptime && build_state->is_internal) num_uptime_internal++; } + SMARTLIST_FOREACH_END(circ); /* If that's enough, then stop now. */ if (num >= MAX_UNUSED_OPEN_CIRCUITS) @@ -1223,7 +1220,6 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) static void circuit_expire_old_circuits_clientside(void) { - circuit_t *circ; struct timeval cutoff, now; tor_gettimeofday(&now); @@ -1239,7 +1235,7 @@ circuit_expire_old_circuits_clientside(void) cutoff.tv_sec -= get_options()->CircuitIdleTimeout; } - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->marked_for_close || !CIRCUIT_IS_ORIGIN(circ)) continue; /* If the circuit has been dirty for too long, and there are no streams @@ -1291,7 +1287,7 @@ circuit_expire_old_circuits_clientside(void) } } } - } + } SMARTLIST_FOREACH_END(circ); } /** How long do we wait before killing circuits with the properties @@ -1318,11 +1314,10 @@ circuit_expire_old_circuits_clientside(void) void circuit_expire_old_circuits_serverside(time_t now) { - circuit_t *circ; or_circuit_t *or_circ; time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ)) continue; or_circ = TO_OR_CIRCUIT(circ); @@ -1339,6 +1334,7 @@ circuit_expire_old_circuits_serverside(time_t now) circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } } + SMARTLIST_FOREACH_END(circ); } /** Number of testing circuits we want open before testing our bandwidth. */ @@ -1363,18 +1359,18 @@ reset_bandwidth_test(void) int circuit_enough_testing_circs(void) { - circuit_t *circ; int num = 0; if (have_performed_bandwidth_test) return 1; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && CIRCUIT_IS_ORIGIN(circ) && circ->purpose == CIRCUIT_PURPOSE_TESTING && circ->state == CIRCUIT_STATE_OPEN) num++; } + SMARTLIST_FOREACH_END(circ); return num >= NUM_PARALLEL_TESTING_CIRCS; } diff --git a/src/or/config.c b/src/or/config.c index 921503b4b9..7800ec1908 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -303,6 +303,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), @@ -558,7 +559,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); @@ -1146,7 +1148,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; } @@ -1593,6 +1596,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; @@ -1688,20 +1705,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 || @@ -2549,7 +2552,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)) { @@ -2564,6 +2568,13 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Can't use a relative path to torrc when RunAsDaemon is set."); #endif + if (server_mode(options) && options->RendConfigLines) + log_warn(LD_CONFIG, + "Tor is currently configured as a relay and a hidden service. " + "That's not very secure: you should probably run your hidden service " + "in a separate Tor process, at least -- see " + "https://trac.torproject.org/8742"); + /* XXXX require that the only port not be DirPort? */ /* XXXX require that at least one port be listened-upon. */ if (n_ports == 0 && !options->RendConfigLines) @@ -4448,7 +4459,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; @@ -4541,7 +4553,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; @@ -4830,7 +4856,7 @@ parse_client_transport_line(const or_options_t *options, if (!validate_only && !is_useless_proxy) { proxy_argc = line_length-2; tor_assert(proxy_argc > 0); - proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + proxy_argv = tor_calloc(sizeof(char *), (proxy_argc + 1)); tmp = proxy_argv; for (i=0;i<proxy_argc;i++) { /* store arguments */ *tmp++ = smartlist_get(items, 2); @@ -5110,7 +5136,7 @@ parse_server_transport_line(const or_options_t *options, if (!validate_only) { proxy_argc = line_length-2; tor_assert(proxy_argc > 0); - proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + proxy_argv = tor_calloc(sizeof(char *), (proxy_argc + 1)); tmp = proxy_argv; for (i=0;i<proxy_argc;i++) { /* store arguments */ diff --git a/src/or/connection.c b/src/or/connection.c index 4788bdf950..4d7cec7f9a 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -3715,9 +3715,15 @@ connection_handle_write_impl(connection_t *conn, int force) if (connection_state_is_connecting(conn)) { if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { log_warn(LD_BUG, "getsockopt() syscall failed"); - if (CONN_IS_EDGE(conn)) - connection_edge_end_errno(TO_EDGE_CONN(conn)); - connection_mark_for_close(conn); + if (conn->type == CONN_TYPE_OR) { + or_connection_t *orconn = TO_OR_CONN(conn); + connection_or_close_for_error(orconn, 0); + } else { + if (CONN_IS_EDGE(conn)) { + connection_edge_end_errno(TO_EDGE_CONN(conn)); + } + connection_mark_for_close(conn); + } return -1; } if (e) { diff --git a/src/or/control.c b/src/or/control.c index ec63506194..b3a9dd693e 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -194,14 +194,14 @@ log_severity_to_event(int severity) static void clear_circ_bw_fields(void) { - circuit_t *circ; origin_circuit_t *ocirc; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!CIRCUIT_IS_ORIGIN(circ)) continue; ocirc = TO_ORIGIN_CIRCUIT(circ); ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0; } + SMARTLIST_FOREACH_END(circ); } /** Set <b>global_event_mask*</b> to the bitwise OR of each live control @@ -1039,7 +1039,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, { int used_quoted_string = 0; const or_options_t *options = get_options(); - const char *errstr = NULL; + const char *errstr = "Unknown error"; char *password; size_t password_len; const char *cp; @@ -1160,9 +1160,10 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, } if (bad) { if (!also_cookie) { - log_warn(LD_CONTROL, + log_warn(LD_BUG, "Couldn't decode HashedControlPassword: invalid base16"); errstr="Couldn't decode HashedControlPassword value in configuration."; + goto err; } bad_password = 1; SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); @@ -1198,8 +1199,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, err: tor_free(password); - connection_printf_to_buf(conn, "515 Authentication failed: %s\r\n", - errstr ? errstr : "Unknown reason."); + connection_printf_to_buf(conn, "515 Authentication failed: %s\r\n", errstr); connection_mark_for_close(TO_CONN(conn)); return 0; ok: @@ -1879,9 +1879,8 @@ getinfo_helper_events(control_connection_t *control_conn, { (void) control_conn; if (!strcmp(question, "circuit-status")) { - circuit_t *circ_; smartlist_t *status = smartlist_new(); - TOR_LIST_FOREACH(circ_, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) { origin_circuit_t *circ; char *circdesc; const char *state; @@ -1903,6 +1902,7 @@ getinfo_helper_events(control_connection_t *control_conn, state, *circdesc ? " " : "", circdesc); tor_free(circdesc); } + SMARTLIST_FOREACH_END(circ_); *answer = smartlist_join_strings(status, "\r\n", 0, NULL); SMARTLIST_FOREACH(status, char *, cp, tor_free(cp)); smartlist_free(status); @@ -3908,12 +3908,11 @@ control_event_stream_bandwidth_used(void) int control_event_circ_bandwidth_used(void) { - circuit_t *circ; origin_circuit_t *ocirc; if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED)) return 0; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!CIRCUIT_IS_ORIGIN(circ)) continue; ocirc = TO_ORIGIN_CIRCUIT(circ); @@ -3926,6 +3925,7 @@ control_event_circ_bandwidth_used(void) (unsigned long)ocirc->n_written_circ_bw); ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0; } + SMARTLIST_FOREACH_END(circ); return 0; } @@ -4090,14 +4090,13 @@ format_cell_stats(char **event_string, circuit_t *circ, int control_event_circuit_cell_stats(void) { - circuit_t *circ; cell_stats_t *cell_stats; char *event_string; if (!get_options()->TestingEnableCellStatsEvent || !EVENT_IS_INTERESTING(EVENT_CELL_STATS)) return 0; cell_stats = tor_malloc(sizeof(cell_stats_t));; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->testing_cell_stats) continue; sum_up_cell_stats_by_command(circ, cell_stats); @@ -4106,6 +4105,7 @@ control_event_circuit_cell_stats(void) "650 CELL_STATS %s\r\n", event_string); tor_free(event_string); } + SMARTLIST_FOREACH_END(circ); tor_free(cell_stats); return 0; } diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 61b2c29b38..94138f8c1e 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -414,12 +414,6 @@ cpuworker_main(void *data) cpuworker_reply_t rpl; fd = fdarray[1]; /* this side is ours */ -#ifndef TOR_IS_MULTITHREADED - tor_close_socket(fdarray[0]); /* this is the side of the socketpair the - * parent uses */ - tor_free_all(1); /* so the child doesn't hold the parent's fd's open */ - handle_signals(0); /* ignore interrupts from the keyboard, etc */ -#endif tor_free(data); setup_server_onion_keys(&onion_keys); @@ -516,7 +510,7 @@ spawn_cpuworker(void) connection_t *conn; int err; - fdarray = tor_malloc(sizeof(tor_socket_t)*2); + fdarray = tor_calloc(sizeof(tor_socket_t), 2); if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fdarray)) < 0) { log_warn(LD_NET, "Couldn't construct socketpair for cpuworker: %s", tor_socket_strerror(-err)); @@ -535,10 +529,6 @@ spawn_cpuworker(void) return -1; } log_debug(LD_OR,"just spawned a cpu worker."); -#ifndef TOR_IS_MULTITHREADED - tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */ - tor_free(fdarray); -#endif conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX); diff --git a/src/or/directory.c b/src/or/directory.c index 51ea312689..d8492cbbec 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -197,9 +197,9 @@ dir_conn_purpose_to_string(int purpose) return "(unknown)"; } -/** Return true iff <b>identity_digest</b> is the digest of a router we - * believe to support extrainfo downloads. (If <b>is_authority</b> we do - * additional checking that's only valid for authorities.) */ +/** Return true iff <b>identity_digest</b> is the digest of a router which + * says that it caches extrainfos. (If <b>is_authority</b> we always + * believe that to be true.) */ int router_supports_extrainfo(const char *identity_digest, int is_authority) { diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 49fafafab2..52258e875f 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1468,7 +1468,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, * to fix the bug was 0.2.2.25-alpha. */ return (router->wants_to_be_hs_dir && router->dir_port && uptime >= get_options()->MinUptimeHidServDirectoryV2 && - node->is_running); + router_is_active(router, node, now)); } /** Don't consider routers with less bandwidth than this when computing @@ -1537,18 +1537,18 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, * sort them and use that to compute thresholds. */ n_active = n_active_nonexit = 0; /* Uptime for every active router. */ - uptimes = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + uptimes = tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers)); /* Bandwidth for every active router. */ - bandwidths_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + bandwidths_kb = tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers)); /* Bandwidth for every active non-exit router. */ bandwidths_excluding_exits_kb = - tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + tor_calloc(sizeof(uint32_t), smartlist_len(rl->routers)); /* Weighted mean time between failure for each active router. */ - mtbfs = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); + mtbfs = tor_calloc(sizeof(double), smartlist_len(rl->routers)); /* Time-known for each active router. */ - tks = tor_malloc(sizeof(long)*smartlist_len(rl->routers)); + tks = tor_calloc(sizeof(long), smartlist_len(rl->routers)); /* Weighted fractional uptime for each active router. */ - wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); + wfus = tor_calloc(sizeof(double), smartlist_len(rl->routers)); nodelist_assert_ok(); @@ -1959,13 +1959,12 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, char published[ISO_TIME_LEN+1]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; - smartlist_t *chunks = NULL; + smartlist_t *chunks = smartlist_new(); format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); - chunks = smartlist_new(); smartlist_add_asprintf(chunks, "r %s %s %s%s%s %s %d %d\n", rs->nickname, @@ -2090,10 +2089,8 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, result = smartlist_join_strings(chunks, "", 0, NULL); err: - if (chunks) { - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - } + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); return result; } diff --git a/src/or/dirvote.c b/src/or/dirvote.c index c7be343ca2..6f60e05b17 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -64,7 +64,7 @@ STATIC char * format_networkstatus_vote(crypto_pk_t *private_signing_key, networkstatus_t *v3_ns) { - smartlist_t *chunks; + smartlist_t *chunks = smartlist_new(); const char *client_versions = NULL, *server_versions = NULL; char fingerprint[FINGERPRINT_LEN+1]; char digest[DIGEST_LEN]; @@ -98,7 +98,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, server_versions_line = tor_strdup(""); } - chunks = smartlist_new(); { char published[ISO_TIME_LEN+1]; char va[ISO_TIME_LEN+1]; @@ -110,7 +109,8 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, char *params; authority_cert_t *cert = v3_ns->cert; char *methods = - make_consensus_method_list(1, MAX_SUPPORTED_CONSENSUS_METHOD, " "); + make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD, + MAX_SUPPORTED_CONSENSUS_METHOD, " "); format_iso_time(published, v3_ns->published); format_iso_time(va, v3_ns->valid_after); format_iso_time(fu, v3_ns->fresh_until); @@ -230,10 +230,9 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, done: tor_free(client_versions_line); tor_free(server_versions_line); - if (chunks) { - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - } + + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); return status; } @@ -454,8 +453,7 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, smartlist_free(alt_orports); } - if (consensus_method >= MIN_METHOD_FOR_MICRODESC && - microdesc_digest256_out) { + if (microdesc_digest256_out) { smartlist_t *digests = smartlist_new(); const char *best_microdesc_digest; SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) { @@ -537,7 +535,8 @@ compute_consensus_method(smartlist_t *votes) static int consensus_method_is_supported(int method) { - return (method >= 1) && (method <= MAX_SUPPORTED_CONSENSUS_METHOD); + return (method >= MIN_SUPPORTED_CONSENSUS_METHOD) && + (method <= MAX_SUPPORTED_CONSENSUS_METHOD); } /** Return a newly allocated string holding the numbers between low and high @@ -601,13 +600,14 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities) const int n_votes = smartlist_len(votes); smartlist_t *output; smartlist_t *param_list = smartlist_new(); + (void) method; /* We require that the parameter lists in the votes are well-formed: that is, that their keywords are unique and sorted, and that their values are between INT32_MIN and INT32_MAX inclusive. This should be guaranteed by the parsing code. */ - vals = tor_malloc(sizeof(int)*n_votes); + vals = tor_calloc(sizeof(int), n_votes); SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { if (!v->net_params) @@ -647,8 +647,7 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities) /* We've reached the end of a series. */ /* Make sure enough authorities voted on this param, unless the * the consensus method we use is too old for that. */ - if (method < MIN_METHOD_FOR_MAJORITY_PARAMS || - i > total_authorities/2 || + if (i > total_authorities/2 || i >= MIN_VOTES_FOR_PARAM) { int32_t median = median_int32(vals, i); char *out_string = tor_malloc(64+cur_param_len); @@ -1001,300 +1000,6 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G, I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); return 1; } -/** - * This function computes the bandwidth weights for consensus method 9. - * - * It has been obsoleted in favor of consensus method 10. - */ -static void -networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M, - int64_t E, int64_t D, int64_t T, - int64_t weight_scale) -{ - int64_t Wgg = -1, Wgd = -1; - int64_t Wmg = -1, Wme = -1, Wmd = -1; - int64_t Wed = -1, Wee = -1; - const char *casename; - - if (G <= 0 || M <= 0 || E <= 0 || D <= 0) { - log_warn(LD_DIR, "Consensus with empty bandwidth: " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT - " D="I64_FORMAT" T="I64_FORMAT, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - return; - } - - /* - * Computed from cases in 3.4.3 of dir-spec.txt - * - * 1. Neither are scarce - * 2. Both Guard and Exit are scarce - * a. R+D <= S - * b. R+D > S - * 3. One of Guard or Exit is scarce - * a. S+D < T/3 - * b. S+D >= T/3 - */ - if (3*E >= T && 3*G >= T) { // E >= T/3 && G >= T/3 - bw_weights_error_t berr = 0; - /* Case 1: Neither are scarce. - * - * Attempt to ensure that we have a large amount of exit bandwidth - * in the middle position. - */ - casename = "Case 1 (Wme*E = Wmd*D)"; - Wgg = (weight_scale*(D+E+G+M))/(3*G); - if (D==0) Wmd = 0; - else Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); - Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); - Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); - Wgd = 0; - Wmg = weight_scale - Wgg; - Wed = weight_scale - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, - weight_scale, G, M, E, D, T, 10, 1); - - if (berr) { - log_warn(LD_DIR, "Bw Weights error %d for case %s. " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT - " D="I64_FORMAT" T="I64_FORMAT, - berr, casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - } else if (3*E < T && 3*G < T) { // E < T/3 && G < T/3 - int64_t R = MIN(E, G); - int64_t S = MAX(E, G); - /* - * Case 2: Both Guards and Exits are scarce - * Balance D between E and G, depending upon - * D capacity and scarcity. - */ - if (R+D < S) { // Subcase a - Wgg = weight_scale; - Wee = weight_scale; - Wmg = 0; - Wme = 0; - Wmd = 0; - if (E < G) { - casename = "Case 2a (E scarce)"; - Wed = weight_scale; - Wgd = 0; - } else { /* E >= G */ - casename = "Case 2a (G scarce)"; - Wed = 0; - Wgd = weight_scale; - } - } else { // Subcase b: R+D > S - bw_weights_error_t berr = 0; - casename = "Case 2b (Wme*E == Wmd*D)"; - if (D != 0) { - Wgg = weight_scale; - Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); // T/3 >= G (Ok) - Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); // T/3 >= M - Wme = (weight_scale*(D + E + G - 2*M))/(6*E); - Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); // 2E+M >= T/3 - Wmg = 0; - Wed = weight_scale - Wgd - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, - weight_scale, G, M, E, D, T, 10, 1); - } - - if (D == 0 || berr) { // Can happen if M > T/3 - casename = "Case 2b (E=G)"; - Wgg = weight_scale; - Wee = weight_scale; - Wmg = 0; - Wme = 0; - Wmd = 0; - if (D == 0) Wgd = 0; - else Wgd = (weight_scale*(D+E-G))/(2*D); - Wed = weight_scale - Wgd; - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, - Wed, weight_scale, G, M, E, D, T, 10, 1); - } - if (berr != BW_WEIGHTS_NO_ERROR && - berr != BW_WEIGHTS_BALANCE_MID_ERROR) { - log_warn(LD_DIR, "Bw Weights error %d for case %s. " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT - " D="I64_FORMAT" T="I64_FORMAT, - berr, casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - } - } else { // if (E < T/3 || G < T/3) { - int64_t S = MIN(E, G); - // Case 3: Exactly one of Guard or Exit is scarce - if (!(3*E < T || 3*G < T) || !(3*G >= T || 3*E >= T)) { - log_warn(LD_BUG, - "Bw-Weights Case 3 but with G="I64_FORMAT" M=" - I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - - if (3*(S+D) < T) { // Subcase a: S+D < T/3 - if (G < E) { - casename = "Case 3a (G scarce)"; - Wgg = Wgd = weight_scale; - Wmd = Wed = Wmg = 0; - // Minor subcase, if E is more scarce than M, - // keep its bandwidth in place. - if (E < M) Wme = 0; - else Wme = (weight_scale*(E-M))/(2*E); - Wee = weight_scale-Wme; - } else { // G >= E - casename = "Case 3a (E scarce)"; - Wee = Wed = weight_scale; - Wmd = Wgd = Wme = 0; - // Minor subcase, if G is more scarce than M, - // keep its bandwidth in place. - if (G < M) Wmg = 0; - else Wmg = (weight_scale*(G-M))/(2*G); - Wgg = weight_scale-Wmg; - } - } else { // Subcase b: S+D >= T/3 - bw_weights_error_t berr = 0; - // D != 0 because S+D >= T/3 - if (G < E) { - casename = "Case 3b (G scarce, Wme*E == Wmd*D)"; - Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); - Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); - Wme = (weight_scale*(D + E + G - 2*M))/(6*E); - Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); - Wgg = weight_scale; - Wmg = 0; - Wed = weight_scale - Wgd - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, - Wed, weight_scale, G, M, E, D, T, 10, 1); - } else { // G >= E - casename = "Case 3b (E scarce, Wme*E == Wmd*D)"; - Wgg = (weight_scale*(D + E + G + M))/(3*G); - Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); - Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); - Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); - Wgd = 0; - Wmg = weight_scale - Wgg; - Wed = weight_scale - Wmd; - - berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, - Wed, weight_scale, G, M, E, D, T, 10, 1); - } - if (berr) { - log_warn(LD_DIR, "Bw Weights error %d for case %s. " - "G="I64_FORMAT" M="I64_FORMAT - " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, - berr, casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - } - } - } - - /* We cast down the weights to 32 bit ints on the assumption that - * weight_scale is ~= 10000. We need to ensure a rogue authority - * doesn't break this assumption to rig our weights */ - tor_assert(0 < weight_scale && weight_scale <= INT32_MAX); - - if (Wgg < 0 || Wgg > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wgg="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wgg), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - - Wgg = MAX(MIN(Wgg, weight_scale), 0); - } - if (Wgd < 0 || Wgd > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wgd="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wgd), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wgd = MAX(MIN(Wgd, weight_scale), 0); - } - if (Wmg < 0 || Wmg > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wmg="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wmg), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wmg = MAX(MIN(Wmg, weight_scale), 0); - } - if (Wme < 0 || Wme > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wme="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wme), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wme = MAX(MIN(Wme, weight_scale), 0); - } - if (Wmd < 0 || Wmd > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wmd="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wmd), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wmd = MAX(MIN(Wmd, weight_scale), 0); - } - if (Wee < 0 || Wee > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wee="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wee), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wee = MAX(MIN(Wee, weight_scale), 0); - } - if (Wed < 0 || Wed > weight_scale) { - log_warn(LD_DIR, "Bw %s: Wed="I64_FORMAT"! G="I64_FORMAT - " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, I64_PRINTF_ARG(Wed), - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); - Wed = MAX(MIN(Wed, weight_scale), 0); - } - - // Add consensus weight keywords - smartlist_add(chunks, tor_strdup("bandwidth-weights ")); - /* - * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine - * that middle nodes need different bandwidth weights for dirport traffic, - * or that weird exit policies need special weight, or that bridges - * need special weight. - * - * NOTE: This list is sorted. - */ - smartlist_add_asprintf(chunks, - "Wbd=%d Wbe=%d Wbg=%d Wbm=%d " - "Wdb=%d " - "Web=%d Wed=%d Wee=%d Weg=%d Wem=%d " - "Wgb=%d Wgd=%d Wgg=%d Wgm=%d " - "Wmb=%d Wmd=%d Wme=%d Wmg=%d Wmm=%d\n", - (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale, - (int)weight_scale, - (int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee, - (int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg, - (int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale); - - log_notice(LD_CIRC, "Computed bandwidth weights for %s with v9: " - "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT - " T="I64_FORMAT, - casename, - I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), - I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); -} /** Given a list of vote networkstatus_t in <b>votes</b>, our public * authority <b>identity_key</b>, our private authority <b>signing_key</b>, @@ -1346,18 +1051,18 @@ networkstatus_compute_consensus(smartlist_t *votes, log_warn(LD_DIR, "The other authorities will use consensus method %d, " "which I don't support. Maybe I should upgrade!", consensus_method); - consensus_method = 1; + consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD; } /* Compute medians of time-related things, and figure out how many * routers we might need to talk about. */ { int n_votes = smartlist_len(votes); - time_t *va_times = tor_malloc(n_votes * sizeof(time_t)); - time_t *fu_times = tor_malloc(n_votes * sizeof(time_t)); - time_t *vu_times = tor_malloc(n_votes * sizeof(time_t)); - int *votesec_list = tor_malloc(n_votes * sizeof(int)); - int *distsec_list = tor_malloc(n_votes * sizeof(int)); + time_t *va_times = tor_calloc(n_votes, sizeof(time_t)); + time_t *fu_times = tor_calloc(n_votes, sizeof(time_t)); + time_t *vu_times = tor_calloc(n_votes, sizeof(time_t)); + int *votesec_list = tor_calloc(n_votes, sizeof(int)); + int *distsec_list = tor_calloc(n_votes, sizeof(int)); int n_versioning_clients = 0, n_versioning_servers = 0; smartlist_t *combined_client_versions = smartlist_new(); smartlist_t *combined_server_versions = smartlist_new(); @@ -1437,10 +1142,8 @@ networkstatus_compute_consensus(smartlist_t *votes, flavor == FLAV_NS ? "" : " ", flavor == FLAV_NS ? "" : flavor_name); - if (consensus_method >= 2) { - smartlist_add_asprintf(chunks, "consensus-method %d\n", - consensus_method); - } + smartlist_add_asprintf(chunks, "consensus-method %d\n", + consensus_method); smartlist_add_asprintf(chunks, "valid-after %s\n" @@ -1457,14 +1160,12 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_free(flaglist); } - if (consensus_method >= MIN_METHOD_FOR_PARAMS) { - params = dirvote_compute_params(votes, consensus_method, - total_authorities); - if (params) { - smartlist_add(chunks, tor_strdup("params ")); - smartlist_add(chunks, params); - smartlist_add(chunks, tor_strdup("\n")); - } + params = dirvote_compute_params(votes, consensus_method, + total_authorities); + if (params) { + smartlist_add(chunks, tor_strdup("params ")); + smartlist_add(chunks, params); + smartlist_add(chunks, tor_strdup("\n")); } /* Sort the votes. */ @@ -1478,8 +1179,7 @@ networkstatus_compute_consensus(smartlist_t *votes, e->digest = get_voter(v)->identity_digest; e->is_legacy = 0; smartlist_add(dir_sources, e); - if (consensus_method >= 3 && - !tor_digest_is_zero(get_voter(v)->legacy_id_digest)) { + if (!tor_digest_is_zero(get_voter(v)->legacy_id_digest)) { dir_src_ent_t *e_legacy = tor_malloc_zero(sizeof(dir_src_ent_t)); e_legacy->v = v; e_legacy->digest = get_voter(v)->legacy_id_digest; @@ -1495,9 +1195,6 @@ networkstatus_compute_consensus(smartlist_t *votes, networkstatus_t *v = e->v; networkstatus_voter_info_t *voter = get_voter(v); - if (e->is_legacy) - tor_assert(consensus_method >= 2); - base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN); base16_encode(votedigest, sizeof(votedigest), voter->vote_digest, DIGEST_LEN); @@ -1555,9 +1252,9 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_t *chosen_flags = smartlist_new(); smartlist_t *versions = smartlist_new(); smartlist_t *exitsummaries = smartlist_new(); - uint32_t *bandwidths_kb = tor_malloc(sizeof(uint32_t) * + uint32_t *bandwidths_kb = tor_calloc(sizeof(uint32_t), smartlist_len(votes)); - uint32_t *measured_bws_kb = tor_malloc(sizeof(uint32_t) * + uint32_t *measured_bws_kb = tor_calloc(sizeof(uint32_t), smartlist_len(votes)); int num_bandwidths; int num_mbws; @@ -1570,7 +1267,6 @@ networkstatus_compute_consensus(smartlist_t *votes, * is the same flag as votes[j]->known_flags[b]. */ int *named_flag; /* Index of the flag "Named" for votes[j] */ int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */ - int chosen_named_idx; int n_authorities_measuring_bandwidth; strmap_t *name_to_id_map = strmap_new(); @@ -1579,16 +1275,15 @@ networkstatus_compute_consensus(smartlist_t *votes, memset(conflict, 0, sizeof(conflict)); memset(unknown, 0xff, sizeof(conflict)); - index = tor_malloc_zero(sizeof(int)*smartlist_len(votes)); - size = tor_malloc_zero(sizeof(int)*smartlist_len(votes)); - n_voter_flags = tor_malloc_zero(sizeof(int) * smartlist_len(votes)); - n_flag_voters = tor_malloc_zero(sizeof(int) * smartlist_len(flags)); - flag_map = tor_malloc_zero(sizeof(int*) * smartlist_len(votes)); - named_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes)); - unnamed_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes)); + index = tor_calloc(sizeof(int), smartlist_len(votes)); + size = tor_calloc(sizeof(int), smartlist_len(votes)); + n_voter_flags = tor_calloc(sizeof(int), smartlist_len(votes)); + n_flag_voters = tor_calloc(sizeof(int), smartlist_len(flags)); + flag_map = tor_calloc(sizeof(int *), smartlist_len(votes)); + named_flag = tor_calloc(sizeof(int), smartlist_len(votes)); + unnamed_flag = tor_calloc(sizeof(int), smartlist_len(votes)); for (i = 0; i < smartlist_len(votes); ++i) unnamed_flag[i] = named_flag[i] = -1; - chosen_named_idx = smartlist_string_pos(flags, "Named"); /* Build the flag indexes. Note that no vote can have more than 64 members * for known_flags, so no value will be greater than 63, so it's safe to @@ -1597,8 +1292,8 @@ networkstatus_compute_consensus(smartlist_t *votes, * that they're actually set before doing U64_LITERAL(1) << index with * them.*/ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { - flag_map[v_sl_idx] = tor_malloc_zero( - sizeof(int)*smartlist_len(v->known_flags)); + flag_map[v_sl_idx] = tor_calloc(sizeof(int), + smartlist_len(v->known_flags)); if (smartlist_len(v->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) { log_warn(LD_BUG, "Somehow, a vote has %d entries in known_flags", smartlist_len(v->known_flags)); @@ -1618,7 +1313,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } SMARTLIST_FOREACH_END(v); /* Named and Unnamed get treated specially */ - if (consensus_method >= 2) { + { SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { uint64_t nf; if (named_flag[v_sl_idx]<0) @@ -1678,7 +1373,7 @@ networkstatus_compute_consensus(smartlist_t *votes, ); /* Now go through all the votes */ - flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags)); + flag_counts = tor_calloc(sizeof(int), smartlist_len(flags)); while (1) { vote_routerstatus_t *rs; routerstatus_t rs_out; @@ -1787,10 +1482,7 @@ networkstatus_compute_consensus(smartlist_t *votes, strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname)); } - if (consensus_method == 1) { - is_named = chosen_named_idx >= 0 && - (!naming_conflict && flag_counts[chosen_named_idx]); - } else { + { const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname); if (!d) { is_named = is_unnamed = 0; @@ -1807,7 +1499,7 @@ networkstatus_compute_consensus(smartlist_t *votes, if (!strcmp(fl, "Named")) { if (is_named) smartlist_add(chosen_flags, (char*)fl); - } else if (!strcmp(fl, "Unnamed") && consensus_method >= 2) { + } else if (!strcmp(fl, "Unnamed")) { if (is_unnamed) smartlist_add(chosen_flags, (char*)fl); } else { @@ -1827,7 +1519,7 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Starting with consensus method 4 we do not list servers * that are not running in a consensus. See Proposal 138 */ - if (consensus_method >= 4 && !is_running) + if (!is_running) continue; /* Pick the version. */ @@ -1839,11 +1531,11 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Pick a bandwidth */ - if (consensus_method >= 6 && num_mbws > 2) { + if (num_mbws > 2) { rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 0; rs_out.bandwidth_kb = median_uint32(measured_bws_kb, num_mbws); - } else if (consensus_method >= 5 && num_bandwidths > 0) { + } else if (num_bandwidths > 0) { rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 1; rs_out.bandwidth_kb = median_uint32(bandwidths_kb, num_bandwidths); @@ -1857,11 +1549,9 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Fix bug 2203: Do not count BadExit nodes as Exits for bw weights */ - if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) { - is_exit = is_exit && !is_bad_exit; - } + is_exit = is_exit && !is_bad_exit; - if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { + { if (rs_out.has_bandwidth) { T += rs_out.bandwidth_kb; if (is_exit && is_guard) @@ -1892,7 +1582,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * the policy that was most often listed in votes, again breaking * ties like in the previous case. */ - if (consensus_method >= 5) { + { /* Okay, go through all the votes for this router. We prepared * that list previously */ const char *chosen_exitsummary = NULL; @@ -1963,7 +1653,6 @@ networkstatus_compute_consensus(smartlist_t *votes, } if (flavor == FLAV_MICRODESC && - consensus_method >= MIN_METHOD_FOR_MANDATORY_MICRODESC && tor_digest256_is_zero(microdesc_digest)) { /* With no microdescriptor digest, we omit the entry entirely. */ continue; @@ -2029,13 +1718,10 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_free(measured_bws_kb); } - if (consensus_method >= MIN_METHOD_FOR_FOOTER) { - /* Starting with consensus method 9, we clearly mark the directory - * footer region */ - smartlist_add(chunks, tor_strdup("directory-footer\n")); - } + /* Mark the directory footer region */ + smartlist_add(chunks, tor_strdup("directory-footer\n")); - if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { + { int64_t weight_scale = BW_WEIGHT_SCALE; char *bw_weight_param = NULL; @@ -2068,13 +1754,8 @@ networkstatus_compute_consensus(smartlist_t *votes, } } - if (consensus_method < 10) { - networkstatus_compute_bw_weights_v9(chunks, G, M, E, D, T, weight_scale); - added_weights = 1; - } else { - added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, - T, weight_scale); - } + added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, + T, weight_scale); } /* Add a signature. */ @@ -2115,7 +1796,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } smartlist_add(chunks, signature); - if (legacy_id_key_digest && legacy_signing_key && consensus_method >= 3) { + if (legacy_id_key_digest && legacy_signing_key) { smartlist_add(chunks, tor_strdup("directory-signature ")); base16_encode(fingerprint, sizeof(fingerprint), legacy_id_key_digest, DIGEST_LEN); @@ -2151,7 +1832,7 @@ networkstatus_compute_consensus(smartlist_t *votes, goto done; } // Verify balancing parameters - if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS && added_weights) { + if (added_weights) { networkstatus_verify_bw_weights(c, consensus_method); } networkstatus_vote_free(c); @@ -2275,8 +1956,11 @@ networkstatus_add_detached_signatures(networkstatus_t *target, if (!sig->good_signature && !sig->bad_signature) { cert = authority_cert_get_by_digests(sig->identity_digest, sig->signing_key_digest); - if (cert) - networkstatus_check_document_signature(target, sig, cert); + if (cert) { + /* Not checking the return value here, since we are going to look + * at the status of sig->good_signature in a moment. */ + (void) networkstatus_check_document_signature(target, sig, cert); + } } /* If this signature is good, or we don't have any signature yet, @@ -3660,7 +3344,7 @@ static const struct consensus_method_range_t { int low; int high; } microdesc_consensus_methods[] = { - {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1}, + {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_A_LINES - 1}, {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1}, {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1}, {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1}, diff --git a/src/or/dirvote.h b/src/or/dirvote.h index 4c57e43661..5eecc91d69 100644 --- a/src/or/dirvote.h +++ b/src/or/dirvote.h @@ -21,28 +21,12 @@ /** Smallest allowable voting interval. */ #define MIN_VOTE_INTERVAL 300 +/** The lowest consensus method that we currently support. */ +#define MIN_SUPPORTED_CONSENSUS_METHOD 13 + /** The highest consensus method that we currently support. */ #define MAX_SUPPORTED_CONSENSUS_METHOD 18 -/** Lowest consensus method that contains a 'directory-footer' marker */ -#define MIN_METHOD_FOR_FOOTER 9 - -/** Lowest consensus method that contains bandwidth weights */ -#define MIN_METHOD_FOR_BW_WEIGHTS 9 - -/** Lowest consensus method that contains consensus params */ -#define MIN_METHOD_FOR_PARAMS 7 - -/** Lowest consensus method that generates microdescriptors */ -#define MIN_METHOD_FOR_MICRODESC 8 - -/** Lowest consensus method that doesn't count bad exits as exits for weight */ -#define MIN_METHOD_TO_CUT_BADEXIT_WEIGHT 11 - -/** Lowest consensus method that ensures a majority of authorities voted - * for a param. */ -#define MIN_METHOD_FOR_MAJORITY_PARAMS 12 - /** Lowest consensus method where microdesc consensuses omit any entry * with no microdesc. */ #define MIN_METHOD_FOR_MANDATORY_MICRODESC 13 diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 66b7201187..edf766bb87 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -12,6 +12,8 @@ * circumvention). **/ +#define ENTRYNODES_PRIVATE + #include "or.h" #include "circpathbias.h" #include "circuitbuild.h" @@ -154,21 +156,40 @@ entry_guard_set_status(entry_guard_t *e, const node_t *node, /** Return true iff enough time has passed since we last tried to connect * to the unreachable guard <b>e</b> that we're willing to try again. */ -static int -entry_is_time_to_retry(entry_guard_t *e, time_t now) +STATIC int +entry_is_time_to_retry(const entry_guard_t *e, time_t now) { - long diff; + struct guard_retry_period_s { + time_t period_duration; + time_t interval_during_period; + }; + + struct guard_retry_period_s periods[] = { + { 6*60*60, 60*60 }, /* For first 6 hrs., retry hourly; */ + { 3*24*60*60, 4*60*60 }, /* Then retry every 4 hrs. until the + 3-day mark; */ + { 7*24*60*60, 18*60*60 }, /* After 3 days, retry every 18 hours until + 1 week mark. */ + { TIME_MAX, 36*60*60 } /* After 1 week, retry every 36 hours. */ + }; + + time_t ith_deadline_for_retry; + time_t unreachable_for; + int i; + if (e->last_attempted < e->unreachable_since) return 1; - diff = now - e->unreachable_since; - if (diff < 6*60*60) - return now > (e->last_attempted + 60*60); - else if (diff < 3*24*60*60) - return now > (e->last_attempted + 4*60*60); - else if (diff < 7*24*60*60) - return now > (e->last_attempted + 18*60*60); - else - return now > (e->last_attempted + 36*60*60); + + unreachable_for = now - e->unreachable_since; + + for (i = 0; ; i++) { + if (unreachable_for <= periods[i].period_duration) { + ith_deadline_for_retry = e->last_attempted + + periods[i].interval_during_period; + + return (now > ith_deadline_for_retry); + } + } } /** Return the node corresponding to <b>e</b>, if <b>e</b> is @@ -188,12 +209,17 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now) * If need_descriptor is true, only return the node if we currently have * a descriptor (routerinfo or microdesc) for it. */ -static INLINE const node_t * -entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, - int assume_reachable, int need_descriptor, const char **msg) +STATIC const node_t * +entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags, + const char **msg) { const node_t *node; const or_options_t *options = get_options(); + int need_uptime = (flags & ENTRY_NEED_UPTIME) != 0; + int need_capacity = (flags & ENTRY_NEED_CAPACITY) != 0; + const int assume_reachable = (flags & ENTRY_ASSUME_REACHABLE) != 0; + const int need_descriptor = (flags & ENTRY_NEED_DESCRIPTOR) != 0; + tor_assert(msg); if (e->path_bias_disabled) { @@ -255,12 +281,18 @@ num_live_entry_guards(int for_directory) { int n = 0; const char *msg; + /* Set the entry node attributes we are interested in. */ + entry_is_live_flags_t entry_flags = ENTRY_NEED_CAPACITY; + if (!for_directory) { + entry_flags |= ENTRY_NEED_DESCRIPTOR; + } + if (! entry_guards) return 0; SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { if (for_directory && !entry->is_dir_cache) continue; - if (entry_is_live(entry, 0, 1, 0, !for_directory, &msg)) + if (entry_is_live(entry, entry_flags, &msg)) ++n; } SMARTLIST_FOREACH_END(entry); return n; @@ -289,7 +321,7 @@ log_entry_guards(int severity) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { const char *msg = NULL; - if (entry_is_live(e, 0, 1, 0, 0, &msg)) + if (entry_is_live(e, ENTRY_NEED_CAPACITY, &msg)) smartlist_add_asprintf(elements, "%s [%s] (up %s)", e->nickname, hex_str(e->identity, DIGEST_LEN), @@ -350,7 +382,7 @@ control_event_guard_deferred(void) * If <b>chosen</b> is defined, use that one, and if it's not * already in our entry_guards list, put it at the *beginning*. * Else, put the one we pick at the end of the list. */ -static const node_t * +STATIC const node_t * add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, int for_discovery, int for_directory) { @@ -437,7 +469,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, /** Choose how many entry guards or directory guards we'll use. If * <b>for_directory</b> is true, we return how many directory guards to * use; else we return how many entry guards to use. */ -static int +STATIC int decide_num_guards(const or_options_t *options, int for_directory) { if (for_directory) { @@ -676,7 +708,7 @@ entry_guards_compute_status(const or_options_t *options, time_t now) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *reason = digestmap_get(reasons, entry->identity); const char *live_msg = ""; - const node_t *r = entry_is_live(entry, 0, 1, 0, 0, &live_msg); + const node_t *r = entry_is_live(entry, ENTRY_NEED_CAPACITY, &live_msg); log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", entry->nickname, hex_str(entry->identity, DIGEST_LEN), @@ -794,7 +826,9 @@ entry_guard_register_connect_status(const char *digest, int succeeded, break; if (e->made_contact) { const char *msg; - const node_t *r = entry_is_live(e, 0, 1, 1, 0, &msg); + const node_t *r = entry_is_live(e, + ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, + &msg); if (r && e->unreachable_since) { refuse_conn = 1; e->can_retry = 1; @@ -847,7 +881,7 @@ update_node_guard_status(void) /** Adjust the entry guards list so that it only contains entries from * EntryNodes, adding new entries from EntryNodes to the list as needed. */ -static void +STATIC void entry_guards_set_from_config(const or_options_t *options) { smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps; @@ -1007,47 +1041,61 @@ choose_random_dirguard(dirinfo_type_t type) return choose_random_entry_impl(NULL, 1, type, NULL); } -/** Helper for choose_random{entry,dirguard}. */ -static const node_t * -choose_random_entry_impl(cpath_build_state_t *state, int for_directory, - dirinfo_type_t dirinfo_type, int *n_options_out) +/** Filter <b>all_entry_guards</b> for usable entry guards and put them + * in <b>live_entry_guards</b>. We filter based on whether the node is + * currently alive, and on whether it satisfies the restrictions + * imposed by the other arguments of this function. + * + * We don't place more guards than NumEntryGuards in <b>live_entry_guards</b>. + * + * If <b>chosen_exit</b> is set, it contains the exit node of this + * circuit. Make sure to not use it or its family as an entry guard. + * + * If <b>need_uptime</b> is set, we are looking for a stable entry guard. + * if <b>need_capacity</b> is set, we are looking for a fast entry guard. + * + * The rest of the arguments are the same as in choose_random_entry_impl(). + * + * Return 1 if we should choose a guard right away. Return 0 if we + * should try to add more nodes to our list before deciding on a + * guard. + */ +STATIC int +populate_live_entry_guards(smartlist_t *live_entry_guards, + const smartlist_t *all_entry_guards, + const node_t *chosen_exit, + dirinfo_type_t dirinfo_type, + int for_directory, + int need_uptime, int need_capacity) { const or_options_t *options = get_options(); - smartlist_t *live_entry_guards = smartlist_new(); - smartlist_t *exit_family = smartlist_new(); - const node_t *chosen_exit = - state?build_state_get_exit_node(state) : NULL; const node_t *node = NULL; - int need_uptime = state ? state->need_uptime : 0; - int need_capacity = state ? state->need_capacity : 0; - int preferred_min, consider_exit_family = 0; - int need_descriptor = !for_directory; const int num_needed = decide_num_guards(options, for_directory); + smartlist_t *exit_family = smartlist_new(); + int retval = 0; + entry_is_live_flags_t entry_flags = 0; - if (n_options_out) - *n_options_out = 0; + { /* Set the flags we want our entry node to have */ + if (need_uptime) { + entry_flags |= ENTRY_NEED_UPTIME; + } + if (need_capacity) { + entry_flags |= ENTRY_NEED_CAPACITY; + } + if (!for_directory) { + entry_flags |= ENTRY_NEED_DESCRIPTOR; + } + } + + tor_assert(all_entry_guards); if (chosen_exit) { nodelist_add_node_and_family(exit_family, chosen_exit); - consider_exit_family = 1; } - if (!entry_guards) - entry_guards = smartlist_new(); - - if (should_add_entry_nodes) - entry_guards_set_from_config(options); - - if (!entry_list_is_constrained(options) && - smartlist_len(entry_guards) < num_needed) - pick_entry_guards(options, for_directory); - - retry: - smartlist_clear(live_entry_guards); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { + SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { const char *msg; - node = entry_is_live(entry, need_uptime, need_capacity, 0, - need_descriptor, &msg); + node = entry_is_live(entry, entry_flags, &msg); if (!node) continue; /* down, no point */ if (for_directory) { @@ -1056,39 +1104,94 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, } if (node == chosen_exit) continue; /* don't pick the same node for entry and exit */ - if (consider_exit_family && smartlist_contains(exit_family, node)) + if (smartlist_contains(exit_family, node)) continue; /* avoid relays that are family members of our exit */ if (dirinfo_type != NO_DIRINFO && !node_can_handle_dirinfo(node, dirinfo_type)) continue; /* this node won't be able to answer our dir questions */ -#if 0 /* since EntryNodes is always strict now, this clause is moot */ - if (options->EntryNodes && - !routerset_contains_node(options->EntryNodes, node)) { - /* We've come to the end of our preferred entry nodes. */ - if (smartlist_len(live_entry_guards)) - goto choose_and_finish; /* only choose from the ones we like */ - if (options->StrictNodes) { - /* in theory this case should never happen, since - * entry_guards_set_from_config() drops unwanted relays */ - tor_fragile_assert(); - } else { - log_info(LD_CIRC, - "No relays from EntryNodes available. Using others."); - } - } -#endif smartlist_add(live_entry_guards, (void*)node); if (!entry->made_contact) { /* Always start with the first not-yet-contacted entry * guard. Otherwise we might add several new ones, pick * the second new one, and now we've expanded our entry * guard list without needing to. */ - goto choose_and_finish; + retval = 1; + goto done; + } + if (smartlist_len(live_entry_guards) >= num_needed) { + retval = 1; + goto done; /* We picked enough entry guards. Done! */ } - if (smartlist_len(live_entry_guards) >= num_needed) - goto choose_and_finish; /* we have enough */ } SMARTLIST_FOREACH_END(entry); + done: + smartlist_free(exit_family); + + return retval; +} + +/** Pick a node to be used as the entry guard of a circuit. + * + * If <b>state</b> is set, it contains the information we know about + * the upcoming circuit. + * + * If <b>for_directory</b> is set, we are looking for a directory guard. + * + * <b>dirinfo_type</b> contains the kind of directory information we + * are looking for in our node. + * + * If <b>n_options_out</b> is set, we set it to the number of + * candidate guard nodes we had before picking a specific guard node. + * + * On success, return the node that should be used as the entry guard + * of the circuit. Return NULL if no such node could be found. + * + * Helper for choose_random{entry,dirguard}. +*/ +static const node_t * +choose_random_entry_impl(cpath_build_state_t *state, int for_directory, + dirinfo_type_t dirinfo_type, int *n_options_out) +{ + const or_options_t *options = get_options(); + smartlist_t *live_entry_guards = smartlist_new(); + const node_t *chosen_exit = + state?build_state_get_exit_node(state) : NULL; + const node_t *node = NULL; + int need_uptime = state ? state->need_uptime : 0; + int need_capacity = state ? state->need_capacity : 0; + int preferred_min = 0; + const int num_needed = decide_num_guards(options, for_directory); + int retval = 0; + + if (n_options_out) + *n_options_out = 0; + + if (!entry_guards) + entry_guards = smartlist_new(); + + if (should_add_entry_nodes) + entry_guards_set_from_config(options); + + if (!entry_list_is_constrained(options) && + smartlist_len(entry_guards) < num_needed) + pick_entry_guards(options, for_directory); + + retry: + smartlist_clear(live_entry_guards); + + /* Populate the list of live entry guards so that we pick one of + them. */ + retval = populate_live_entry_guards(live_entry_guards, + entry_guards, + chosen_exit, + dirinfo_type, + for_directory, + need_uptime, need_capacity); + + if (retval == 1) { /* We should choose a guard right now. */ + goto choose_and_finish; + } + if (entry_list_is_constrained(options)) { /* If we prefer the entry nodes we've got, and we have at least * one choice, that's great. Use it. */ @@ -1127,18 +1230,7 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, need_capacity = 0; goto retry; } -#if 0 - /* Removing this retry logic: if we only allow one exit, and it is in the - same family as all our entries, then we are just plain not going to win - here. */ - if (!node && entry_list_is_constrained(options) && consider_exit_family) { - /* still no? if we're using bridges or have strictentrynodes - * set, and our chosen exit is in the same family as all our - * bridges/entry guards, then be flexible about families. */ - consider_exit_family = 0; - goto retry; - } -#endif + /* live_entry_guards may be empty below. Oh well, we tried. */ } @@ -1156,7 +1248,6 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, if (n_options_out) *n_options_out = smartlist_len(live_entry_guards); smartlist_free(live_entry_guards); - smartlist_free(exit_family); return node; } diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index e229f3b79a..52b31a225d 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -77,6 +77,38 @@ int num_live_entry_guards(int for_directory); #endif +#ifdef ENTRYNODES_PRIVATE +STATIC const node_t *add_an_entry_guard(const node_t *chosen, + int reset_status, int prepend, + int for_discovery, int for_directory); + +STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards, + const smartlist_t *all_entry_guards, + const node_t *chosen_exit, + dirinfo_type_t dirinfo_type, + int for_directory, + int need_uptime, int need_capacity); +STATIC int decide_num_guards(const or_options_t *options, int for_directory); + +STATIC void entry_guards_set_from_config(const or_options_t *options); + +/** Flags to be passed to entry_is_live() to indicate what kind of + * entry nodes we are looking for. */ +typedef enum { + ENTRY_NEED_UPTIME = 1<<0, + ENTRY_NEED_CAPACITY = 1<<1, + ENTRY_ASSUME_REACHABLE = 1<<2, + ENTRY_NEED_DESCRIPTOR = 1<<3, +} entry_is_live_flags_t; + +STATIC const node_t *entry_is_live(const entry_guard_t *e, + entry_is_live_flags_t flags, + const char **msg); + +STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now); + +#endif + void remove_all_entry_guards(void); void entry_guards_compute_status(const or_options_t *options, time_t now); diff --git a/src/or/geoip.c b/src/or/geoip.c index f722bac468..feb54aac6e 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -963,7 +963,7 @@ geoip_get_dirreq_history(dirreq_type_t type) /* We may have rounded 'completed' up. Here we want to use the * real value. */ complete = smartlist_len(dirreq_completed); - dltimes = tor_malloc_zero(sizeof(uint32_t) * complete); + dltimes = tor_calloc(sizeof(uint32_t), complete); SMARTLIST_FOREACH_BEGIN(dirreq_completed, dirreq_map_entry_t *, ent) { uint32_t bytes_per_second; uint32_t time_diff = (uint32_t) tv_mdiff(&ent->request_time, @@ -1033,7 +1033,7 @@ geoip_get_client_history(geoip_client_action_t action, if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6)) return -1; - counts = tor_malloc_zero(sizeof(unsigned)*n_countries); + counts = tor_calloc(sizeof(unsigned), n_countries); HT_FOREACH(ent, clientmap, &client_history) { int country; if ((*ent)->action != (int)action) diff --git a/src/or/main.c b/src/or/main.c index 9c1cabf037..094120fecf 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1861,6 +1861,10 @@ do_hup(void) return -1; } options = get_options(); /* they have changed now */ + /* Logs are only truncated the first time they are opened, but were + probably intended to be cleaned up on signal. */ + if (options->TruncateLogFile) + truncate_logs(); } else { char *msg = NULL; log_notice(LD_GENERAL, "Not reloading config file: the controller told " @@ -2709,31 +2713,6 @@ do_dump_config(void) return 0; } -#if defined (WINCE) -int -find_flashcard_path(PWCHAR path, size_t size) -{ - WIN32_FIND_DATA d = {0}; - HANDLE h = NULL; - - if (!path) - return -1; - - h = FindFirstFlashCard(&d); - if (h == INVALID_HANDLE_VALUE) - return -1; - - if (wcslen(d.cFileName) == 0) { - FindClose(h); - return -1; - } - - wcsncpy(path,d.cFileName,size); - FindClose(h); - return 0; -} -#endif - static void init_addrinfo(void) { @@ -2754,43 +2733,47 @@ sandbox_init_filter(void) sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status")); - sandbox_cfg_allow_open_filename_array(&cfg, - get_datadir_fname("cached-certs"), - get_datadir_fname("cached-certs.tmp"), - get_datadir_fname("cached-consensus"), - get_datadir_fname("cached-consensus.tmp"), - get_datadir_fname("unverified-consensus"), - get_datadir_fname("unverified-consensus.tmp"), - get_datadir_fname("unverified-microdesc-consensus"), - get_datadir_fname("unverified-microdesc-consensus.tmp"), - get_datadir_fname("cached-microdesc-consensus"), - get_datadir_fname("cached-microdesc-consensus.tmp"), - get_datadir_fname("cached-microdescs"), - get_datadir_fname("cached-microdescs.tmp"), - get_datadir_fname("cached-microdescs.new"), - get_datadir_fname("cached-microdescs.new.tmp"), - get_datadir_fname("cached-descriptors"), - get_datadir_fname("cached-descriptors.new"), - get_datadir_fname("cached-descriptors.tmp"), - get_datadir_fname("cached-descriptors.new.tmp"), - get_datadir_fname("cached-descriptors.tmp.tmp"), - get_datadir_fname("cached-extrainfo"), - get_datadir_fname("cached-extrainfo.new"), - get_datadir_fname("cached-extrainfo.tmp"), - get_datadir_fname("cached-extrainfo.new.tmp"), - get_datadir_fname("cached-extrainfo.tmp.tmp"), - get_datadir_fname("state.tmp"), - get_datadir_fname("unparseable-desc.tmp"), - get_datadir_fname("unparseable-desc"), - get_datadir_fname("v3-status-votes"), - get_datadir_fname("v3-status-votes.tmp"), - tor_strdup("/dev/srandom"), - tor_strdup("/dev/urandom"), - tor_strdup("/dev/random"), - tor_strdup("/etc/hosts"), - tor_strdup("/proc/meminfo"), - NULL, 0 - ); +#define OPEN(name) \ + sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name)) + +#define OPEN_DATADIR(name) \ + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name)) + +#define OPEN_DATADIR2(name, name2) \ + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname2((name), (name2))) + +#define OPEN_DATADIR_SUFFIX(name, suffix) do { \ + OPEN_DATADIR(name); \ + OPEN_DATADIR(name suffix); \ + } while (0) + +#define OPEN_DATADIR2_SUFFIX(name, name2, suffix) do { \ + OPEN_DATADIR2(name, name2); \ + OPEN_DATADIR2(name, name2 suffix); \ + } while (0) + + OPEN_DATADIR_SUFFIX("cached-certs", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("unverified-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("unverified-microdesc-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-microdesc-consensus", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-microdescs", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-microdescs.new", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-descriptors", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-descriptors.new", ".tmp"); + OPEN_DATADIR("cached-descriptors.tmp.tmp"); + OPEN_DATADIR_SUFFIX("cached-extrainfo", ".tmp"); + OPEN_DATADIR_SUFFIX("cached-extrainfo.new", ".tmp"); + OPEN_DATADIR("cached-extrainfo.tmp.tmp"); + OPEN_DATADIR_SUFFIX("state", ".tmp"); + OPEN_DATADIR_SUFFIX("unparseable-desc", ".tmp"); + OPEN_DATADIR_SUFFIX("v3-status-votes", ".tmp"); + OPEN("/dev/srandom"); + OPEN("/dev/urandom"); + OPEN("/dev/random"); + OPEN("/etc/hosts"); + OPEN("/proc/meminfo"); + if (options->ServerDNSResolvConfFile) sandbox_cfg_allow_open_filename(&cfg, tor_strdup(options->ServerDNSResolvConfFile)); @@ -2831,14 +2814,17 @@ sandbox_init_filter(void) RENAME_SUFFIX("unparseable-desc", ".tmp"); RENAME_SUFFIX("v3-status-votes", ".tmp"); - sandbox_cfg_allow_stat_filename_array(&cfg, - get_datadir_fname(NULL), - get_datadir_fname("lock"), - get_datadir_fname("state"), - get_datadir_fname("router-stability"), - get_datadir_fname("cached-extrainfo.new"), - NULL, 0 - ); +#define STAT_DATADIR(name) \ + sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname(name)) + +#define STAT_DATADIR2(name, name2) \ + sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname2((name), (name2))) + + STAT_DATADIR(NULL); + STAT_DATADIR("lock"); + STAT_DATADIR("state"); + STAT_DATADIR("router-stability"); + STAT_DATADIR("cached-extrainfo.new"); { smartlist_t *files = smartlist_new(); @@ -2860,7 +2846,8 @@ sandbox_init_filter(void) sandbox_cfg_allow_rename(&cfg, tor_strdup(tmp_name), tor_strdup(file_name)); /* steals references */ - sandbox_cfg_allow_open_filename_array(&cfg, file_name, tmp_name, NULL); + sandbox_cfg_allow_open_filename(&cfg, file_name); + sandbox_cfg_allow_open_filename(&cfg, tmp_name); }); SMARTLIST_FOREACH(dirs, char *, dir, { /* steals reference */ @@ -2887,38 +2874,28 @@ sandbox_init_filter(void) // orport if (server_mode(get_options())) { - sandbox_cfg_allow_open_filename_array(&cfg, - get_datadir_fname2("keys", "secret_id_key"), - get_datadir_fname2("keys", "secret_onion_key"), - get_datadir_fname2("keys", "secret_onion_key_ntor"), - get_datadir_fname2("keys", "secret_onion_key_ntor.tmp"), - get_datadir_fname2("keys", "secret_id_key.old"), - get_datadir_fname2("keys", "secret_onion_key.old"), - get_datadir_fname2("keys", "secret_onion_key_ntor.old"), - get_datadir_fname2("keys", "secret_onion_key.tmp"), - get_datadir_fname2("keys", "secret_id_key.tmp"), - get_datadir_fname2("stats", "bridge-stats"), - get_datadir_fname2("stats", "bridge-stats.tmp"), - get_datadir_fname2("stats", "dirreq-stats"), - get_datadir_fname2("stats", "dirreq-stats.tmp"), - get_datadir_fname2("stats", "entry-stats"), - get_datadir_fname2("stats", "entry-stats.tmp"), - get_datadir_fname2("stats", "exit-stats"), - get_datadir_fname2("stats", "exit-stats.tmp"), - get_datadir_fname2("stats", "buffer-stats"), - get_datadir_fname2("stats", "buffer-stats.tmp"), - get_datadir_fname2("stats", "conn-stats"), - get_datadir_fname2("stats", "conn-stats.tmp"), - get_datadir_fname("approved-routers"), - get_datadir_fname("fingerprint"), - get_datadir_fname("fingerprint.tmp"), - get_datadir_fname("hashed-fingerprint"), - get_datadir_fname("hashed-fingerprint.tmp"), - get_datadir_fname("router-stability"), - get_datadir_fname("router-stability.tmp"), - tor_strdup("/etc/resolv.conf"), - NULL, 0 - ); + + OPEN_DATADIR2_SUFFIX("keys", "secret_id_key", "tmp"); + OPEN_DATADIR2_SUFFIX("keys", "secret_onion_key", ".tmp"); + OPEN_DATADIR2_SUFFIX("keys", "secret_onion_key_ntor", ".tmp"); + OPEN_DATADIR2("keys", "secret_id_key.old"); + OPEN_DATADIR2("keys", "secret_onion_key.old"); + OPEN_DATADIR2("keys", "secret_onion_key_ntor.old"); + + OPEN_DATADIR2_SUFFIX("stats", "bridge-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "dirreq-stats", ".tmp"); + + OPEN_DATADIR2_SUFFIX("stats", "entry-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "exit-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "buffer-stats", ".tmp"); + OPEN_DATADIR2_SUFFIX("stats", "conn-stats", ".tmp"); + + OPEN_DATADIR("approved-routers"); + OPEN_DATADIR_SUFFIX("fingerprint", ".tmp"); + OPEN_DATADIR_SUFFIX("hashed-fingerprint", ".tmp"); + OPEN_DATADIR_SUFFIX("router-stability", ".tmp"); + + OPEN("/etc/resolv.conf"); RENAME_SUFFIX("fingerprint", ".tmp"); RENAME_SUFFIX2("keys", "secret_onion_key_ntor", ".tmp"); @@ -2942,12 +2919,9 @@ sandbox_init_filter(void) get_datadir_fname2("keys", "secret_onion_key_ntor"), get_datadir_fname2("keys", "secret_onion_key_ntor.old")); - sandbox_cfg_allow_stat_filename_array(&cfg, - get_datadir_fname("keys"), - get_datadir_fname("stats"), - get_datadir_fname2("stats", "dirreq-stats"), - NULL, 0 - ); + STAT_DATADIR("keys"); + STAT_DATADIR("stats"); + STAT_DATADIR2("stats", "dirreq-stats"); } init_addrinfo(); @@ -2962,31 +2936,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 0f1457f783..3683607741 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2864,8 +2864,8 @@ typedef struct circuit_t { /** Unique ID for measuring tunneled network status requests. */ uint64_t dirreq_id; - /** Next circuit in linked list of all circuits (global_circuitlist). */ - TOR_LIST_ENTRY(circuit_t) head; + /** Index in smartlist of all circuits (global_circuitlist). */ + int global_circuitlist_idx; /** Next circuit in the doubly-linked ring of circuits waiting to add * cells to n_conn. NULL if we have no cells pending, or if we're not @@ -3402,6 +3402,8 @@ typedef struct { int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which * each log message occurs? */ + int TruncateLogFile; /**< Boolean: Should we truncate the log file + before we start writing? */ char *DebugLogFile; /**< Where to send verbose log messages. */ char *DataDirectory; /**< OR only: where to store long-term data. */ diff --git a/src/or/policies.c b/src/or/policies.c index 8a91509a77..6a9e73bdd5 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -1334,9 +1334,9 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) * The summary will either be an "accept" plus a comma-separated list of port * ranges or a "reject" plus port-ranges, depending on which is shorter. * - * If no exits are allowed at all then NULL is returned, if no ports - * are blocked instead of "reject " we return "accept 1-65535" (this - * is an exception to the shorter-representation-wins rule). + * If no exits are allowed at all then "reject 1-65535" is returned. If no + * ports are blocked instead of "reject " we return "accept 1-65535". (These + * are an exception to the shorter-representation-wins rule). */ char * policy_summarize(smartlist_t *policy, sa_family_t family) diff --git a/src/or/reasons.c b/src/or/reasons.c index 750e89bbe7..1a53a93d88 100644 --- a/src/or/reasons.c +++ b/src/or/reasons.c @@ -367,7 +367,7 @@ circuit_end_reason_to_control_string(int reason) } } -/** Return a string corresponding to a SOCKS4 reponse code. */ +/** Return a string corresponding to a SOCKS4 response code. */ const char * socks4_response_code_to_string(uint8_t code) { @@ -385,7 +385,7 @@ socks4_response_code_to_string(uint8_t code) } } -/** Return a string corresponding to a SOCKS5 reponse code. */ +/** Return a string corresponding to a SOCKS5 response code. */ const char * socks5_response_code_to_string(uint8_t code) { diff --git a/src/or/relay.c b/src/or/relay.c index f42602d412..d97c84fb07 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -523,6 +523,7 @@ relay_header_unpack(relay_header_t *dest, const uint8_t *src) static const char * relay_command_to_string(uint8_t command) { + static char buf[64]; switch (command) { case RELAY_COMMAND_BEGIN: return "BEGIN"; case RELAY_COMMAND_DATA: return "DATA"; @@ -547,7 +548,12 @@ relay_command_to_string(uint8_t command) case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED: return "RENDEZVOUS_ESTABLISHED"; case RELAY_COMMAND_INTRODUCE_ACK: return "INTRODUCE_ACK"; - default: return "(unrecognized)"; + case RELAY_COMMAND_EXTEND2: return "EXTEND2"; + case RELAY_COMMAND_EXTENDED2: return "EXTENDED2"; + default: + tor_snprintf(buf, sizeof(buf), "Unrecognized relay command %u", + (unsigned)command); + return buf; } } @@ -2322,15 +2328,15 @@ packed_cell_free(packed_cell_t *cell) void dump_cell_pool_usage(int severity) { - circuit_t *c; int n_circs = 0; int n_cells = 0; - TOR_LIST_FOREACH(c, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) { n_cells += c->n_chan_cells.n; if (!CIRCUIT_IS_ORIGIN(c)) n_cells += TO_OR_CIRCUIT(c)->p_chan_cells.n; ++n_circs; } + SMARTLIST_FOREACH_END(c); tor_log(severity, LD_MM, "%d cells allocated on %d circuits. %d cells leaked.", n_cells, n_circs, (int)total_cells_allocated - n_cells); @@ -2433,6 +2439,7 @@ cell_queues_check_size(void) { size_t alloc = cell_queues_get_total_allocation(); alloc += buf_get_total_allocation(); + alloc += tor_zlib_get_total_allocation(); if (alloc >= get_options()->MaxMemInQueues) { circuits_handle_oom(alloc); return 1; diff --git a/src/or/rendclient.c b/src/or/rendclient.c index d42024010d..fa4dc0d9c9 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -376,9 +376,8 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ) static void rend_client_close_other_intros(const char *onion_address) { - circuit_t *c; /* abort parallel intro circs, if any */ - TOR_LIST_FOREACH(c, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) { if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) && !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { @@ -393,6 +392,7 @@ rend_client_close_other_intros(const char *onion_address) } } } + SMARTLIST_FOREACH_END(c); } /** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell. diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index a664b5d501..aca9da198a 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -528,7 +528,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, return -1; } /* Base64-encode introduction points. */ - ipos_base64 = tor_malloc_zero(ipos_len * 2); + ipos_base64 = tor_calloc(ipos_len, 2); if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len)<0) { log_warn(LD_REND, "Could not encode introduction point string to " "base64. length=%d", (int)ipos_len); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index a7c1e32f15..749d6fa880 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -524,7 +524,6 @@ rend_config_services(const or_options_t *options, int validate_only) * other ones. */ if (old_service_list && !validate_only) { smartlist_t *surviving_services = smartlist_new(); - circuit_t *circ; /* Copy introduction points to new services. */ /* XXXX This is O(n^2), but it's only called on reconfigure, so it's @@ -544,7 +543,7 @@ rend_config_services(const or_options_t *options, int validate_only) /* XXXX it would be nicer if we had a nicer abstraction to use here, * so we could just iterate over the list of services to close, but * once again, this isn't critical-path code. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN && (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -569,6 +568,7 @@ rend_config_services(const or_options_t *options, int validate_only) /* XXXX Is there another reason we should use here? */ } } + SMARTLIST_FOREACH_END(circ); smartlist_free(surviving_services); SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr, rend_service_free(ptr)); @@ -1446,10 +1446,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, memwipe(hexcookie, 0, sizeof(hexcookie)); /* Free the parsed cell */ - if (parsed_req) { - rend_service_free_intro(parsed_req); - parsed_req = NULL; - } + rend_service_free_intro(parsed_req); /* Free rp if we must */ if (need_rp_free) extend_info_free(rp); @@ -1539,7 +1536,6 @@ void rend_service_free_intro(rend_intro_cell_t *request) { if (!request) { - log_info(LD_BUG, "rend_service_free_intro() called with NULL request!"); return; } @@ -1648,8 +1644,9 @@ rend_service_begin_parse_intro(const uint8_t *request, goto done; err: - if (rv) rend_service_free_intro(rv); + rend_service_free_intro(rv); rv = NULL; + if (err_msg_out && !err_msg) { tor_asprintf(&err_msg, "unknown INTRODUCE%d error", @@ -1985,7 +1982,7 @@ rend_service_decrypt_intro( char service_id[REND_SERVICE_ID_LEN_BASE32+1]; ssize_t key_len; uint8_t buf[RELAY_PAYLOAD_SIZE]; - int result, status = 0; + int result, status = -1; if (!intro || !key) { if (err_msg_out) { @@ -2064,6 +2061,8 @@ rend_service_decrypt_intro( intro->plaintext = tor_malloc(intro->plaintext_len); memcpy(intro->plaintext, buf, intro->plaintext_len); + status = 0; + goto done; err: @@ -2072,7 +2071,6 @@ rend_service_decrypt_intro( "unknown INTRODUCE%d error decrypting encrypted part", intro ? (int)(intro->type) : -1); } - if (status >= 0) status = -1; done: if (err_msg_out) *err_msg_out = err_msg; @@ -2099,7 +2097,7 @@ rend_service_parse_intro_plaintext( char *err_msg = NULL; ssize_t ver_specific_len, ver_invariant_len; uint8_t version; - int status = 0; + int status = -1; if (!intro) { if (err_msg_out) { @@ -2158,6 +2156,7 @@ rend_service_parse_intro_plaintext( (int)(intro->type), (long)(intro->plaintext_len)); status = -6; + goto err; } else { memcpy(intro->rc, intro->plaintext + ver_specific_len, @@ -2170,6 +2169,7 @@ rend_service_parse_intro_plaintext( /* Flag it as being fully parsed */ intro->parsed = 1; + status = 0; goto done; err: @@ -2178,7 +2178,6 @@ rend_service_parse_intro_plaintext( "unknown INTRODUCE%d error parsing encrypted part", intro ? (int)(intro->type) : -1); } - if (status >= 0) status = -1; done: if (err_msg_out) *err_msg_out = err_msg; @@ -2384,8 +2383,7 @@ static int count_established_intro_points(const char *query) { int num_ipos = 0; - circuit_t *circ; - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN && (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -2396,6 +2394,7 @@ count_established_intro_points(const char *query) num_ipos++; } } + SMARTLIST_FOREACH_END(circ); return num_ipos; } diff --git a/src/or/rephist.c b/src/or/rephist.c index 5446c25e36..7bc9e1ce12 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1998,12 +1998,9 @@ void rep_hist_exit_stats_init(time_t now) { start_of_exit_stats_interval = now; - exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS * - sizeof(uint64_t)); - exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS * - sizeof(uint64_t)); - exit_streams = tor_malloc_zero(EXIT_STATS_NUM_PORTS * - sizeof(uint32_t)); + exit_bytes_read = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t)); + exit_bytes_written = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t)); + exit_streams = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint32_t)); } /** Reset counters for exit port statistics. */ @@ -2474,7 +2471,6 @@ rep_hist_format_buffer_stats(time_t now) time_t rep_hist_buffer_stats_write(time_t now) { - circuit_t *circ; char *str = NULL; if (!start_of_buffer_stats_interval) @@ -2483,9 +2479,10 @@ rep_hist_buffer_stats_write(time_t now) goto done; /* Not ready to write */ /* Add open circuits to the history. */ - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { + SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { rep_hist_buffer_stats_add_circ(circ, now); } + SMARTLIST_FOREACH_END(circ); /* Generate history string. */ str = rep_hist_format_buffer_stats(now); @@ -2572,7 +2569,7 @@ rep_hist_format_desc_stats(time_t now) size = digestmap_size(served_descs); if (size > 0) { - vals = tor_malloc(size * sizeof(int)); + vals = tor_calloc(size, sizeof(int)); for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); iter = digestmap_iter_next(served_descs, iter)) { diff --git a/src/or/router.c b/src/or/router.c index 2cdbb0c8bb..87b6705d84 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1879,7 +1879,7 @@ router_rebuild_descriptor(int force) family = smartlist_new(); ri->declared_family = smartlist_new(); smartlist_split_string(family, options->MyFamily, ",", - SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); SMARTLIST_FOREACH_BEGIN(family, char *, name) { const node_t *member; if (!strcasecmp(name, options->Nickname)) @@ -2371,7 +2371,8 @@ router_dump_router_to_string(routerinfo_t *router, has_extra_info_digest ? "extra-info-digest " : "", has_extra_info_digest ? extra_info_digest : "", has_extra_info_digest ? "\n" : "", - options->DownloadExtraInfo ? "caches-extra-info\n" : "", + (options->DownloadExtraInfo || options->V3AuthoritativeDir) ? + "caches-extra-info\n" : "", onion_pkey, identity_pkey, family_line, we_are_hibernating() ? "hibernating 1\n" : "", diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b5e924522e..14451c0cd8 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -448,9 +448,10 @@ trusted_dirs_flush_certs_to_disk(void) trusted_dir_servers_certs_changed = 0; } -/** Remove all v3 authority certificates that have been superseded for more - * than 48 hours. (If the most recent cert was published more than 48 hours - * ago, then we aren't going to get any consensuses signed with older +/** Remove all expired v3 authority certificates that have been superseded for + * more than 48 hours or, if not expired, that were published more than 7 days + * before being superseded. (If the most recent cert was published more than 48 + * hours ago, then we aren't going to get any consensuses signed with older * keys.) */ static void trusted_dirs_remove_old_certs(void) @@ -488,6 +489,7 @@ trusted_dirs_remove_old_certs(void) } SMARTLIST_FOREACH_END(cert); } } DIGESTMAP_FOREACH_END; +#undef DEAD_CERT_LIFETIME #undef OLD_CERT_LIFETIME trusted_dirs_flush_certs_to_disk(); @@ -1438,7 +1440,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) /* Find all the running dirservers we know about. */ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { - int is_trusted; + int is_trusted, is_trusted_extrainfo; int is_overloaded; tor_addr_t addr; const routerstatus_t *status = node->rs; @@ -1453,8 +1455,10 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) if (requireother && router_digest_is_me(node->identity)) continue; is_trusted = router_digest_is_trusted_dir(node->identity); + is_trusted_extrainfo = router_digest_is_trusted_dir_type( + node->identity, EXTRAINFO_DIRINFO); if ((type & EXTRAINFO_DIRINFO) && - !router_supports_extrainfo(node->identity, 0)) + !router_supports_extrainfo(node->identity, is_trusted_extrainfo)) continue; if ((type & MICRODESC_DIRINFO) && !is_trusted && !node->rs->version_supports_microdesc_cache) @@ -1530,7 +1534,7 @@ dirserver_choose_by_weight(const smartlist_t *servers, double authority_weight) u64_dbl_t *weights; const dir_server_t *ds; - weights = tor_malloc(sizeof(u64_dbl_t) * n); + weights = tor_calloc(sizeof(u64_dbl_t), n); for (i = 0; i < n; ++i) { ds = smartlist_get(servers, i); weights[i].dbl = ds->weight; @@ -1805,7 +1809,7 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, double scale_factor; int i; /* big, but far away from overflowing an int64_t */ -#define SCALE_TO_U64_MAX (INT64_MAX / 4) +#define SCALE_TO_U64_MAX ((int64_t) (INT64_MAX / 4)) for (i = 0; i < n_entries; ++i) total += entries[i].dbl; @@ -2038,7 +2042,7 @@ compute_weighted_bandwidths(const smartlist_t *sl, Web /= weight_scale; Wdb /= weight_scale; - bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl)); + bandwidths = tor_calloc(sizeof(u64_dbl_t), smartlist_len(sl)); // Cycle through smartlist and total the bandwidth. SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { @@ -2185,7 +2189,7 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl, /* First count the total bandwidth weight, and make a list * of each value. We use UINT64_MAX to indicate "unknown". */ - bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl)); + bandwidths = tor_calloc(sizeof(u64_dbl_t), smartlist_len(sl)); fast_bits = bitarray_init_zero(smartlist_len(sl)); exit_bits = bitarray_init_zero(smartlist_len(sl)); guard_bits = bitarray_init_zero(smartlist_len(sl)); @@ -3292,6 +3296,14 @@ routerlist_reset_warnings(void) networkstatus_reset_warnings(); } +/** Return 1 if the signed descriptor of this router is older than + * <b>seconds</b> seconds. Otherwise return 0. */ +MOCK_IMPL(int, +router_descriptor_is_older_than,(const routerinfo_t *router, int seconds)) +{ + return router->cache_info.published_on < time(NULL) - seconds; +} + /** Add <b>router</b> to the routerlist, if we don't already have it. Replace * older entries (if any) with the same key. Note: Callers should not hold * their pointers to <b>router</b> if this function fails; <b>router</b> @@ -3461,7 +3473,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, } if (!in_consensus && from_cache && - router->cache_info.published_on < time(NULL) - OLD_ROUTER_DESC_MAX_AGE) { + router_descriptor_is_older_than(router, OLD_ROUTER_DESC_MAX_AGE)) { *msg = "Router descriptor was really old."; routerinfo_free(router); return ROUTER_WAS_NOT_NEW; @@ -3569,9 +3581,9 @@ routerlist_remove_old_cached_routers_with_id(time_t now, n_extra = n - mdpr; } - lifespans = tor_malloc_zero(sizeof(struct duration_idx_t)*n); - rmv = tor_malloc_zero(sizeof(uint8_t)*n); - must_keep = tor_malloc_zero(sizeof(uint8_t)*n); + lifespans = tor_calloc(sizeof(struct duration_idx_t), n); + rmv = tor_calloc(sizeof(uint8_t), n); + must_keep = tor_calloc(sizeof(uint8_t), n); /* Set lifespans to contain the lifespan and index of each server. */ /* Set rmv[i-lo]=1 if we're going to remove a server for being too old. */ for (i = lo; i <= hi; ++i) { diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 6e2f2eaea0..52f2303c7c 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -212,6 +212,9 @@ STATIC int choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries); STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, uint64_t *total_out); + +MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router, + int seconds)); #endif #endif diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 5add728d6d..6546d19402 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -2047,6 +2047,7 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method) double Gtotal=0, Mtotal=0, Etotal=0; const char *casename = NULL; int valid = 1; + (void) consensus_method; weight_scale = networkstatus_get_weight_scale_param(ns); Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1); @@ -2126,12 +2127,8 @@ networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method) // Then, gather G, M, E, D, T to determine case SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { int is_exit = 0; - if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) { - /* Bug #2203: Don't count bad exits as exits for balancing */ - is_exit = rs->is_exit && !rs->is_bad_exit; - } else { - is_exit = rs->is_exit; - } + /* Bug #2203: Don't count bad exits as exits for balancing */ + is_exit = rs->is_exit && !rs->is_bad_exit; if (rs->has_bandwidth) { T += rs->bandwidth_kb; if (is_exit && rs->is_possible_guard) { diff --git a/src/or/status.c b/src/or/status.c index afaa9de840..c4156d0cc3 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -28,13 +28,7 @@ static void log_accounting(const time_t now, const or_options_t *options); STATIC int count_circuits(void) { - circuit_t *circ; - int nr=0; - - TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) - nr++; - - return nr; + return smartlist_len(circuit_get_global_list()); } /** Take seconds <b>secs</b> and return a newly allocated human-readable |