summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2013-04-11 01:29:24 -0400
committerRoger Dingledine <arma@torproject.org>2013-04-11 01:29:24 -0400
commit887eba98950f2974bd2031510e1ece2279a4f106 (patch)
tree0bda88092333a1aa21925033596f395df4e3d4b1 /src/or
parentfcd9248387249d68619734a73860ffaab12b021b (diff)
parent6acf0ac2851fb95953edea9c231d82f487f28c3d (diff)
downloadtor-887eba98950f2974bd2031510e1ece2279a4f106.tar.gz
tor-887eba98950f2974bd2031510e1ece2279a4f106.zip
Merge branch 'maint-0.2.4' into release-0.2.4
Diffstat (limited to 'src/or')
-rw-r--r--src/or/addressmap.c2
-rw-r--r--src/or/channel.c24
-rw-r--r--src/or/channeltls.c2
-rw-r--r--src/or/circuitbuild.c82
-rw-r--r--src/or/circuitlist.c17
-rw-r--r--src/or/circuitlist.h2
-rw-r--r--src/or/circuitstats.c29
-rw-r--r--src/or/circuituse.c80
-rw-r--r--src/or/circuituse.h1
-rw-r--r--src/or/config.c28
-rw-r--r--src/or/confparse.c7
-rw-r--r--src/or/connection.c27
-rw-r--r--src/or/connection_edge.c58
-rw-r--r--src/or/control.c24
-rw-r--r--src/or/control.h3
-rw-r--r--src/or/cpuworker.c7
-rw-r--r--src/or/dirserv.c302
-rw-r--r--src/or/dirserv.h14
-rw-r--r--src/or/dirvote.c4
-rw-r--r--src/or/dirvote.h3
-rw-r--r--src/or/dnsserv.c11
-rw-r--r--src/or/dnsserv.h3
-rw-r--r--src/or/entrynodes.c96
-rw-r--r--src/or/hibernate.c4
-rw-r--r--src/or/main.c8
-rw-r--r--src/or/microdesc.c86
-rw-r--r--src/or/microdesc.h4
-rw-r--r--src/or/networkstatus.c12
-rw-r--r--src/or/networkstatus.h1
-rw-r--r--src/or/nodelist.c20
-rw-r--r--src/or/nodelist.h1
-rw-r--r--src/or/or.h40
-rw-r--r--src/or/policies.c18
-rw-r--r--src/or/policies.h2
-rw-r--r--src/or/relay.c94
-rw-r--r--src/or/rendcommon.c7
-rw-r--r--src/or/rendcommon.h1
-rw-r--r--src/or/router.c17
-rw-r--r--src/or/router.h2
-rw-r--r--src/or/routerlist.c53
-rw-r--r--src/or/routerlist.h2
-rw-r--r--src/or/routerparse.c17
-rw-r--r--src/or/routerparse.h2
-rw-r--r--src/or/status.c6
-rw-r--r--src/or/transports.c4
45 files changed, 895 insertions, 332 deletions
diff --git a/src/or/addressmap.c b/src/or/addressmap.c
index 826eb301db..79e4b7c5e2 100644
--- a/src/or/addressmap.c
+++ b/src/or/addressmap.c
@@ -560,7 +560,7 @@ addressmap_register(const char *address, char *new_address, time_t expires,
log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'",
safe_str_client(address),
safe_str_client(ent->new_address));
- control_event_address_mapped(address, ent->new_address, expires, NULL);
+ control_event_address_mapped(address, ent->new_address, expires, NULL, 1);
}
/** An attempt to resolve <b>address</b> failed at some OR.
diff --git a/src/or/channel.c b/src/or/channel.c
index 82db061af9..4e9086f2e6 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -1751,6 +1751,14 @@ channel_write_cell(channel_t *chan, cell_t *cell)
tor_assert(chan);
tor_assert(cell);
+ if (chan->state == CHANNEL_STATE_CLOSING) {
+ log_debug(LD_CHANNEL, "Discarding cell_t %p on closing channel %p with "
+ "global ID "U64_FORMAT, cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ tor_free(cell);
+ return;
+ }
+
log_debug(LD_CHANNEL,
"Writing cell_t %p to channel %p with global ID "
U64_FORMAT,
@@ -1777,6 +1785,14 @@ channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell)
tor_assert(chan);
tor_assert(packed_cell);
+ if (chan->state == CHANNEL_STATE_CLOSING) {
+ log_debug(LD_CHANNEL, "Discarding packed_cell_t %p on closing channel %p "
+ "with global ID "U64_FORMAT, packed_cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ packed_cell_free(packed_cell);
+ return;
+ }
+
log_debug(LD_CHANNEL,
"Writing packed_cell_t %p to channel %p with global ID "
U64_FORMAT,
@@ -1805,6 +1821,14 @@ channel_write_var_cell(channel_t *chan, var_cell_t *var_cell)
tor_assert(chan);
tor_assert(var_cell);
+ if (chan->state == CHANNEL_STATE_CLOSING) {
+ log_debug(LD_CHANNEL, "Discarding var_cell_t %p on closing channel %p "
+ "with global ID "U64_FORMAT, var_cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ var_cell_free(var_cell);
+ return;
+ }
+
log_debug(LD_CHANNEL,
"Writing var_cell_t %p to channel %p with global ID "
U64_FORMAT,
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 1035a14127..60693daeb2 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1208,7 +1208,7 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(chan->conn->handshake_state);
end = cell->payload + cell->payload_len;
- for (cp = cell->payload; cp+1 < end; ++cp) {
+ for (cp = cell->payload; cp+1 < end; cp += 2) {
uint16_t v = ntohs(get_uint16(cp));
if (is_or_protocol_version_known(v) && v > highest_supported_version)
highest_supported_version = v;
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index fbe94a98ba..31242f6c14 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -803,6 +803,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0);
}
+ pathbias_count_build_success(circ);
+ circuit_rep_hist_note_result(circ);
+ circuit_has_opened(circ); /* do other actions as necessary */
+
if (!can_complete_circuit && !circ->build_state->onehop_tunnel) {
const or_options_t *options = get_options();
can_complete_circuit=1;
@@ -819,10 +823,6 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
}
}
- pathbias_count_build_success(circ);
- circuit_rep_hist_note_result(circ);
- circuit_has_opened(circ); /* do other actions as necessary */
-
/* We're done with measurement circuits here. Just close them */
if (circ->base_.purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
@@ -901,7 +901,7 @@ circuit_note_clock_jumped(int seconds_elapsed)
control_event_client_status(severity, "CIRCUIT_NOT_ESTABLISHED REASON=%s",
"CLOCK_JUMPED");
circuit_mark_all_unused_circs();
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
}
/** Take the 'extend' <b>cell</b>, pull out addr/port plus the onion
@@ -1378,7 +1378,7 @@ pathbias_should_count(origin_circuit_t *circ)
if (circ->build_state->desired_path_len != 1 ||
!circ->build_state->onehop_tunnel) {
if ((rate_msg = rate_limit_log(&count_limit, approx_time()))) {
- log_notice(LD_BUG,
+ log_info(LD_BUG,
"One-hop circuit has length %d. Path state is %s. "
"Circuit is a %s currently %s.%s",
circ->build_state->desired_path_len,
@@ -1539,7 +1539,7 @@ pathbias_count_build_success(origin_circuit_t *circ)
guard->circ_successes++;
entry_guards_changed();
- log_info(LD_CIRC, "Got success count %f/%f for guard %s=%s",
+ log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)",
guard->circ_successes, guard->circ_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
} else {
@@ -1558,7 +1558,7 @@ pathbias_count_build_success(origin_circuit_t *circ)
if (guard->circ_attempts < guard->circ_successes) {
log_notice(LD_BUG, "Unexpectedly high successes counts (%f/%f) "
- "for guard %s=%s",
+ "for guard %s ($%s)",
guard->circ_successes, guard->circ_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
}
@@ -1626,7 +1626,7 @@ pathbias_count_use_attempt(origin_circuit_t *circ)
entry_guards_changed();
log_debug(LD_CIRC,
- "Marked circuit %d (%f/%f) as used for guard %s=%s.",
+ "Marked circuit %d (%f/%f) as used for guard %s ($%s).",
circ->global_identifier,
guard->use_successes, guard->use_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
@@ -1734,9 +1734,16 @@ pathbias_count_use_success(origin_circuit_t *circ)
guard->use_successes++;
entry_guards_changed();
+ if (guard->use_attempts < guard->use_successes) {
+ log_notice(LD_BUG, "Unexpectedly high use successes counts (%f/%f) "
+ "for guard %s=%s",
+ guard->use_successes, guard->use_attempts,
+ guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ }
+
log_debug(LD_CIRC,
"Marked circuit %d (%f/%f) as used successfully for guard "
- "%s=%s.",
+ "%s ($%s).",
circ->global_identifier, guard->use_successes,
guard->use_attempts, guard->nickname,
hex_str(guard->identity, DIGEST_LEN));
@@ -2010,6 +2017,9 @@ pathbias_check_close(origin_circuit_t *ocirc, int reason)
pathbias_count_use_failed(ocirc);
break;
+ case PATH_STATE_NEW_CIRC:
+ case PATH_STATE_BUILD_ATTEMPTED:
+ case PATH_STATE_ALREADY_COUNTED:
default:
// Other states are uninteresting. No stats to count.
break;
@@ -2253,7 +2263,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
if (pathbias_get_dropguards(options)) {
if (!guard->path_bias_disabled) {
log_warn(LD_CIRC,
- "Your Guard %s=%s is failing to carry an extremely large "
+ "Your Guard %s ($%s) is failing to carry an extremely large "
"amount of stream on its circuits. "
"To avoid potential route manipulation attacks, Tor has "
"disabled use of this guard. "
@@ -2279,7 +2289,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
} else if (!guard->path_bias_use_extreme) {
guard->path_bias_use_extreme = 1;
log_warn(LD_CIRC,
- "Your Guard %s=%s is failing to carry an extremely large "
+ "Your Guard %s ($%s) is failing to carry an extremely large "
"amount of streams on its circuits. "
"This could indicate a route manipulation attack, network "
"overload, bad local network connectivity, or a bug. "
@@ -2303,7 +2313,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
if (!guard->path_bias_use_noticed) {
guard->path_bias_use_noticed = 1;
log_notice(LD_CIRC,
- "Your Guard %s=%s is failing to carry more streams on its "
+ "Your Guard %s ($%s) is failing to carry more streams on its "
"circuits than usual. "
"Most likely this means the Tor network is overloaded "
"or your network connection is poor. "
@@ -2359,7 +2369,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
if (pathbias_get_dropguards(options)) {
if (!guard->path_bias_disabled) {
log_warn(LD_CIRC,
- "Your Guard %s=%s is failing an extremely large "
+ "Your Guard %s ($%s) is failing an extremely large "
"amount of circuits. "
"To avoid potential route manipulation attacks, Tor has "
"disabled use of this guard. "
@@ -2385,7 +2395,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
} else if (!guard->path_bias_extreme) {
guard->path_bias_extreme = 1;
log_warn(LD_CIRC,
- "Your Guard %s=%s is failing an extremely large "
+ "Your Guard %s ($%s) is failing an extremely large "
"amount of circuits. "
"This could indicate a route manipulation attack, "
"extreme network overload, or a bug. "
@@ -2409,7 +2419,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
if (!guard->path_bias_warned) {
guard->path_bias_warned = 1;
log_warn(LD_CIRC,
- "Your Guard %s=%s is failing a very large "
+ "Your Guard %s ($%s) is failing a very large "
"amount of circuits. "
"Most likely this means the Tor network is "
"overloaded, but it could also mean an attack against "
@@ -2434,7 +2444,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
if (!guard->path_bias_noticed) {
guard->path_bias_noticed = 1;
log_notice(LD_CIRC,
- "Your Guard %s=%s is failing more circuits than "
+ "Your Guard %s ($%s) is failing more circuits than "
"usual. "
"Most likely this means the Tor network is overloaded. "
"Success counts are %ld/%ld. Use counts are %ld/%ld. "
@@ -2478,6 +2488,9 @@ pathbias_scale_close_rates(entry_guard_t *guard)
int opened_built = pathbias_count_circs_in_states(guard,
PATH_STATE_BUILD_SUCCEEDED,
PATH_STATE_USE_FAILED);
+ /* Verify that the counts are sane before and after scaling */
+ int counts_are_sane = (guard->circ_attempts >= guard->circ_successes);
+
guard->circ_attempts -= opened_attempts;
guard->circ_successes -= opened_built;
@@ -2495,10 +2508,20 @@ pathbias_scale_close_rates(entry_guard_t *guard)
log_info(LD_CIRC,
"Scaled pathbias counts to (%f,%f)/%f (%d/%d open) for guard "
- "%s=%s",
+ "%s ($%s)",
guard->circ_successes, guard->successful_circuits_closed,
guard->circ_attempts, opened_built, opened_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+
+ /* Have the counts just become invalid by this scaling attempt? */
+ if (counts_are_sane && guard->circ_attempts < guard->circ_successes) {
+ log_notice(LD_BUG,
+ "Scaling has mangled pathbias counts to %f/%f (%d/%d open) "
+ "for guard %s ($%s)",
+ guard->circ_successes, guard->circ_attempts, opened_built,
+ opened_attempts, guard->nickname,
+ hex_str(guard->identity, DIGEST_LEN));
+ }
}
}
@@ -2521,6 +2544,9 @@ pathbias_scale_use_rates(entry_guard_t *guard)
double scale_ratio = pathbias_get_scale_ratio(options);
int opened_attempts = pathbias_count_circs_in_states(guard,
PATH_STATE_USE_ATTEMPTED, PATH_STATE_USE_SUCCEEDED);
+ /* Verify that the counts are sane before and after scaling */
+ int counts_are_sane = (guard->use_attempts >= guard->use_successes);
+
guard->use_attempts -= opened_attempts;
guard->use_attempts *= scale_ratio;
@@ -2529,9 +2555,20 @@ pathbias_scale_use_rates(entry_guard_t *guard)
guard->use_attempts += opened_attempts;
log_info(LD_CIRC,
- "Scaled pathbias use counts to %f/%f (%d open) for guard %s=%s",
- guard->use_successes, guard->use_attempts, opened_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ "Scaled pathbias use counts to %f/%f (%d open) for guard %s ($%s)",
+ guard->use_successes, guard->use_attempts, opened_attempts,
+ guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+
+ /* Have the counts just become invalid by this scaling attempt? */
+ if (counts_are_sane && guard->use_attempts < guard->use_successes) {
+ log_notice(LD_BUG,
+ "Scaling has mangled pathbias usage counts to %f/%f "
+ "(%d open) for guard %s ($%s)",
+ guard->circ_successes, guard->circ_attempts,
+ opened_attempts, guard->nickname,
+ hex_str(guard->identity, DIGEST_LEN));
+ }
+
entry_guards_changed();
}
}
@@ -2554,7 +2591,7 @@ entry_guard_inc_circ_attempt_count(entry_guard_t *guard)
pathbias_scale_close_rates(guard);
guard->circ_attempts++;
- log_info(LD_CIRC, "Got success count %f/%f for guard %s=%s",
+ log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)",
guard->circ_successes, guard->circ_attempts, guard->nickname,
hex_str(guard->identity, DIGEST_LEN));
return 0;
@@ -3398,6 +3435,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
});
}
/* and exclude current entry guards and their families, if applicable */
+ /*XXXX025 use the using_as_guard flag to accomplish this.*/
if (options->UseEntryGuards) {
SMARTLIST_FOREACH(get_entry_guards(), const entry_guard_t *, entry,
{
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 17e18c7603..1903fbe2eb 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -24,6 +24,7 @@
#include "nodelist.h"
#include "onion.h"
#include "onion_fast.h"
+#include "policies.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -531,6 +532,9 @@ circuit_purpose_to_string(uint8_t purpose)
case CIRCUIT_PURPOSE_CONTROLLER:
return "Circuit made by controller";
+ case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
+ return "Path-bias testing circuit";
+
default:
tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
return buf;
@@ -653,6 +657,7 @@ circuit_free(circuit_t *circ)
memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len);
tor_free(ocirc->socks_password);
}
+ addr_policy_list_free(ocirc->prepend_policy);
} else {
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
/* Remember cell statistics for this circuit before deallocating. */
@@ -1204,6 +1209,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
if ((!need_uptime || circ->build_state->need_uptime) &&
(!need_capacity || circ->build_state->need_capacity) &&
(internal == circ->build_state->is_internal) &&
+ !circ->unusable_for_new_conns &&
circ->remaining_relay_early_cells &&
circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN &&
!circ->build_state->onehop_tunnel &&
@@ -1299,20 +1305,17 @@ circuit_mark_all_unused_circs(void)
* This is useful for letting the user change pseudonyms, so new
* streams will not be linkable to old streams.
*/
-/* XXX024 this is a bad name for what this function does */
void
-circuit_expire_all_dirty_circs(void)
+circuit_mark_all_dirty_circs_as_unusable(void)
{
circuit_t *circ;
- const or_options_t *options = get_options();
for (circ=global_circuitlist; circ; circ = circ->next) {
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
- circ->timestamp_dirty)
- /* XXXX024 This is a screwed-up way to say "This is too dirty
- * for new circuits. */
- circ->timestamp_dirty -= options->MaxCircuitDirtiness;
+ circ->timestamp_dirty) {
+ mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
+ }
}
}
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index e81c0785fe..d67f80b065 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -46,7 +46,7 @@ or_circuit_t *circuit_get_intro_point(const char *digest);
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
extend_info_t *info, int flags);
void circuit_mark_all_unused_circs(void);
-void circuit_expire_all_dirty_circs(void);
+void circuit_mark_all_dirty_circs_as_unusable(void);
void circuit_mark_for_close_(circuit_t *circ, int reason,
int line, const char *file);
int circuit_get_cpath_len(origin_circuit_t *circ);
diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c
index 73e34d9ed7..1d7812bf2b 100644
--- a/src/or/circuitstats.c
+++ b/src/or/circuitstats.c
@@ -417,19 +417,16 @@ circuit_build_times_get_initial_timeout(void)
* Check if we have LearnCircuitBuildTimeout, and if we don't,
* always use CircuitBuildTimeout, no questions asked.
*/
- if (get_options()->LearnCircuitBuildTimeout) {
- if (!unit_tests && get_options()->CircuitBuildTimeout) {
- timeout = get_options()->CircuitBuildTimeout*1000;
- if (timeout < circuit_build_times_min_timeout()) {
- log_warn(LD_CIRC, "Config CircuitBuildTimeout too low. Setting to %ds",
- circuit_build_times_min_timeout()/1000);
- timeout = circuit_build_times_min_timeout();
- }
- } else {
- timeout = circuit_build_times_initial_timeout();
+ if (!unit_tests && get_options()->CircuitBuildTimeout) {
+ timeout = get_options()->CircuitBuildTimeout*1000;
+ if (get_options()->LearnCircuitBuildTimeout &&
+ timeout < circuit_build_times_min_timeout()) {
+ log_warn(LD_CIRC, "Config CircuitBuildTimeout too low. Setting to %ds",
+ circuit_build_times_min_timeout()/1000);
+ timeout = circuit_build_times_min_timeout();
}
} else {
- timeout = get_options()->CircuitBuildTimeout*1000;
+ timeout = circuit_build_times_initial_timeout();
}
return timeout;
@@ -1235,11 +1232,11 @@ circuit_build_times_network_close(circuit_build_times_t *cbt,
format_local_iso_time(last_live_buf, cbt->liveness.network_last_live);
format_local_iso_time(start_time_buf, start_time);
format_local_iso_time(now_buf, now);
- log_warn(LD_BUG,
- "Circuit somehow completed a hop while the network was "
- "not live. Network was last live at %s, but circuit launched "
- "at %s. It's now %s.", last_live_buf, start_time_buf,
- now_buf);
+ log_notice(LD_CIRC,
+ "A circuit somehow completed a hop while the network was "
+ "not live. The network was last live at %s, but the circuit "
+ "launched at %s. It's now %s. This could mean your clock "
+ "changed.", last_live_buf, start_time_buf, now_buf);
}
cbt->liveness.nonlive_timeouts++;
if (cbt->liveness.nonlive_timeouts == 1) {
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 51d8716faa..8fb70f5853 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -85,10 +85,14 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
}
if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
- purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
+ purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
if (circ->timestamp_dirty &&
circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
return 0;
+ }
+
+ if (origin_circ->unusable_for_new_conns)
+ return 0;
/* decide if this circ is suitable for this conn */
@@ -105,6 +109,8 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
+ tor_addr_t addr;
+ const int family = tor_addr_parse(&addr, conn->socks_request->address);
if (!exitnode && !build_state->onehop_tunnel) {
log_debug(LD_CIRC,"Not considering circuit with unknown router.");
return 0; /* this circuit is screwed and doesn't know it yet,
@@ -125,9 +131,7 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
return 0; /* this is a circuit to somewhere else */
if (tor_digest_is_zero(digest)) {
/* we don't know the digest; have to compare addr:port */
- tor_addr_t addr;
- int r = tor_addr_parse(&addr, conn->socks_request->address);
- if (r < 0 ||
+ if (family < 0 ||
!tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
build_state->chosen_exit->port != conn->socks_request->port)
return 0;
@@ -139,6 +143,13 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
return 0;
}
}
+ if (origin_circ->prepend_policy && family != -1) {
+ int r = compare_tor_addr_to_addr_policy(&addr,
+ conn->socks_request->port,
+ origin_circ->prepend_policy);
+ if (r == ADDR_POLICY_REJECTED)
+ return 0;
+ }
if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
/* can't exit from this router */
return 0;
@@ -518,15 +529,25 @@ circuit_expire_building(void)
if (timercmp(&victim->timestamp_began, &cutoff, >))
continue; /* it's still young, leave it alone */
- if (!any_opened_circs) {
+ /* We need to double-check the opened state here because
+ * we don't want to consider opened 1-hop dircon circuits for
+ * deciding when to relax the timeout, but we *do* want to relax
+ * those circuits too if nothing else is opened *and* they still
+ * aren't either. */
+ if (!any_opened_circs && victim->state != CIRCUIT_STATE_OPEN) {
/* It's still young enough that we wouldn't close it, right? */
if (timercmp(&victim->timestamp_began, &close_cutoff, >)) {
if (!TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout) {
int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath->state
== CPATH_STATE_OPEN;
log_info(LD_CIRC,
- "No circuits are opened. Relaxing timeout for "
- "a circuit with channel state %s. %d guards are live.",
+ "No circuits are opened. Relaxing timeout for circuit %d "
+ "(a %s %d-hop circuit in state %s with channel state %s). "
+ "%d guards are live.",
+ TO_ORIGIN_CIRCUIT(victim)->global_identifier,
+ circuit_purpose_to_string(victim->purpose),
+ TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len,
+ circuit_state_to_string(victim->state),
channel_state_to_string(victim->n_chan->state),
num_live_entry_guards(0));
@@ -541,10 +562,14 @@ circuit_expire_building(void)
} else {
static ratelim_t relax_timeout_limit = RATELIM_INIT(3600);
log_fn_ratelim(&relax_timeout_limit, LOG_NOTICE, LD_CIRC,
- "No circuits are opened. Relaxed timeout for "
- "a circuit with channel state %s to %ldms. "
- "However, it appears the circuit has timed out anyway. "
- "%d guards are live.",
+ "No circuits are opened. Relaxed timeout for circuit %d "
+ "(a %s %d-hop circuit in state %s with channel state %s) to "
+ "%ldms. However, it appears the circuit has timed out "
+ "anyway. %d guards are live.",
+ TO_ORIGIN_CIRCUIT(victim)->global_identifier,
+ circuit_purpose_to_string(victim->purpose),
+ TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len,
+ circuit_state_to_string(victim->state),
channel_state_to_string(victim->n_chan->state),
(long)circ_times.close_ms, num_live_entry_guards(0));
}
@@ -660,7 +685,7 @@ circuit_expire_building(void)
circuit_purpose_to_string(victim->purpose));
} else if (circuit_build_times_count_close(&circ_times,
first_hop_succeeded,
- victim->timestamp_began.tv_sec)) {
+ victim->timestamp_created.tv_sec)) {
circuit_build_times_set_timeout(&circ_times);
}
}
@@ -799,9 +824,12 @@ circuit_stream_is_being_handled(entry_connection_t *conn,
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
(!circ->timestamp_dirty ||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) {
- cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ cpath_build_state_t *build_state = origin_circ->build_state;
if (build_state->is_internal || build_state->onehop_tunnel)
continue;
+ if (!origin_circ->unusable_for_new_conns)
+ continue;
exitnode = build_state_get_exit_node(build_state);
if (exitnode && (!need_uptime || build_state->need_uptime)) {
@@ -843,6 +871,7 @@ circuit_predict_and_launch_new(void)
/* First, count how many of each type of circuit we have already. */
for (circ=global_circuitlist;circ;circ = circ->next) {
cpath_build_state_t *build_state;
+ origin_circuit_t *origin_circ;
if (!CIRCUIT_IS_ORIGIN(circ))
continue;
if (circ->marked_for_close)
@@ -851,7 +880,10 @@ circuit_predict_and_launch_new(void)
continue; /* only count clean circs */
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
continue; /* only pay attention to general-purpose circs */
- build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ if (origin_circ->unusable_for_new_conns)
+ continue;
+ build_state = origin_circ->build_state;
if (build_state->onehop_tunnel)
continue;
num++;
@@ -2275,3 +2307,23 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
}
}
+/** Mark <b>circ</b> so that no more connections can be attached to it. */
+void
+mark_circuit_unusable_for_new_conns(origin_circuit_t *circ)
+{
+ const or_options_t *options = get_options();
+ tor_assert(circ);
+
+ /* XXXX025 This is a kludge; we're only keeping it around in case there's
+ * something that doesn't check unusable_for_new_conns, and to avoid
+ * deeper refactoring of our expiration logic. */
+ if (! circ->base_.timestamp_dirty)
+ circ->base_.timestamp_dirty = approx_time();
+ if (options->MaxCircuitDirtiness >= circ->base_.timestamp_dirty)
+ circ->base_.timestamp_dirty = 1; /* prevent underflow */
+ else
+ circ->base_.timestamp_dirty -= options->MaxCircuitDirtiness;
+
+ circ->unusable_for_new_conns = 1;
+}
+
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index d4d68aad92..11e5a64163 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -55,6 +55,7 @@ void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose);
int hostname_in_track_host_exits(const or_options_t *options,
const char *address);
+void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ);
#endif
diff --git a/src/or/config.c b/src/or/config.c
index 15138f9d7b..ffa984bcda 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001 Matej Pfajfar.
+ /* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2013, The Tor Project, Inc. */
@@ -255,6 +255,7 @@ static config_var_t option_vars_[] = {
#endif
OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"),
OBSOLETE("Group"),
+ V(GuardLifetime, INTERVAL, "0 minutes"),
V(HardwareAccel, BOOL, "0"),
V(HeartbeatPeriod, INTERVAL, "6 hours"),
V(AccelName, STRING, NULL),
@@ -300,6 +301,7 @@ static config_var_t option_vars_[] = {
V(MaxClientCircuitsPending, UINT, "32"),
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
+ V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
OBSOLETE("MonthlyAccountingStart"),
V(MyFamily, STRING, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
@@ -339,6 +341,8 @@ static config_var_t option_vars_[] = {
V(PerConnBWRate, MEMUNIT, "0"),
V(PidFile, STRING, NULL),
V(TestingTorNetwork, BOOL, "0"),
+ V(TestingMinExitFlagThreshold, MEMUNIT, "0"),
+ V(TestingMinFastFlagThreshold, MEMUNIT, "0"),
V(OptimisticData, AUTOBOOL, "auto"),
V(PortForwarding, BOOL, "0"),
V(PortForwardingHelper, FILENAME, "tor-fw-helper"),
@@ -1502,7 +1506,7 @@ options_act(const or_options_t *old_options)
"preferred or excluded node lists. "
"Abandoning previous circuits.");
circuit_mark_all_unused_circs();
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
revise_trackexithosts = 1;
}
@@ -2481,7 +2485,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too low. Increasing "
"to 0.25");
options->PathsNeededToBuildCircuits = 0.25;
- } else if (options->PathsNeededToBuildCircuits < 0.95) {
+ } else if (options->PathsNeededToBuildCircuits > 0.95) {
log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too high. Decreasing "
"to 0.95");
options->PathsNeededToBuildCircuits = 0.95;
@@ -2601,9 +2605,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->UseBridges && options->EntryNodes)
REJECT("You cannot set both UseBridges and EntryNodes.");
- if (options->EntryNodes && !options->UseEntryGuards)
- log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. "
- "EntryNodes will be ignored.");
+ if (options->EntryNodes && !options->UseEntryGuards) {
+ REJECT("If EntryNodes is set, UseEntryGuards must be enabled.");
+ }
options->AllowInvalid_ = 0;
if (options->AllowInvalidNodes) {
@@ -2721,15 +2725,19 @@ options_validate(or_options_t *old_options, or_options_t *options,
"http://freehaven.net/anonbib/#hs-attack06 for details.");
}
- if (!(options->LearnCircuitBuildTimeout) &&
- options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) {
+ if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout &&
+ options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) {
log_warn(LD_CONFIG,
- "CircuitBuildTimeout is shorter (%d seconds) than recommended "
- "(%d seconds), and LearnCircuitBuildTimeout is disabled. "
+ "CircuitBuildTimeout is shorter (%d seconds) than the recommended "
+ "minimum (%d seconds), and LearnCircuitBuildTimeout is disabled. "
"If tor isn't working, raise this value or enable "
"LearnCircuitBuildTimeout.",
options->CircuitBuildTimeout,
RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT );
+ } else if (!options->LearnCircuitBuildTimeout &&
+ !options->CircuitBuildTimeout) {
+ log_notice(LD_CONFIG, "You disabled LearnCircuitBuildTimeout, but didn't "
+ "a CircuitBuildTimeout. I'll pick a plausible default.");
}
if (options->PathBiasNoticeRate > 1.0) {
diff --git a/src/or/confparse.c b/src/or/confparse.c
index 717d4ac2aa..8863d92409 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -91,12 +91,15 @@ config_get_lines(const char *string, config_line_t **result, int extended)
{
config_line_t *list = NULL, **next;
char *k, *v;
+ const char *parse_err;
next = &list;
do {
k = v = NULL;
- string = parse_config_line_from_str(string, &k, &v);
+ string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err);
if (!string) {
+ log_warn(LD_CONFIG, "Error while parsing configuration: %s",
+ parse_err?parse_err:"<unknown>");
config_free_lines(list);
tor_free(k);
tor_free(v);
@@ -1100,6 +1103,8 @@ static struct unit_table_t time_units[] = {
{ "days", 24*60*60 },
{ "week", 7*24*60*60 },
{ "weeks", 7*24*60*60 },
+ { "month", 2629728, }, /* about 30.437 days */
+ { "months", 2629728, },
{ NULL, 0 },
};
diff --git a/src/or/connection.c b/src/or/connection.c
index c659e65fe5..2cc3d7486b 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -918,8 +918,11 @@ make_socket_reuseable(tor_socket_t sock)
* right after somebody else has let it go. But REUSEADDR on win32
* means you can bind to the port _even when somebody else
* already has it bound_. So, don't do that on Win32. */
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
- (socklen_t)sizeof(one));
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
+ (socklen_t)sizeof(one)) == -1) {
+ log_warn(LD_NET, "Error setting SO_REUSEADDR flag: %s",
+ tor_socket_strerror(errno));
+ }
#endif
}
@@ -1102,7 +1105,10 @@ connection_listener_new(const struct sockaddr *listensockaddr,
tor_assert(0);
}
- set_socket_nonblocking(s);
+ if (set_socket_nonblocking(s) == -1) {
+ tor_close_socket(s);
+ goto err;
+ }
lis_conn = listener_connection_new(type, listensockaddr->sa_family);
conn = TO_CONN(lis_conn);
@@ -1265,7 +1271,10 @@ connection_handle_listener_read(connection_t *conn, int new_type)
(int)news,(int)conn->s);
make_socket_reuseable(news);
- set_socket_nonblocking(news);
+ if (set_socket_nonblocking(news) == -1) {
+ tor_close_socket(news);
+ return 0;
+ }
if (options->ConstrainedSockets)
set_constrained_socket_buffers(news, (int)options->ConstrainedSockSize);
@@ -1494,7 +1503,11 @@ connection_connect(connection_t *conn, const char *address,
}
}
- set_socket_nonblocking(s);
+ if (set_socket_nonblocking(s) == -1) {
+ *socket_error = tor_socket_errno(s);
+ tor_close_socket(s);
+ return -1;
+ }
if (options->ConstrainedSockets)
set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);
@@ -3426,6 +3439,10 @@ connection_handle_write_impl(connection_t *conn, int force)
if (result < 0) {
if (CONN_IS_EDGE(conn))
connection_edge_end_errno(TO_EDGE_CONN(conn));
+ if (conn->type == CONN_TYPE_AP) {
+ /* writing failed; we couldn't send a SOCKS reply if we wanted to */
+ TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
connection_close_immediate(conn); /* Don't flush; connection is dead. */
connection_mark_for_close(conn);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 84d556513c..926fcab90c 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -651,7 +651,9 @@ connection_ap_expire_beginning(void)
}
continue;
}
- if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL) {
+ if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ circ->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT &&
+ circ->purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
log_warn(LD_BUG, "circuit->purpose == CIRCUIT_PURPOSE_C_GENERAL failed. "
"The purpose on the circuit was %s; it was in state %s, "
"path_state %s.",
@@ -674,12 +676,10 @@ connection_ap_expire_beginning(void)
/* un-mark it as ending, since we're going to reuse it */
conn->edge_has_sent_end = 0;
conn->end_reason = 0;
- /* kludge to make us not try this circuit again, yet to allow
- * current streams on it to survive if they can: make it
- * unattractive to use for new streams */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->timestamp_dirty);
- circ->timestamp_dirty -= options->MaxCircuitDirtiness;
+ /* make us not try this circuit again, but allow
+ * current streams on it to survive if they can */
+ mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
+
/* give our stream another 'cutoff' seconds to try */
conn->base_.timestamp_lastread += cutoff;
if (entry_conn->num_socks_retries < 250) /* avoid overflow */
@@ -1806,9 +1806,7 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
/* Mark this circuit "unusable for new streams". */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->base_.timestamp_dirty);
- circ->base_.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ mark_circuit_unusable_for_new_conns(circ);
return -1;
}
@@ -1899,9 +1897,7 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
/* Mark this circuit "unusable for new streams". */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->base_.timestamp_dirty);
- circ->base_.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ mark_circuit_unusable_for_new_conns(circ);
return -1;
}
@@ -1945,13 +1941,14 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
string_addr, payload_len) < 0)
return -1; /* circuit is closed, don't continue */
- tor_free(base_conn->address); /* Maybe already set by dnsserv. */
- base_conn->address = tor_strdup("(Tor_internal)");
+ if (!base_conn->address) {
+ /* This might be unnecessary. XXXX */
+ base_conn->address = tor_dup_addr(&base_conn->addr);
+ }
base_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket "TOR_SOCKET_T_FORMAT
", n_circ_id %u",
base_conn->s, (unsigned)circ->base_.n_circ_id);
- control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0);
return 0;
}
@@ -2043,25 +2040,21 @@ tell_controller_about_resolved_result(entry_connection_t *conn,
int ttl,
time_t expires)
{
-
- if (ttl >= 0 && (answer_type == RESOLVED_TYPE_IPV4 ||
- answer_type == RESOLVED_TYPE_HOSTNAME)) {
- return; /* we already told the controller. */
- } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
+ expires = time(NULL) + ttl;
+ if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
char *cp = tor_dup_ip(ntohl(get_uint32(answer)));
control_event_address_mapped(conn->socks_request->address,
- cp, expires, NULL);
+ cp, expires, NULL, 0);
tor_free(cp);
} else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
char *cp = tor_strndup(answer, answer_len);
control_event_address_mapped(conn->socks_request->address,
- cp, expires, NULL);
+ cp, expires, NULL, 0);
tor_free(cp);
} else {
control_event_address_mapped(conn->socks_request->address,
- "<error>",
- time(NULL)+ttl,
- "error=yes");
+ "<error>", time(NULL)+ttl,
+ "error=yes", 0);
}
}
@@ -2119,8 +2112,9 @@ connection_ap_handshake_socks_resolved(entry_connection_t *conn,
conn->socks_request->has_finished = 1;
return;
} else {
- /* This must be a request from the controller. We already sent
- * a mapaddress if there's a ttl. */
+ /* This must be a request from the controller. Since answers to those
+ * requests are not cached, they do not generate an ADDRMAP event on
+ * their own. */
tell_controller_about_resolved_result(conn, answer_type, answer_len,
(char*)answer, ttl, expires);
conn->socks_request->has_finished = 1;
@@ -2201,9 +2195,11 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
tor_assert(conn->socks_request); /* make sure it's an AP stream */
- control_event_stream_status(conn,
- status==SOCKS5_SUCCEEDED ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
- endreason);
+ if (!SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
+ control_event_stream_status(conn, status==SOCKS5_SUCCEEDED ?
+ STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
+ endreason);
+ }
/* Flag this stream's circuit as having completed a stream successfully
* (for path bias) */
diff --git a/src/or/control.c b/src/or/control.c
index 03e5d79c8e..f50b87711c 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2939,7 +2939,7 @@ handle_control_resolve(control_connection_t *conn, uint32_t len,
failed = smartlist_new();
SMARTLIST_FOREACH(args, const char *, arg, {
if (!is_keyval_pair(arg)) {
- if (dnsserv_launch_request(arg, is_reverse)<0)
+ if (dnsserv_launch_request(arg, is_reverse, conn)<0)
smartlist_add(failed, (char*)arg);
}
});
@@ -2947,7 +2947,7 @@ handle_control_resolve(control_connection_t *conn, uint32_t len,
send_control_done(conn);
SMARTLIST_FOREACH(failed, const char *, arg, {
control_event_address_mapped(arg, arg, time(NULL),
- "internal");
+ "internal", 0);
});
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
@@ -3742,7 +3742,7 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
}
}
- if (tp == STREAM_EVENT_NEW) {
+ if (tp == STREAM_EVENT_NEW || tp == STREAM_EVENT_NEW_RESOLVE) {
tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
} else {
@@ -3752,11 +3752,7 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW_RESOLVE) {
purpose = " PURPOSE=DNS_REQUEST";
} else if (tp == STREAM_EVENT_NEW) {
- if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request ||
- (conn->socks_request &&
- SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)))
- purpose = " PURPOSE=DNS_REQUEST";
- else if (conn->use_begindir) {
+ if (conn->use_begindir) {
connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
int linked_dir_purpose = -1;
if (linked && linked->type == CONN_TYPE_DIR)
@@ -4028,15 +4024,17 @@ control_event_descriptors_changed(smartlist_t *routers)
*/
int
control_event_address_mapped(const char *from, const char *to, time_t expires,
- const char *error)
+ const char *error, const int cached)
{
if (!EVENT_IS_INTERESTING(EVENT_ADDRMAP))
return 0;
if (expires < 3 || expires == TIME_MAX)
send_control_event(EVENT_ADDRMAP, ALL_FORMATS,
- "650 ADDRMAP %s %s NEVER %s\r\n", from, to,
- error?error:"");
+ "650 ADDRMAP %s %s NEVER %s%s"
+ "CACHED=\"%s\"\r\n",
+ from, to, error?error:"", error?" ":"",
+ cached?"YES":"NO");
else {
char buf[ISO_TIME_LEN+1];
char buf2[ISO_TIME_LEN+1];
@@ -4044,10 +4042,10 @@ control_event_address_mapped(const char *from, const char *to, time_t expires,
format_iso_time(buf2,expires);
send_control_event(EVENT_ADDRMAP, ALL_FORMATS,
"650 ADDRMAP %s %s \"%s\""
- " %s%sEXPIRES=\"%s\"\r\n",
+ " %s%sEXPIRES=\"%s\" CACHED=\"%s\"\r\n",
from, to, buf,
error?error:"", error?" ":"",
- buf2);
+ buf2, cached?"YES":"NO");
}
return 0;
diff --git a/src/or/control.h b/src/or/control.h
index 51ae230b09..0ea7941b13 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -53,7 +53,8 @@ int control_event_stream_bandwidth_used(void);
void control_event_logmsg(int severity, uint32_t domain, const char *msg);
int control_event_descriptors_changed(smartlist_t *routers);
int control_event_address_mapped(const char *from, const char *to,
- time_t expires, const char *error);
+ time_t expires, const char *error,
+ const int cached);
int control_event_or_authdir_new_descriptor(const char *action,
const char *desc,
size_t desclen,
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 38c6613f08..61f9faa394 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -535,13 +535,16 @@ spawn_cpuworker(void)
conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX);
- set_socket_nonblocking(fd);
-
/* set up conn so it's got all the data we need to remember */
conn->s = fd;
conn->address = tor_strdup("localhost");
tor_addr_make_unspec(&conn->addr);
+ if (set_socket_nonblocking(fd) == -1) {
+ connection_free(conn); /* this closes fd */
+ return -1;
+ }
+
if (connection_add(conn) < 0) { /* no space, forget it */
log_warn(LD_NET,"connection_add for cpuworker failed. Giving up.");
connection_free(conn); /* this closes fd */
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index badacd683d..e837e4bed5 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -66,6 +66,13 @@ static cached_dir_t *the_directory = NULL;
/** For authoritative directories: the current (v1) network status. */
static cached_dir_t the_runningrouters;
+/** Total number of routers with measured bandwidth; this is set by
+ * dirserv_count_measured_bws() before the loop in
+ * dirserv_generate_networkstatus_vote_obj() and checked by
+ * dirserv_get_credible_bandwidth() and
+ * dirserv_compute_performance_thresholds() */
+static int routers_with_measured_bw = 0;
+
static void directory_remove_invalid(void);
static cached_dir_t *dirserv_regenerate_directory(void);
static char *format_versions_list(config_line_t *ln);
@@ -85,9 +92,8 @@ static const signed_descriptor_t *get_signed_descriptor_by_fp(
time_t publish_cutoff);
static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei,
const char **msg);
-
-/************** Measured Bandwidth parsing code ******/
-#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
+static uint32_t dirserv_get_bandwidth_for_router(const routerinfo_t *ri);
+static uint32_t dirserv_get_credible_bandwidth(const routerinfo_t *ri);
/************** Fingerprint handling code ************/
@@ -1824,7 +1830,7 @@ dirserv_thinks_router_is_unreliable(time_t now,
}
}
if (need_capacity) {
- uint32_t bw = router_get_advertised_bandwidth(router);
+ uint32_t bw = dirserv_get_bandwidth_for_router(router);
if (bw < fast_bandwidth)
return 1;
}
@@ -1876,15 +1882,29 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
#define ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER 4096
/** Helper for dirserv_compute_performance_thresholds(): Decide whether to
- * include a router in our calculations, and return true iff we should. */
+ * include a router in our calculations, and return true iff we should; the
+ * require_mbw parameter is passed in by
+ * dirserv_compute_performance_thresholds() and controls whether we ever
+ * count routers with only advertised bandwidths */
static int
router_counts_toward_thresholds(const node_t *node, time_t now,
- const digestmap_t *omit_as_sybil)
+ const digestmap_t *omit_as_sybil,
+ int require_mbw)
{
+ /* Have measured bw? */
+ int have_mbw =
+ dirserv_has_measured_bw(node->ri->cache_info.identity_digest);
+ uint64_t min_bw = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER;
+ const or_options_t *options = get_options();
+
+ if (options->TestingTorNetwork) {
+ min_bw = (int64_t)options->TestingMinExitFlagThreshold;
+ }
+
return node->ri && router_is_active(node->ri, node, now) &&
!digestmap_get(omit_as_sybil, node->ri->cache_info.identity_digest) &&
- (router_get_advertised_bandwidth(node->ri) >=
- ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER);
+ (dirserv_get_credible_bandwidth(node->ri) >= min_bw) &&
+ (have_mbw || !require_mbw);
}
/** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1906,6 +1926,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
time_t now = time(NULL);
const or_options_t *options = get_options();
+ /* Require mbw? */
+ int require_mbw =
+ (routers_with_measured_bw >
+ options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
+
/* initialize these all here, in case there are no routers */
stable_uptime = 0;
stable_mtbf = 0;
@@ -1938,7 +1963,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
/* Now, fill in the arrays. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
- if (router_counts_toward_thresholds(node, now, omit_as_sybil)) {
+ if (router_counts_toward_thresholds(node, now, omit_as_sybil,
+ require_mbw)) {
routerinfo_t *ri = node->ri;
const char *id = ri->cache_info.identity_digest;
uint32_t bw;
@@ -1947,7 +1973,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
mtbfs[n_active] = rep_hist_get_stability(id, now);
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
- bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
+ bandwidths[n_active] = bw = dirserv_get_credible_bandwidth(ri);
total_bandwidth += bw;
if (node->is_exit && !node->is_bad_exit) {
total_exit_bandwidth += bw;
@@ -1985,6 +2011,9 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG,
ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG,
INT32_MAX);
+ if (options->TestingTorNetwork) {
+ min_fast = (int32_t)options->TestingMinFastFlagThreshold;
+ }
max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold",
INT32_MAX, min_fast, INT32_MAX);
if (fast_bandwidth < (uint32_t)min_fast)
@@ -2003,7 +2032,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
n_familiar = 0;
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
- if (router_counts_toward_thresholds(node, now, omit_as_sybil)) {
+ if (router_counts_toward_thresholds(node, now,
+ omit_as_sybil, require_mbw)) {
routerinfo_t *ri = node->ri;
const char *id = ri->cache_info.identity_digest;
long tk = rep_hist_get_weighted_time_known(id, now);
@@ -2046,6 +2076,203 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
tor_free(wfus);
}
+/** Measured bandwidth cache entry */
+typedef struct mbw_cache_entry_s {
+ long mbw;
+ time_t as_of;
+} mbw_cache_entry_t;
+
+/** Measured bandwidth cache - keys are identity_digests, values are
+ * mbw_cache_entry_t *. */
+static digestmap_t *mbw_cache = NULL;
+
+/** Store a measured bandwidth cache entry when reading the measured
+ * bandwidths file. */
+void
+dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
+ time_t as_of)
+{
+ mbw_cache_entry_t *e = NULL;
+
+ tor_assert(parsed_line);
+
+ /* Allocate a cache if we need */
+ if (!mbw_cache) mbw_cache = digestmap_new();
+
+ /* Check if we have an existing entry */
+ e = digestmap_get(mbw_cache, parsed_line->node_id);
+ /* If we do, we can re-use it */
+ if (e) {
+ /* Check that we really are newer, and update */
+ if (as_of > e->as_of) {
+ e->mbw = parsed_line->bw;
+ e->as_of = as_of;
+ }
+ } else {
+ /* We'll have to insert a new entry */
+ e = tor_malloc(sizeof(*e));
+ e->mbw = parsed_line->bw;
+ e->as_of = as_of;
+ digestmap_set(mbw_cache, parsed_line->node_id, e);
+ }
+}
+
+/** Clear and free the measured bandwidth cache */
+void
+dirserv_clear_measured_bw_cache(void)
+{
+ if (mbw_cache) {
+ /* Free the map and all entries */
+ digestmap_free(mbw_cache, tor_free_);
+ mbw_cache = NULL;
+ }
+}
+
+/** Scan the measured bandwidth cache and remove expired entries */
+void
+dirserv_expire_measured_bw_cache(time_t now)
+{
+
+ if (mbw_cache) {
+ /* Iterate through the cache and check each entry */
+ DIGESTMAP_FOREACH_MODIFY(mbw_cache, k, mbw_cache_entry_t *, e) {
+ if (now > e->as_of + MAX_MEASUREMENT_AGE) {
+ tor_free(e);
+ MAP_DEL_CURRENT(k);
+ }
+ } DIGESTMAP_FOREACH_END;
+
+ /* Check if we cleared the whole thing and free if so */
+ if (digestmap_size(mbw_cache) == 0) {
+ digestmap_free(mbw_cache, tor_free_);
+ mbw_cache = 0;
+ }
+ }
+}
+
+/** Get the current size of the measured bandwidth cache */
+int
+dirserv_get_measured_bw_cache_size(void)
+{
+ if (mbw_cache) return digestmap_size(mbw_cache);
+ else return 0;
+}
+
+/** Query the cache by identity digest, return value indicates whether
+ * we found it. The bw_out and as_of_out pointers receive the cached
+ * bandwidth value and the time it was cached if not NULL. */
+int
+dirserv_query_measured_bw_cache(const char *node_id, long *bw_out,
+ time_t *as_of_out)
+{
+ mbw_cache_entry_t *v = NULL;
+ int rv = 0;
+
+ if (mbw_cache && node_id) {
+ v = digestmap_get(mbw_cache, node_id);
+ if (v) {
+ /* Found something */
+ rv = 1;
+ if (bw_out) *bw_out = v->mbw;
+ if (as_of_out) *as_of_out = v->as_of;
+ }
+ }
+
+ return rv;
+}
+
+/** Predicate wrapper for dirserv_query_measured_bw_cache() */
+int
+dirserv_has_measured_bw(const char *node_id)
+{
+ return dirserv_query_measured_bw_cache(node_id, NULL, NULL);
+}
+
+/** Get the best estimate of a router's bandwidth for dirauth purposes,
+ * preferring measured to advertised values if available. */
+
+static uint32_t
+dirserv_get_bandwidth_for_router(const routerinfo_t *ri)
+{
+ uint32_t bw = 0;
+ /*
+ * Yeah, measured bandwidths in measured_bw_line_t are (implicitly
+ * signed) longs and the ones router_get_advertised_bandwidth() returns
+ * are uint32_t.
+ */
+ long mbw = 0;
+
+ if (ri) {
+ /*
+ * * First try to see if we have a measured bandwidth; don't bother with
+ * as_of_out here, on the theory that a stale measured bandwidth is still
+ * better to trust than an advertised one.
+ */
+ if (dirserv_query_measured_bw_cache(ri->cache_info.identity_digest,
+ &mbw, NULL)) {
+ /* Got one! */
+ bw = (uint32_t)mbw;
+ } else {
+ /* If not, fall back to advertised */
+ bw = router_get_advertised_bandwidth(ri);
+ }
+ }
+
+ return bw;
+}
+
+/** Look through the routerlist, and using the measured bandwidth cache count
+ * how many measured bandwidths we know. This is used to decide whether we
+ * ever trust advertised bandwidths for purposes of assigning flags. */
+static void
+dirserv_count_measured_bws(routerlist_t *rl)
+{
+ /* Initialize this first */
+ routers_with_measured_bw = 0;
+
+ tor_assert(rl);
+ tor_assert(rl->routers);
+
+ /* Iterate over the routerlist and count measured bandwidths */
+ SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
+ /* Check if we know a measured bandwidth for this one */
+ if (dirserv_has_measured_bw(ri->cache_info.identity_digest)) {
+ ++routers_with_measured_bw;
+ }
+ } SMARTLIST_FOREACH_END(ri);
+}
+
+/** Return the bandwidth we believe for assigning flags; prefer measured
+ * over advertised, and if we have above a threshold quantity of measured
+ * bandwidths, we don't want to ever give flags to unmeasured routers, so
+ * return 0. */
+static uint32_t
+dirserv_get_credible_bandwidth(const routerinfo_t *ri)
+{
+ int threshold;
+ uint32_t bw = 0;
+ long mbw;
+
+ tor_assert(ri);
+ /* Check if we have a measured bandwidth, and check the threshold if not */
+ if (!(dirserv_query_measured_bw_cache(ri->cache_info.identity_digest,
+ &mbw, NULL))) {
+ threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ if (routers_with_measured_bw > threshold) {
+ /* Return zero for unmeasured bandwidth if we are above threshold */
+ bw = 0;
+ } else {
+ /* Return an advertised bandwidth otherwise */
+ bw = router_get_advertised_bandwidth(ri);
+ }
+ } else {
+ /* We have the measured bandwidth in mbw */
+ bw = (uint32_t)mbw;
+ }
+
+ return bw;
+}
+
/** Give a statement of our current performance thresholds for inclusion
* in a vote document. */
char *
@@ -2216,9 +2443,10 @@ routerstatus_format_entry(char *buf, size_t buf_len,
return -1;
}
- /* This assert can fire for the control port, because
+ /* This assert could fire for the control port, because
* it can request NS documents before all descriptors
- * have been fetched. */
+ * have been fetched. Therefore, we only do this test when
+ * format != NS_CONTROL_PORT. */
if (tor_memneq(desc->cache_info.signed_descriptor_digest,
rs->descriptor_digest,
DIGEST_LEN)) {
@@ -2327,8 +2555,8 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
else if (!first_is_running && second_is_running)
return 1;
- bw_first = router_get_advertised_bandwidth(first);
- bw_second = router_get_advertised_bandwidth(second);
+ bw_first = dirserv_get_bandwidth_for_router(first);
+ bw_second = dirserv_get_bandwidth_for_router(second);
if (bw_first > bw_second)
return -1;
@@ -2468,7 +2696,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
int listbaddirs, int vote_on_hsdirs)
{
const or_options_t *options = get_options();
- uint32_t routerbw = router_get_advertised_bandwidth(ri);
+ uint32_t routerbw = dirserv_get_credible_bandwidth(ri);
memset(rs, 0, sizeof(routerstatus_t));
@@ -2670,8 +2898,9 @@ dirserv_read_measured_bandwidths(const char *from_file,
char line[256];
FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
- time_t file_time;
+ time_t file_time, now;
int ok;
+
if (fp == NULL) {
log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
from_file);
@@ -2695,7 +2924,8 @@ dirserv_read_measured_bandwidths(const char *from_file,
return -1;
}
- if ((time(NULL) - file_time) > MAX_MEASUREMENT_AGE) {
+ now = time(NULL);
+ if ((now - file_time) > MAX_MEASUREMENT_AGE) {
log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
(unsigned)(time(NULL) - file_time));
fclose(fp);
@@ -2709,12 +2939,17 @@ dirserv_read_measured_bandwidths(const char *from_file,
measured_bw_line_t parsed_line;
if (fgets(line, sizeof(line), fp) && strlen(line)) {
if (measured_bw_line_parse(&parsed_line, line) != -1) {
+ /* Also cache the line for dirserv_get_bandwidth_for_router() */
+ dirserv_cache_measured_bw(&parsed_line, file_time);
if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
applied_lines++;
}
}
}
+ /* Now would be a nice time to clean the cache, too */
+ dirserv_expire_measured_bw_cache(now);
+
fclose(fp);
log_info(LD_DIRSERV,
"Bandwidth measurement file successfully read. "
@@ -2778,6 +3013,22 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
if (!contact)
contact = "(none)";
+ /*
+ * Do this so dirserv_compute_performance_thresholds() and
+ * set_routerstatus_from_routerinfo() see up-to-date bandwidth info.
+ */
+ if (options->V3BandwidthsFile) {
+ dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
+ } else {
+ /*
+ * No bandwidths file; clear the measured bandwidth cache in case we had
+ * one last time around.
+ */
+ if (dirserv_get_measured_bw_cache_size() > 0) {
+ dirserv_clear_measured_bw_cache();
+ }
+ }
+
/* precompute this part, since we need it to decide what "stable"
* means. */
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
@@ -2794,6 +3045,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
rep_hist_make_router_pessimal(sybil_id, now);
} DIGESTMAP_FOREACH_END;
+ /* Count how many have measured bandwidths so we know how to assign flags;
+ * this must come before dirserv_compute_performance_thresholds() */
+ dirserv_count_measured_bws(rl);
+
dirserv_compute_performance_thresholds(rl, omit_as_sybil);
routerstatuses = smartlist_new();
@@ -2838,9 +3093,18 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_free(routers);
digestmap_free(omit_as_sybil, NULL);
+ /* This pass through applies the measured bw lines to the routerstatuses */
if (options->V3BandwidthsFile) {
dirserv_read_measured_bandwidths(options->V3BandwidthsFile,
routerstatuses);
+ } else {
+ /*
+ * No bandwidths file; clear the measured bandwidth cache in case we had
+ * one last time around.
+ */
+ if (dirserv_get_measured_bw_cache_size() > 0) {
+ dirserv_clear_measured_bw_cache();
+ }
}
v3_out = tor_malloc_zero(sizeof(networkstatus_t));
@@ -3908,5 +4172,7 @@ dirserv_free_all(void)
cached_v2_networkstatus = NULL;
strmap_free(cached_consensuses, free_cached_dir_);
cached_consensuses = NULL;
+
+ dirserv_clear_measured_bw_cache();
}
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index 0caf55f830..a84ae964c9 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -76,7 +76,6 @@ int directory_fetches_from_authorities(const or_options_t *options);
int directory_fetches_dir_info_early(const or_options_t *options);
int directory_fetches_dir_info_later(const or_options_t *options);
int directory_caches_v2_dir_info(const or_options_t *options);
-#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o)
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
@@ -138,10 +137,23 @@ void cached_dir_decref(cached_dir_t *d);
cached_dir_t *new_cached_dir(char *s, time_t published);
#ifdef DIRSERV_PRIVATE
+
+/* Put the MAX_MEASUREMENT_AGE #define here so unit tests can see it */
+#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
+
int measured_bw_line_parse(measured_bw_line_t *out, const char *line);
int measured_bw_line_apply(measured_bw_line_t *parsed_line,
smartlist_t *routerstatuses);
+
+void dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
+ time_t as_of);
+void dirserv_clear_measured_bw_cache(void);
+void dirserv_expire_measured_bw_cache(time_t now);
+int dirserv_get_measured_bw_cache_size(void);
+int dirserv_query_measured_bw_cache(const char *node_id, long *bw_out,
+ time_t *as_of_out);
+int dirserv_has_measured_bw(const char *node_id);
#endif
int dirserv_read_measured_bandwidths(const char *from_file,
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index bcfe2b0698..7043cef245 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -1913,7 +1913,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
/* Fix bug 2203: Do not count BadExit nodes as Exits for bw weights */
- if (consensus_method >= 11) {
+ if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) {
is_exit = is_exit && !is_bad_exit;
}
@@ -2210,7 +2210,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
// Verify balancing parameters
if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS && added_weights) {
- networkstatus_verify_bw_weights(c);
+ networkstatus_verify_bw_weights(c, consensus_method);
}
networkstatus_vote_free(c);
}
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index fbb61b652f..8d036d6c14 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -34,6 +34,9 @@
/** 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
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index 7032b58145..a1275cf2b3 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -147,7 +147,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
return;
}
- control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0);
+ control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0);
/* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will
@@ -170,7 +170,8 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
* response; -1 if we couldn't launch the request.
*/
int
-dnsserv_launch_request(const char *name, int reverse)
+dnsserv_launch_request(const char *name, int reverse,
+ control_connection_t *control_conn)
{
entry_connection_t *entry_conn;
edge_connection_t *conn;
@@ -181,6 +182,10 @@ dnsserv_launch_request(const char *name, int reverse)
conn = ENTRY_TO_EDGE_CONN(entry_conn);
conn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
+ tor_addr_copy(&TO_CONN(conn)->addr, &control_conn->base_.addr);
+ TO_CONN(conn)->port = control_conn->base_.port;
+ TO_CONN(conn)->address = tor_dup_addr(&control_conn->base_.addr);
+
if (reverse)
entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
else
@@ -203,6 +208,8 @@ dnsserv_launch_request(const char *name, int reverse)
return -1;
}
+ control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0);
+
/* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will
* answer it immediately if it's in the cache, or completely bogus, or
diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h
index 6bdb98de70..687a77e59e 100644
--- a/src/or/dnsserv.h
+++ b/src/or/dnsserv.h
@@ -20,7 +20,8 @@ void dnsserv_resolved(entry_connection_t *conn,
const char *answer,
int ttl);
void dnsserv_reject_request(entry_connection_t *conn);
-int dnsserv_launch_request(const char *name, int is_reverse);
+int dnsserv_launch_request(const char *name, int is_reverse,
+ control_connection_t *control_conn);
#endif
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 5d356b6231..3234f4f3c7 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -24,6 +24,7 @@
#include "entrynodes.h"
#include "main.h"
#include "microdesc.h"
+#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
#include "router.h"
@@ -332,6 +333,9 @@ control_event_guard_deferred(void)
#endif
}
+/** Largest amount that we'll backdate chosen_on_date */
+#define CHOSEN_ON_DATE_SLOP (30*86400)
+
/** Add a new (preferably stable and fast) router to our
* entry_guards list. Return a pointer to the router if we succeed,
* or NULL if we can't find any more suitable entries.
@@ -367,13 +371,22 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
} else {
const routerstatus_t *rs;
rs = router_pick_directory_server(MICRODESC_DIRINFO|V3_DIRINFO,
- PDS_PREFER_TUNNELED_DIR_CONNS_);
+ PDS_PREFER_TUNNELED_DIR_CONNS_|PDS_FOR_GUARD);
if (!rs)
return NULL;
node = node_get_by_id(rs->identity_digest);
if (!node)
return NULL;
}
+ if (node->using_as_guard)
+ return NULL;
+ if (entry_guard_get_by_id_digest(node->identity) != NULL) {
+ log_info(LD_CIRC, "I was about to add a duplicate entry guard.");
+ /* This can happen if we choose a guard, then the node goes away, then
+ * comes back. */
+ ((node_t*) node)->using_as_guard = 1;
+ return NULL;
+ }
entry = tor_malloc_zero(sizeof(entry_guard_t));
log_info(LD_CIRC, "Chose %s as new entry guard.",
node_describe(node));
@@ -391,6 +404,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
* this guard. For details, see the Jan 2010 or-dev thread. */
entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30);
entry->chosen_by_version = tor_strdup(VERSION);
+ ((node_t*)node)->using_as_guard = 1;
if (prepend)
smartlist_insert(entry_guards, 0, entry);
else
@@ -435,6 +449,32 @@ entry_guard_free(entry_guard_t *e)
tor_free(e);
}
+/**
+ * Return the minimum lifetime of working entry guard, in seconds,
+ * as given in the consensus networkstatus. (Plus CHOSEN_ON_DATE_SLOP,
+ * so that we can do the chosen_on_date randomization while achieving the
+ * desired minimum lifetime.)
+ */
+static int32_t
+guards_get_lifetime(void)
+{
+ const or_options_t *options = get_options();
+#define DFLT_GUARD_LIFETIME (86400 * 60) /* Two months. */
+#define MIN_GUARD_LIFETIME (86400 * 30) /* One months. */
+#define MAX_GUARD_LIFETIME (86400 * 1826) /* Five years. */
+
+ if (options->GuardLifetime >= 1) {
+ return CLAMP(MIN_GUARD_LIFETIME,
+ options->GuardLifetime,
+ MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
+ }
+
+ return networkstatus_get_param(NULL, "GuardLifetime",
+ DFLT_GUARD_LIFETIME,
+ MIN_GUARD_LIFETIME,
+ MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
+}
+
/** Remove any entry guard which was selected by an unknown version of Tor,
* or which was selected by a version of Tor that's known to select
* entry guards badly, or which was selected more 2 months ago. */
@@ -444,6 +484,7 @@ static int
remove_obsolete_entry_guards(time_t now)
{
int changed = 0, i;
+ int32_t guard_lifetime = guards_get_lifetime();
for (i = 0; i < smartlist_len(entry_guards); ++i) {
entry_guard_t *entry = smartlist_get(entry_guards, i);
@@ -474,8 +515,8 @@ remove_obsolete_entry_guards(time_t now)
}
tor_free(tor_ver);
}
- if (!version_is_bad && entry->chosen_on_date + 3600*24*60 < now) {
- /* It's been 2 months since the date listed in our state file. */
+ if (!version_is_bad && entry->chosen_on_date + guard_lifetime < now) {
+ /* It's been too long since the date listed in our state file. */
msg = "was selected several months ago";
date_is_bad = 1;
}
@@ -730,6 +771,21 @@ entry_nodes_should_be_added(void)
should_add_entry_nodes = 1;
}
+/** Update the using_as_guard fields of all the nodes. We do this after we
+ * remove entry guards from the list: This is the only function that clears
+ * the using_as_guard field. */
+static void
+update_node_guard_status(void)
+{
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node, node->using_as_guard = 0);
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
+ node_t *node = node_get_mutable_by_id(entry->identity);
+ if (node)
+ node->using_as_guard = 1;
+ } SMARTLIST_FOREACH_END(entry);
+}
+
/** 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
@@ -814,6 +870,8 @@ entry_guards_set_from_config(const or_options_t *options)
SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
entry_guard_free(e));
+ update_node_guard_status();
+
smartlist_free(entry_nodes);
smartlist_free(worse_entry_nodes);
smartlist_free(entry_fps);
@@ -1153,6 +1211,21 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
continue;
}
+ if (use_cnt < success_cnt) {
+ int severity = LOG_INFO;
+ /* If this state file was written by a Tor that would have
+ * already fixed it, then the overcounting bug is still there.. */
+ if (tor_version_as_new_as(state_version, "0.2.4.12-alpha")) {
+ severity = LOG_NOTICE;
+ }
+ log_fn(severity, LD_BUG,
+ "State file contains unexpectedly high usage success "
+ "counts %lf/%lf for Guard %s ($%s)",
+ success_cnt, use_cnt,
+ node->nickname, hex_str(node->identity, DIGEST_LEN));
+ success_cnt = use_cnt;
+ }
+
node->use_attempts = use_cnt;
node->use_successes = success_cnt;
@@ -1203,6 +1276,21 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
unusable = 0;
}
+ if (hop_cnt < success_cnt) {
+ int severity = LOG_INFO;
+ /* If this state file was written by a Tor that would have
+ * already fixed it, then the overcounting bug is still there.. */
+ if (tor_version_as_new_as(state_version, "0.2.4.12-alpha")) {
+ severity = LOG_NOTICE;
+ }
+ log_fn(severity, LD_BUG,
+ "State file contains unexpectedly high success counts "
+ "%lf/%lf for Guard %s ($%s)",
+ success_cnt, hop_cnt,
+ node->nickname, hex_str(node->identity, DIGEST_LEN));
+ success_cnt = hop_cnt;
+ }
+
node->circ_attempts = hop_cnt;
node->circ_successes = success_cnt;
@@ -1269,6 +1357,8 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
* few lines, so we don't have to re-dirty it */
if (remove_obsolete_entry_guards(now))
entry_guards_dirty = 1;
+
+ update_node_guard_status();
}
digestmap_free(added_by, tor_free_);
return *msg ? -1 : 0;
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 36af4d8f83..a412571331 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -506,10 +506,6 @@ accounting_run_housekeeping(time_t now)
}
}
-/** When we have no idea how fast we are, how long do we assume it will take
- * us to exhaust our bandwidth? */
-#define GUESS_TIME_TO_USE_BANDWIDTH (24*60*60)
-
/** Based on our interval and our estimated bandwidth, choose a
* deterministic (but random-ish) time to wake up. */
static void
diff --git a/src/or/main.c b/src/or/main.c
index b5d1e2da34..fd8b6cf674 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -158,10 +158,6 @@ int can_complete_circuit=0;
/** How long do we let a directory connection stall before expiring it? */
#define DIR_CONN_MAX_STALL (5*60)
-/** How long do we let OR connections handshake before we decide that
- * they are obsolete? */
-#define TLS_HANDSHAKE_TIMEOUT (60)
-
/** Decides our behavior when no logs are configured/before any
* logs have been configured. For 0, we log notice to stdout as normal.
* For 1, we log warnings only. For 2, we log nothing.
@@ -1129,7 +1125,7 @@ signewnym_impl(time_t now)
return;
}
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
addressmap_clear_transient();
rend_client_purge_state();
time_of_last_signewnym = now;
@@ -1848,7 +1844,7 @@ do_hup(void)
/* Rotate away from the old dirty circuits. This has to be done
* after we've read the new options, but before we start using
* circuits for directory fetches. */
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
/* retry appropriate downloads */
router_reset_status_download_failures();
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index ac48930faf..d9955c7b49 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -71,7 +71,7 @@ HT_GENERATE(microdesc_map, microdesc_t, node,
* *<b>annotation_len_out</b> to the number of bytes written as
* annotations. */
static ssize_t
-dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out)
+dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
{
ssize_t r = 0;
size_t written;
@@ -81,10 +81,10 @@ dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out)
char annotation[ISO_TIME_LEN+32];
format_iso_time(buf, md->last_listed);
tor_snprintf(annotation, sizeof(annotation), "@last-listed %s\n", buf);
- if (fputs(annotation, f) < 0) {
+ if (write_all(fd, annotation, strlen(annotation), 0) < 0) {
log_warn(LD_DIR,
"Couldn't write microdescriptor annotation: %s",
- strerror(ferror(f)));
+ strerror(errno));
return -1;
}
r += strlen(annotation);
@@ -93,13 +93,13 @@ dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out)
*annotation_len_out = 0;
}
- md->off = (off_t) ftell(f);
- written = fwrite(md->body, 1, md->bodylen, f);
+ md->off = tor_fd_getpos(fd);
+ written = write_all(fd, md->body, md->bodylen, 0);
if (written != md->bodylen) {
log_warn(LD_DIR,
"Couldn't dump microdescriptor (wrote %lu out of %lu): %s",
(unsigned long)written, (unsigned long)md->bodylen,
- strerror(ferror(f)));
+ strerror(errno));
return -1;
}
r += md->bodylen;
@@ -198,15 +198,15 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
{
smartlist_t *added;
open_file_t *open_file = NULL;
- FILE *f = NULL;
+ int fd = -1;
// int n_added = 0;
ssize_t size = 0;
if (where == SAVED_NOWHERE && !no_save) {
- f = start_writing_to_stdio_file(cache->journal_fname,
- OPEN_FLAGS_APPEND|O_BINARY,
- 0600, &open_file);
- if (!f) {
+ fd = start_writing_to_file(cache->journal_fname,
+ OPEN_FLAGS_APPEND|O_BINARY,
+ 0600, &open_file);
+ if (fd < 0) {
log_warn(LD_DIR, "Couldn't append to journal in %s: %s",
cache->journal_fname, strerror(errno));
return NULL;
@@ -228,9 +228,9 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
}
/* Okay, it's a new one. */
- if (f) {
+ if (fd >= 0) {
size_t annotation_len;
- size = dump_microdescriptor(f, md, &annotation_len);
+ size = dump_microdescriptor(fd, md, &annotation_len);
if (size < 0) {
/* we already warned in dump_microdescriptor */
abort_writing_to_file(open_file);
@@ -252,8 +252,14 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
cache->total_len_seen += md->bodylen;
} SMARTLIST_FOREACH_END(md);
- if (f)
- finish_writing_to_file(open_file); /*XXX Check me.*/
+ if (fd >= 0) {
+ if (finish_writing_to_file(open_file) < 0) {
+ log_warn(LD_DIR, "Error appending to microdescriptor file: %s",
+ strerror(errno));
+ smartlist_clear(added);
+ return added;
+ }
+ }
{
networkstatus_t *ns = networkstatus_get_latest_consensus();
@@ -406,11 +412,11 @@ int
microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
{
open_file_t *open_file;
- FILE *f;
+ int fd = -1;
microdesc_t **mdp;
smartlist_t *wrote;
ssize_t size;
- off_t off = 0;
+ off_t off = 0, off_real;
int orig_size, new_size;
if (cache == NULL) {
@@ -430,10 +436,10 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
orig_size = (int)(cache->cache_content ? cache->cache_content->size : 0);
orig_size += (int)cache->journal_len;
- f = start_writing_to_stdio_file(cache->cache_fname,
- OPEN_FLAGS_REPLACE|O_BINARY,
- 0600, &open_file);
- if (!f)
+ fd = start_writing_to_file(cache->cache_fname,
+ OPEN_FLAGS_REPLACE|O_BINARY,
+ 0600, &open_file);
+ if (fd < 0)
return -1;
wrote = smartlist_new();
@@ -444,7 +450,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
if (md->no_save)
continue;
- size = dump_microdescriptor(f, md, &annotation_len);
+ size = dump_microdescriptor(fd, md, &annotation_len);
if (size < 0) {
/* XXX handle errors from dump_microdescriptor() */
/* log? return -1? die? coredump the universe? */
@@ -453,6 +459,14 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
tor_assert(((size_t)size) == annotation_len + md->bodylen);
md->off = off + annotation_len;
off += size;
+ off_real = tor_fd_getpos(fd);
+ if (off_real != off) {
+ log_warn(LD_BUG, "Discontinuity in position in microdescriptor cache."
+ "By my count, I'm at "I64_FORMAT
+ ", but I should be at "I64_FORMAT,
+ I64_PRINTF_ARG(off), I64_PRINTF_ARG(off_real));
+ off = off_real;
+ }
if (md->saved_location != SAVED_IN_CACHE) {
tor_free(md->body);
md->saved_location = SAVED_IN_CACHE;
@@ -460,11 +474,15 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
smartlist_add(wrote, md);
}
+ if (finish_writing_to_file(open_file) < 0) {
+ log_warn(LD_DIR, "Error rebuilding microdescriptor cache: %s",
+ strerror(errno));
+ return -1;
+ }
+
if (cache->cache_content)
tor_munmap_file(cache->cache_content);
- finish_writing_to_file(open_file); /*XXX Check me.*/
-
cache->cache_content = tor_mmap_file(cache->cache_fname);
if (!cache->cache_content && smartlist_len(wrote)) {
@@ -532,7 +550,7 @@ microdesc_check_counts(void)
/** Deallocate a single microdescriptor. Note: the microdescriptor MUST have
* previously been removed from the cache if it had ever been inserted. */
void
-microdesc_free(microdesc_t *md)
+microdesc_free_(microdesc_t *md, const char *fname, int lineno)
{
if (!md)
return;
@@ -543,12 +561,12 @@ microdesc_free(microdesc_t *md)
microdesc_cache_t *cache = get_microdesc_cache();
microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md);
if (md2 == md) {
- log_warn(LD_BUG, "microdesc_free() called, but md was still in "
- "microdesc_map");
+ log_warn(LD_BUG, "microdesc_free() called from %s:%d, but md was still "
+ "in microdesc_map", fname, lineno);
HT_REMOVE(microdesc_map, &cache->map, md);
} else {
- log_warn(LD_BUG, "microdesc_free() called with held_in_map set, but "
- "microdesc was not in the map.");
+ log_warn(LD_BUG, "microdesc_free() called from %s:%d with held_in_map "
+ "set, but microdesc was not in the map.", fname, lineno);
}
tor_fragile_assert();
}
@@ -562,11 +580,13 @@ microdesc_free(microdesc_t *md)
}
});
if (found) {
- log_warn(LD_BUG, "microdesc_free() called, but md was still referenced "
- "%d node(s); held_by_nodes == %u", found, md->held_by_nodes);
+ log_warn(LD_BUG, "microdesc_free() called from %s:%d, but md was still "
+ "referenced %d node(s); held_by_nodes == %u",
+ fname, lineno, found, md->held_by_nodes);
} else {
- log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set to %u, "
- "but md was not referenced by any nodes", md->held_by_nodes);
+ log_warn(LD_BUG, "microdesc_free() called from %s:%d with held_by_nodes "
+ "set to %u, but md was not referenced by any nodes",
+ fname, lineno, md->held_by_nodes);
}
tor_fragile_assert();
}
diff --git a/src/or/microdesc.h b/src/or/microdesc.h
index 4e58aa33f0..7adb8c68af 100644
--- a/src/or/microdesc.h
+++ b/src/or/microdesc.h
@@ -39,7 +39,9 @@ smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns,
int downloadable_only,
digestmap_t *skip);
-void microdesc_free(microdesc_t *md);
+void microdesc_free_(microdesc_t *md, const char *fname, int line);
+#define microdesc_free(md) \
+ microdesc_free_((md), __FILE__, __LINE__)
void microdesc_free_all(void);
void update_microdesc_downloads(time_t now);
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index c63c76fccd..8846cd0634 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1432,18 +1432,6 @@ consensus_is_waiting_for_certs(void)
? 1 : 0;
}
-/** Return the network status with a given identity digest. */
-networkstatus_v2_t *
-networkstatus_v2_get_by_digest(const char *digest)
-{
- SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
- {
- if (tor_memeq(ns->identity_digest, digest, DIGEST_LEN))
- return ns;
- });
- return NULL;
-}
-
/** Return the most recent consensus that we have downloaded, or NULL if we
* don't have one. */
networkstatus_t *
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index b64e4b8e1a..761f8e7f0e 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -75,7 +75,6 @@ void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
int client_would_use_router(const routerstatus_t *rs, time_t now,
const or_options_t *options);
-networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_t *networkstatus_get_latest_consensus(void);
networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
consensus_flavor_t f);
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index ee1bc392e3..178f084b69 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -688,6 +688,24 @@ node_exit_policy_rejects_all(const node_t *node)
return 1;
}
+/** Return true iff the exit policy for <b>node</b> is such that we can treat
+ * rejecting an address of type <b>family</b> unexpectedly as a sign of that
+ * node's failure. */
+int
+node_exit_policy_is_exact(const node_t *node, sa_family_t family)
+{
+ if (family == AF_UNSPEC) {
+ return 1; /* Rejecting an address but not telling us what address
+ * is a bad sign. */
+ } else if (family == AF_INET) {
+ return node->ri != NULL;
+ } else if (family == AF_INET6) {
+ return 0;
+ }
+ tor_fragile_assert();
+ return 1;
+}
+
/** Return list of tor_addr_port_t with all OR ports (in the sense IP
* addr + TCP port) for <b>node</b>. Caller must free all elements
* using tor_free() and free the list using smartlist_free().
@@ -1400,7 +1418,7 @@ get_frac_paths_needed_for_circs(const or_options_t *options,
const networkstatus_t *ns)
{
#define DFLT_PCT_USABLE_NEEDED 60
- if (options->PathsNeededToBuildCircuits >= 1.0) {
+ if (options->PathsNeededToBuildCircuits >= 0.0) {
return options->PathsNeededToBuildCircuits;
} else {
return networkstatus_get_param(ns, "min_paths_for_circs_pct",
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 65cf0d0284..8a4665a8bf 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -41,6 +41,7 @@ int node_get_purpose(const node_t *node);
(node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
int node_is_me(const node_t *node);
int node_exit_policy_rejects_all(const node_t *node);
+int node_exit_policy_is_exact(const node_t *node, sa_family_t family);
smartlist_t *node_get_all_orports(const node_t *node);
int node_allows_single_hop_exits(const node_t *node);
const char *node_get_nickname(const node_t *node);
diff --git a/src/or/or.h b/src/or/or.h
index c7d259853b..4e19140b4b 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1417,8 +1417,8 @@ typedef struct or_connection_t {
unsigned int is_outgoing:1;
unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
unsigned int wide_circ_ids:1;
- uint8_t link_proto; /**< What protocol version are we using? 0 for
- * "none negotiated yet." */
+ uint16_t link_proto; /**< What protocol version are we using? 0 for
+ * "none negotiated yet." */
or_handshake_state_t *handshake_state; /**< If we are setting this connection
* up, state information to do so. */
@@ -2249,6 +2249,9 @@ typedef struct node_t {
/** Local info: we treat this node as if it rejects everything */
unsigned int rejects_all:1;
+ /** Local info: this node is in our list of guards */
+ unsigned int using_as_guard:1;
+
/* Local info: derived. */
/** True if the IPv6 OR port is preferred over the IPv4 OR port. */
@@ -2942,6 +2945,10 @@ typedef struct origin_circuit_t {
*/
ENUM_BF(path_state_t) path_state : 3;
+ /* If this flag is set, we should not consider attaching any more
+ * connections to this circuit. */
+ unsigned int unusable_for_new_conns : 1;
+
/**
* Tristate variable to guard against pathbias miscounting
* due to circuit purpose transitions changing the decision
@@ -3059,6 +3066,10 @@ typedef struct origin_circuit_t {
* ISO_STREAM. */
uint64_t associated_isolated_stream_global_id;
/**@}*/
+ /** A list of addr_policy_t for this circuit in particular. Used by
+ * adjust_exit_policy_from_exitpolicy_failure.
+ */
+ smartlist_t *prepend_policy;
} origin_circuit_t;
struct onion_queue_t;
@@ -3868,6 +3879,10 @@ typedef struct {
* consensus vote on the 'params' line. */
char *ConsensusParams;
+ /** Authority only: minimum number of measured bandwidths we must see
+ * before we only beliee measured bandwidths to assign flags. */
+ int MinMeasuredBWsForAuthToIgnoreAdvertised;
+
/** The length of time that we think an initial consensus should be fresh.
* Only altered on testing networks. */
int TestingV3AuthInitialVotingInterval;
@@ -3895,6 +3910,12 @@ typedef struct {
* of certain configuration options. */
int TestingTorNetwork;
+ /** Minimum value for the Exit flag threshold on testing networks. */
+ uint64_t TestingMinExitFlagThreshold;
+
+ /** Minimum value for the Fast flag threshold on testing networks. */
+ uint64_t TestingMinFastFlagThreshold;
+
/** If true, and we have GeoIP data, and we're a bridge, keep a per-country
* count of how many client addresses have contacted us so that we can help
* the bridge authority guess which countries have blocked access to us. */
@@ -4012,6 +4033,8 @@ typedef struct {
* should guess a suitable value. */
int SSLKeyLifetime;
+ /** How long (seconds) do we keep a guard before picking a new one? */
+ int GuardLifetime;
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
@@ -4465,15 +4488,6 @@ typedef struct vote_timing_t {
/********************************* geoip.c **************************/
-/** Round all GeoIP results to the next multiple of this value, to avoid
- * leaking information. */
-#define DIR_RECORD_USAGE_GRANULARITY 8
-/** Time interval: Flush geoip data to disk this often. */
-#define DIR_ENTRY_RECORD_USAGE_RETAIN_IPS (24*60*60)
-/** How long do we have to have observed per-country request history before
- * we are willing to talk about it? */
-#define DIR_RECORD_USAGE_MIN_OBSERVATION_TIME (12*60*60)
-
/** Indicates an action that we might be noting geoip statistics on.
* Note that if we're noticing CONNECT, we're a bridge, and if we're noticing
* the others, we're not.
@@ -4793,6 +4807,10 @@ typedef struct dir_server_t {
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
+/** This node is to be chosen as a directory guard, so don't choose any
+ * node that's currently a guard. */
+#define PDS_FOR_GUARD (1<<5)
+
#define PDS_PREFER_TUNNELED_DIR_CONNS_ (1<<16)
/** Possible ways to weight routers when choosing one randomly. See
diff --git a/src/or/policies.c b/src/or/policies.c
index 9696b8123b..be4da55061 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -837,6 +837,24 @@ append_exit_policy_string(smartlist_t **policy, const char *more)
}
}
+/** Add "reject <b>addr</b>:*" to <b>dest</b>, creating the list as needed. */
+void
+addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *addr)
+{
+ addr_policy_t p, *add;
+ memset(&p, 0, sizeof(p));
+ p.policy_type = ADDR_POLICY_REJECT;
+ p.maskbits = tor_addr_family(addr) == AF_INET6 ? 128 : 32;
+ tor_addr_copy(&p.addr, addr);
+ p.prt_min = 1;
+ p.prt_max = 65535;
+
+ add = addr_policy_get_canonical_entry(&p);
+ if (!*dest)
+ *dest = smartlist_new();
+ smartlist_add(*dest, add);
+}
+
/** Detect and excise "dead code" from the policy *<b>dest</b>. */
static void
exit_policy_remove_redundancies(smartlist_t *dest)
diff --git a/src/or/policies.h b/src/or/policies.h
index da375c4425..c0e7a9efce 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -47,6 +47,8 @@ int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int rejectprivate, const char *local_address,
int add_default_policy);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
+void addr_policy_append_reject_addr(smartlist_t **dest,
+ const tor_addr_t *addr);
void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
int exit_policy_is_general_exit(smartlist_t *policy);
int policy_is_reject_star(const smartlist_t *policy, sa_family_t family);
diff --git a/src/or/relay.c b/src/or/relay.c
index 9ff9e1e1f4..0ca3e56fd5 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -17,6 +17,7 @@
#include "channel.h"
#include "circuitbuild.h"
#include "circuitlist.h"
+#include "circuituse.h"
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
@@ -53,6 +54,10 @@ static int circuit_resume_edge_reading_helper(edge_connection_t *conn,
static int circuit_consider_stop_edge_reading(circuit_t *circ,
crypt_path_t *layer_hint);
static int circuit_queue_streams_are_blocked(circuit_t *circ);
+static void adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ,
+ entry_connection_t *conn,
+ node_t *node,
+ const tor_addr_t *addr);
/** Stop reading on edge connections when we have this many cells
* waiting on the appropriate queue. */
@@ -710,7 +715,6 @@ connection_ap_process_end_not_open(
relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
entry_connection_t *conn, crypt_path_t *layer_hint)
{
- struct in_addr in;
node_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE);
int control_reason;
@@ -753,10 +757,10 @@ connection_ap_process_end_not_open(
stream_end_reason_to_string(reason));
exitrouter = node_get_mutable_by_id(chosen_exit_digest);
switch (reason) {
- case END_STREAM_REASON_EXITPOLICY:
+ case END_STREAM_REASON_EXITPOLICY: {
+ tor_addr_t addr;
+ tor_addr_make_unspec(&addr);
if (rh->length >= 5) {
- tor_addr_t addr;
-
int ttl = -1;
tor_addr_make_unspec(&addr);
if (rh->length == 5 || rh->length == 9) {
@@ -808,16 +812,11 @@ connection_ap_process_end_not_open(
}
}
/* check if he *ought* to have allowed it */
- if (exitrouter &&
- (rh->length < 5 ||
- (tor_inet_aton(conn->socks_request->address, &in) &&
- !conn->chosen_exit_name))) {
- log_info(LD_APP,
- "Exitrouter %s seems to be more restrictive than its exit "
- "policy. Not using this router as exit for now.",
- node_describe(exitrouter));
- policies_set_node_exitpolicy_to_reject_all(exitrouter);
- }
+
+ adjust_exit_policy_from_exitpolicy_failure(circ,
+ conn,
+ exitrouter,
+ &addr);
if (conn->chosen_exit_optional ||
conn->chosen_exit_retries) {
@@ -837,6 +836,7 @@ connection_ap_process_end_not_open(
return 0;
/* else, conn will get closed below */
break;
+ }
case END_STREAM_REASON_CONNECTREFUSED:
if (!conn->chosen_exit_optional)
break; /* break means it'll close, below */
@@ -851,9 +851,7 @@ connection_ap_process_end_not_open(
/* We haven't retried too many times; reattach the connection. */
circuit_log_path(LOG_INFO,LD_APP,circ);
/* Mark this circuit "unusable for new streams". */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->base_.timestamp_dirty);
- circ->base_.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ mark_circuit_unusable_for_new_conns(circ);
if (conn->chosen_exit_optional) {
/* stop wanting a specific exit */
@@ -901,6 +899,47 @@ connection_ap_process_end_not_open(
return 0;
}
+/** Called when we have gotten an END_REASON_EXITPOLICY failure on <b>circ</b>
+ * for <b>conn</b>, while attempting to connect via <b>node</b>. If the node
+ * told us which address it rejected, then <b>addr</b> is that address;
+ * otherwise it is AF_UNSPEC.
+ *
+ * If we are sure the node should have allowed this address, mark the node as
+ * having a reject *:* exit policy. Otherwise, mark the circuit as unusable
+ * for this particular address.
+ **/
+static void
+adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ,
+ entry_connection_t *conn,
+ node_t *node,
+ const tor_addr_t *addr)
+{
+ int make_reject_all = 0;
+ const sa_family_t family = tor_addr_family(addr);
+
+ if (node) {
+ tor_addr_t tmp;
+ int asked_for_family = tor_addr_parse(&tmp, conn->socks_request->address);
+ if (family == AF_UNSPEC) {
+ make_reject_all = 1;
+ } else if (node_exit_policy_is_exact(node, family) &&
+ asked_for_family != -1 && !conn->chosen_exit_name) {
+ make_reject_all = 1;
+ }
+
+ if (make_reject_all) {
+ log_info(LD_APP,
+ "Exitrouter %s seems to be more restrictive than its exit "
+ "policy. Not using this router as exit for now.",
+ node_describe(node));
+ policies_set_node_exitpolicy_to_reject_all(node);
+ }
+ }
+
+ if (family != AF_UNSPEC)
+ addr_policy_append_reject_addr(&circ->prepend_policy, addr);
+}
+
/** Helper: change the socks_request-&gt;address field on conn to the
* dotted-quad representation of <b>new_addr</b>,
* and send an appropriate REMAP event. */
@@ -1101,12 +1140,15 @@ connection_edge_process_relay_cell_not_open(
2+answer_len));
else
ttl = -1;
- if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
- uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
- if (get_options()->ClientDNSRejectInternalAddresses &&
- is_internal_IP(addr, 0)) {
+ if (answer_type == RESOLVED_TYPE_IPV4 ||
+ answer_type == RESOLVED_TYPE_IPV6) {
+ tor_addr_t addr;
+ if (decode_address_from_payload(&addr, cell->payload+RELAY_HEADER_SIZE,
+ rh->length) &&
+ tor_addr_is_internal(&addr, 0) &&
+ get_options()->ClientDNSRejectInternalAddresses) {
log_info(LD_APP,"Got a resolve with answer %s. Rejecting.",
- fmt_addr32(addr));
+ fmt_addr(&addr));
connection_ap_handshake_socks_resolved(entry_conn,
RESOLVED_TYPE_ERROR_TRANSIENT,
0, NULL, 0, TIME_MAX);
@@ -1398,6 +1440,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
"'truncate' unsupported at origin. Dropping.");
return 0;
}
+ if (circ->n_hop) {
+ if (circ->n_chan)
+ log_warn(LD_BUG, "n_chan and n_hop set on the same circuit!");
+ extend_info_free(circ->n_hop);
+ circ->n_hop = NULL;
+ tor_free(circ->n_chan_create_cell);
+ circuit_set_state(circ, CIRCUIT_STATE_OPEN);
+ }
if (circ->n_chan) {
uint8_t trunc_reason = get_uint8(cell->payload + RELAY_HEADER_SIZE);
circuit_clear_cell_queue(circ, circ->n_chan);
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 79c1a724e4..2cfc364c3b 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -1452,13 +1452,6 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
command);
}
-/** Return the number of entries in our rendezvous descriptor cache. */
-int
-rend_cache_size(void)
-{
- return strmap_size(rend_cache);
-}
-
/** Allocate and return a new rend_data_t with the same
* contents as <b>query</b>. */
rend_data_t *
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index 189891b747..f476593d2b 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -49,7 +49,6 @@ int rend_cache_store(const char *desc, size_t desc_len, int published,
int rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query);
int rend_cache_store_v2_desc_as_dir(const char *desc);
-int rend_cache_size(void);
int rend_encode_v2_descriptors(smartlist_t *descs_out,
rend_service_descriptor_t *desc, time_t now,
uint8_t period, rend_auth_type_t auth_type,
diff --git a/src/or/router.c b/src/or/router.c
index 422fe5db2e..c8c9ce1a4f 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -2983,23 +2983,6 @@ router_get_verbose_nickname(char *buf, const routerinfo_t *router)
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}
-/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
- * verbose representation of the identity of <b>router</b>. The format is:
- * A dollar sign.
- * The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
- * A "=" if the router is named; a "~" if it is not.
- * The router's nickname.
- **/
-void
-routerstatus_get_verbose_nickname(char *buf, const routerstatus_t *router)
-{
- buf[0] = '$';
- base16_encode(buf+1, HEX_DIGEST_LEN+1, router->identity_digest,
- DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
- strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
-}
-
/** Forget that we have issued any router-related warnings, so that we'll
* warn again if we see the same errors. */
void
diff --git a/src/or/router.h b/src/or/router.h
index fd2076af01..96749b53c0 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -132,8 +132,6 @@ const char *routerstatus_describe(const routerstatus_t *ri);
const char *extend_info_describe(const extend_info_t *ei);
void router_get_verbose_nickname(char *buf, const routerinfo_t *router);
-void routerstatus_get_verbose_nickname(char *buf,
- const routerstatus_t *router);
void router_reset_warnings(void);
void router_reset_reachability(void);
void router_free_all(void);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 2f08167f18..0c978e9d00 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -54,8 +54,6 @@ static const routerstatus_t *router_pick_dirserver_generic(
smartlist_t *sourcelist,
dirinfo_type_t type, int flags);
static void mark_all_dirservers_up(smartlist_t *server_list);
-static int router_nickname_matches(const routerinfo_t *router,
- const char *nickname);
static void dir_server_free(dir_server_t *ds);
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static const char *signed_descriptor_get_body_impl(
@@ -339,7 +337,6 @@ trusted_dirs_remove_old_certs(void)
time_t now = time(NULL);
#define DEAD_CERT_LIFETIME (2*24*60*60)
#define OLD_CERT_LIFETIME (7*24*60*60)
-#define CERT_EXPIRY_SKEW (60*60)
if (!trusted_dir_certs)
return;
@@ -1153,6 +1150,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
int requireother = ! (flags & PDS_ALLOW_SELF);
int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
int prefer_tunnel = (flags & PDS_PREFER_TUNNELED_DIR_CONNS_);
+ int for_guard = (flags & PDS_FOR_GUARD);
int try_excluding = 1, n_excluded = 0;
if (!consensus)
@@ -1192,6 +1190,8 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
if ((type & MICRODESC_DIRINFO) && !is_trusted &&
!node->rs->version_supports_microdesc_cache)
continue;
+ if (for_guard && node->using_as_guard)
+ continue; /* Don't make the same node a guard twice. */
if (try_excluding &&
routerset_contains_routerstatus(options->ExcludeNodes, status,
country)) {
@@ -1462,30 +1462,6 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
nodelist_add_node_and_family(sl, node);
}
-/** Return 1 iff any member of the (possibly NULL) comma-separated list
- * <b>list</b> is an acceptable nickname or hexdigest for <b>router</b>. Else
- * return 0.
- */
-int
-router_nickname_is_in_list(const routerinfo_t *router, const char *list)
-{
- smartlist_t *nickname_list;
- int v = 0;
-
- if (!list)
- return 0; /* definitely not */
- tor_assert(router);
-
- nickname_list = smartlist_new();
- smartlist_split_string(nickname_list, list, ",",
- SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH(nickname_list, const char *, cp,
- if (router_nickname_matches(router, cp)) {v=1;break;});
- SMARTLIST_FOREACH(nickname_list, char *, cp, tor_free(cp));
- smartlist_free(nickname_list);
- return v;
-}
-
/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
@@ -2312,18 +2288,6 @@ router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest)
router_is_named(router));
}
-/** Return true if <b>router</b>'s nickname matches <b>nickname</b>
- * (case-insensitive), or if <b>router's</b> identity key digest
- * matches a hexadecimal value stored in <b>nickname</b>. Return
- * false otherwise. */
-static int
-router_nickname_matches(const routerinfo_t *router, const char *nickname)
-{
- if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname))
- return 1;
- return router_hex_digest_matches(router, nickname);
-}
-
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero, any authority is okay. */
@@ -4052,17 +4016,6 @@ clear_dir_servers(void)
router_dir_info_changed();
}
-/** Return 1 if any trusted dir server supports v1 directories,
- * else return 0. */
-int
-any_trusted_dir_is_v1_authority(void)
-{
- if (trusted_dir_servers)
- return get_n_authorities(V1_DIRINFO) > 0;
-
- return 0;
-}
-
/** For every current directory connection whose purpose is <b>purpose</b>,
* and where the resource being downloaded begins with <b>prefix</b>, split
* rest of the resource into base16 fingerprints (or base64 fingerprints if
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 1849fff31c..28b2f58935 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -42,7 +42,6 @@ int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
-int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
const routerinfo_t *routerlist_find_my_routerinfo(void);
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
@@ -146,7 +145,6 @@ void dir_server_add(dir_server_t *ent);
void authority_cert_free(authority_cert_t *cert);
void clear_dir_servers(void);
-int any_trusted_dir_is_v1_authority(void);
void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus);
void update_router_descriptor_downloads(time_t now);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index ce2cd5c513..f8edb8407c 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1953,7 +1953,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_supports_optimistic_data =
tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
rs->version_supports_extend2_cells =
- tor_version_as_new_as(tok->args[0], "0.2.4.7-alpha");
+ tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);
@@ -2030,7 +2030,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
}
} else {
log_info(LD_BUG, "Found an entry in networkstatus with no "
- "microdescriptor digest. (Router %s=%s at %s:%d.)",
+ "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN),
fmt_addr32(rs->addr), rs->or_port);
}
@@ -2257,7 +2257,7 @@ networkstatus_v2_parse_from_string(const char *s)
/** Verify the bandwidth weights of a network status document */
int
-networkstatus_verify_bw_weights(networkstatus_t *ns)
+networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
{
int64_t weight_scale;
int64_t G=0, M=0, E=0, D=0, T=0;
@@ -2343,14 +2343,21 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// 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;
+ }
if (rs->has_bandwidth) {
T += rs->bandwidth;
- if (rs->is_exit && rs->is_possible_guard) {
+ if (is_exit && rs->is_possible_guard) {
D += rs->bandwidth;
Gtotal += Wgd*rs->bandwidth;
Mtotal += Wmd*rs->bandwidth;
Etotal += Wed*rs->bandwidth;
- } else if (rs->is_exit) {
+ } else if (is_exit) {
E += rs->bandwidth;
Mtotal += Wme*rs->bandwidth;
Etotal += Wee*rs->bandwidth;
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index 859a691e2a..7bf7d79073 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -54,7 +54,7 @@ void dump_distinct_digest_count(int severity);
int compare_routerstatus_entries(const void **_a, const void **_b);
int compare_vote_routerstatus_entries(const void **_a, const void **_b);
networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s);
-int networkstatus_verify_bw_weights(networkstatus_t *ns);
+int networkstatus_verify_bw_weights(networkstatus_t *ns, int);
networkstatus_t *networkstatus_parse_vote_from_string(const char *s,
const char **eos_out,
networkstatus_type_t ns_type);
diff --git a/src/or/status.c b/src/or/status.c
index 126167dcb9..e44de635cb 100644
--- a/src/or/status.c
+++ b/src/or/status.c
@@ -85,6 +85,7 @@ log_heartbeat(time_t now)
char *bw_rcvd = NULL;
char *uptime = NULL;
const routerinfo_t *me;
+ double r = tls_get_write_overhead_ratio();
const or_options_t *options = get_options();
(void)now;
@@ -112,6 +113,11 @@ log_heartbeat(time_t now)
100*(U64_TO_DBL(stats_n_data_bytes_packaged) /
U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) );
+ if (r > 1.0) {
+ double overhead = ( r - 1.0 ) * 100.0;
+ log_notice(LD_HEARTBEAT, "TLS write overhead: %.f%%", overhead);
+ }
+
tor_free(uptime);
tor_free(bw_sent);
tor_free(bw_rcvd);
diff --git a/src/or/transports.c b/src/or/transports.c
index 945d422f34..b5a00c90ec 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -124,10 +124,6 @@ static INLINE void free_execve_args(char **arg);
#define PROTO_CMETHODS_DONE "CMETHODS DONE"
#define PROTO_SMETHODS_DONE "SMETHODS DONE"
-/** Number of environment variables for managed proxy clients/servers. */
-#define ENVIRON_SIZE_CLIENT 3
-#define ENVIRON_SIZE_SERVER 7 /* XXX known to be too high, but that's ok */
-
/** The first and only supported - at the moment - configuration
protocol version. */
#define PROTO_VERSION_ONE 1