diff options
Diffstat (limited to 'src/or')
57 files changed, 1315 insertions, 618 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/buffers.c b/src/or/buffers.c index b54584fb4a..47fa31dc07 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1781,6 +1781,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, if (req->socks_version != 5) { /* we need to negotiate a method */ unsigned char nummethods = (unsigned char)*(data+1); + int have_user_pass, have_no_auth; int r=0; tor_assert(!req->socks_version); if (datalen < 2u+nummethods) { @@ -1791,19 +1792,21 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, return -1; req->replylen = 2; /* 2 bytes of response */ req->reply[0] = 5; /* socks5 reply */ - if (memchr(data+2, SOCKS_NO_AUTH, nummethods)) { - req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth - method */ - req->socks_version = 5; /* remember we've already negotiated auth */ - log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); - r=0; - } else if (memchr(data+2, SOCKS_USER_PASS, nummethods)) { + have_user_pass = (memchr(data+2, SOCKS_USER_PASS, nummethods) !=NULL); + have_no_auth = (memchr(data+2, SOCKS_NO_AUTH, nummethods) !=NULL); + if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) { req->auth_type = SOCKS_USER_PASS; req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass" auth method */ req->socks_version = 5; /* remember we've already negotiated auth */ log_debug(LD_APP,"socks5: accepted method 2 (username/password)"); r=0; + } else if (have_no_auth) { + req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth + method */ + req->socks_version = 5; /* remember we've already negotiated auth */ + log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); + r=0; } else { log_warn(LD_APP, "socks5: offered methods don't include 'no auth' or " diff --git a/src/or/channel.c b/src/or/channel.c index f8afc405e6..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, @@ -2607,17 +2631,17 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason) cell.command = CELL_DESTROY; cell.payload[0] = (uint8_t) reason; log_debug(LD_OR, - "Sending destroy (circID %d) on channel %p " + "Sending destroy (circID %u) on channel %p " "(global ID " U64_FORMAT ")", - circ_id, chan, + (unsigned)circ_id, chan, U64_PRINTF_ARG(chan->global_identifier)); channel_write_cell(chan, &cell); } else { log_warn(LD_BUG, - "Someone called channel_send_destroy() for circID %d " + "Someone called channel_send_destroy() for circID %u " "on a channel " U64_FORMAT " at %p in state %s (%d)", - circ_id, U64_PRINTF_ARG(chan->global_identifier), + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier), chan, channel_state_to_string(chan->state), chan->state); } 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 8a3a36accb..31242f6c14 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -523,7 +523,7 @@ circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell, log_warn(LD_CIRC,"failed to get unique circID."); return -1; } - log_debug(LD_CIRC,"Chosen circID %u.", id); + log_debug(LD_CIRC,"Chosen circID %u.", (unsigned)id); circuit_set_n_circid_chan(circ, id, circ->n_chan); memset(&cell, 0, sizeof(cell_t)); @@ -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 ef32680736..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. */ @@ -780,13 +785,13 @@ circuit_dump_conn_details(int severity, circuit_t *circ, int conn_array_index, const char *type, - int this_circid, - int other_circid) + circid_t this_circid, + circid_t other_circid) { - tor_log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d " - "(other side %d), state %d (%s), born %ld:", - conn_array_index, type, this_circid, other_circid, circ->state, - circuit_state_to_string(circ->state), + tor_log(severity, LD_CIRC, "Conn %d has %s circuit: circID %u " + "(other side %u), state %d (%s), born %ld:", + conn_array_index, type, (unsigned)this_circid, (unsigned)other_circid, + circ->state, circuit_state_to_string(circ->state), (long)circ->timestamp_began.tv_sec); if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */ circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ)); @@ -843,12 +848,12 @@ circuit_dump_chan_details(int severity, circuit_t *circ, channel_t *chan, const char *type, - int this_circid, - int other_circid) + circid_t this_circid, + circid_t other_circid) { - tor_log(severity, LD_CIRC, "Conn %p has %s circuit: circID %d " - "(other side %d), state %d (%s), born %ld:", - chan, type, this_circid, other_circid, circ->state, + tor_log(severity, LD_CIRC, "Conn %p has %s circuit: circID %u " + "(other side %u), state %d (%s), born %ld:", + chan, type, (unsigned)this_circid, (unsigned)other_circid, circ->state, circuit_state_to_string(circ->state), (long)circ->timestamp_began.tv_sec); if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */ @@ -943,16 +948,16 @@ circuit_get_by_circid_channel_impl(circid_t circ_id, channel_t *chan) if (found && found->circuit) { log_debug(LD_CIRC, "circuit_get_by_circid_channel_impl() returning circuit %p for" - " circ_id %d, channel ID " U64_FORMAT " (%p)", - found->circuit, circ_id, + " circ_id %u, channel ID " U64_FORMAT " (%p)", + found->circuit, (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier), chan); return found->circuit; } log_debug(LD_CIRC, "circuit_get_by_circid_channel_impl() found nothing for" - " circ_id %d, channel ID " U64_FORMAT " (%p)", - circ_id, + " circ_id %u, channel ID " U64_FORMAT " (%p)", + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier), chan); return NULL; @@ -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/circuitmux.c b/src/or/circuitmux.c index dcc1901819..545cfd0650 100644 --- a/src/or/circuitmux.c +++ b/src/or/circuitmux.c @@ -425,9 +425,9 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux) } else { /* Complain and move on */ log_warn(LD_CIRC, - "Circuit %d/channel " U64_FORMAT " had direction == " + "Circuit %u/channel " U64_FORMAT " had direction == " "CELL_DIRECTION_IN, but isn't an or_circuit_t", - to_remove->circ_id, + (unsigned)to_remove->circ_id, U64_PRINTF_ARG(to_remove->chan_id)); } @@ -449,16 +449,16 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux) } else { /* Complain and move on */ log_warn(LD_CIRC, - "Couldn't find circuit %d (for channel " U64_FORMAT ")", - to_remove->circ_id, + "Couldn't find circuit %u (for channel " U64_FORMAT ")", + (unsigned)to_remove->circ_id, U64_PRINTF_ARG(to_remove->chan_id)); } } else { /* Complain and move on */ log_warn(LD_CIRC, - "Couldn't find channel " U64_FORMAT " (for circuit id %d)", + "Couldn't find channel " U64_FORMAT " (for circuit id %u)", U64_PRINTF_ARG(to_remove->chan_id), - to_remove->circ_id); + (unsigned)to_remove->circ_id); } /* Assert that we don't have un-freed policy data for this circuit */ @@ -905,7 +905,7 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ, log_info(LD_CIRC, "Circuit %u on channel " U64_FORMAT " was already attached to " "cmux %p (trying to attach to %p)", - circ_id, U64_PRINTF_ARG(channel_id), + (unsigned)circ_id, U64_PRINTF_ARG(channel_id), ((direction == CELL_DIRECTION_OUT) ? circ->n_mux : TO_OR_CIRCUIT(circ)->p_mux), cmux); @@ -938,7 +938,7 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ, */ log_debug(LD_CIRC, "Attaching circuit %u on channel " U64_FORMAT " to cmux %p", - circ_id, U64_PRINTF_ARG(channel_id), cmux); + (unsigned)circ_id, U64_PRINTF_ARG(channel_id), cmux); /* * Assert that the circuit doesn't already have a mux for this @@ -1138,8 +1138,8 @@ circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ, /* If we're already active, log a warning and finish */ if (already_active) { log_warn(LD_CIRC, - "Circuit %d on channel " U64_FORMAT " was already active", - circ_id, U64_PRINTF_ARG(chan->global_identifier)); + "Circuit %u on channel " U64_FORMAT " was already active", + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier)); return; } @@ -1236,7 +1236,7 @@ circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ, if (already_inactive) { log_warn(LD_CIRC, "Circuit %d on channel " U64_FORMAT " was already inactive", - circ_id, U64_PRINTF_ARG(chan->global_identifier)); + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier)); return; } 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 c0612039be..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); } } @@ -695,9 +720,9 @@ circuit_expire_building(void) case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: /* If we have reached this line, we want to spare the circ for now. */ - log_info(LD_CIRC,"Marking circ %d (state %d:%s, purpose %d) " + log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) " "as timed-out HS circ", - victim->n_circ_id, + (unsigned)victim->n_circ_id, victim->state, circuit_state_to_string(victim->state), victim->purpose); TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1; @@ -713,9 +738,9 @@ circuit_expire_building(void) if (!(options->CloseHSServiceRendCircuitsImmediatelyOnTimeout) && !(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out) && victim->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) { - log_info(LD_CIRC,"Marking circ %d (state %d:%s, purpose %d) " + log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) " "as timed-out HS circ; relaunching rendezvous attempt.", - victim->n_circ_id, + (unsigned)victim->n_circ_id, victim->state, circuit_state_to_string(victim->state), victim->purpose); TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1; @@ -728,7 +753,7 @@ circuit_expire_building(void) "Abandoning circ %u %s:%d (state %d,%d:%s, purpose %d, " "len %d)", TO_ORIGIN_CIRCUIT(victim)->global_identifier, channel_get_canonical_remote_descr(victim->n_chan), - victim->n_circ_id, + (unsigned)victim->n_circ_id, TO_ORIGIN_CIRCUIT(victim)->has_opened, victim->state, circuit_state_to_string(victim->state), victim->purpose, @@ -737,7 +762,8 @@ circuit_expire_building(void) log_info(LD_CIRC, "Abandoning circ %u %d (state %d,%d:%s, purpose %d, len %d)", TO_ORIGIN_CIRCUIT(victim)->global_identifier, - victim->n_circ_id, TO_ORIGIN_CIRCUIT(victim)->has_opened, + (unsigned)victim->n_circ_id, + TO_ORIGIN_CIRCUIT(victim)->has_opened, victim->state, circuit_state_to_string(victim->state), victim->purpose, TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len); @@ -798,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)) { @@ -842,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) @@ -850,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++; @@ -1070,9 +1103,10 @@ circuit_expire_old_circuits_clientside(void) circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now.tv_sec && !TO_ORIGIN_CIRCUIT(circ)->p_streams /* nothing attached */ ) { - log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %ld sec ago, " + log_debug(LD_CIRC, "Closing n_circ_id %u (dirty %ld sec ago, " "purpose %d)", - circ->n_circ_id, (long)(now.tv_sec - circ->timestamp_dirty), + (unsigned)circ->n_circ_id, + (long)(now.tv_sec - circ->timestamp_dirty), circ->purpose); /* Don't do this magic for testing circuits. Their death is governed * by circuit_expire_building */ @@ -1153,8 +1187,8 @@ circuit_expire_old_circuits_serverside(time_t now) !or_circ->n_streams && !or_circ->resolving_streams && or_circ->p_chan && channel_when_last_xmit(or_circ->p_chan) <= cutoff) { - log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)", - or_circ->p_circ_id, + log_info(LD_CIRC, "Closing circ_id %u (empty %d secs ago)", + (unsigned)or_circ->p_circ_id, (int)(now - channel_when_last_xmit(or_circ->p_chan))); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } @@ -1896,8 +1930,8 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, const node_t *exitnode; /* add it into the linked list of streams on this circuit */ - log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.", - circ->base_.n_circ_id); + log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %u.", + (unsigned)circ->base_.n_circ_id); /* reset it, so we can measure circ timeouts */ ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL); ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams; @@ -2121,8 +2155,8 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) return retval; log_debug(LD_APP|LD_CIRC, - "Attaching apconn to circ %d (stream %d sec old).", - circ->base_.n_circ_id, conn_age); + "Attaching apconn to circ %u (stream %d sec old).", + (unsigned)circ->base_.n_circ_id, conn_age); /* print the circ's path, so people can figure out which circs are * sucking. */ circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ); @@ -2147,7 +2181,7 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) log_info(LD_REND, "rend joined circ %d already here. attaching. " "(stream %d sec old)", - rendcirc->base_.n_circ_id, conn_age); + (unsigned)rendcirc->base_.n_circ_id, conn_age); /* Mark rendezvous circuits as 'newly dirty' every time you use * them, since the process of rebuilding a rendezvous circ is so * expensive. There is a tradeoff between linkability and @@ -2168,9 +2202,9 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) if (rendcirc && (rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)) { log_info(LD_REND, - "pending-join circ %d already here, with intro ack. " + "pending-join circ %u already here, with intro ack. " "Stalling. (stream %d sec old)", - rendcirc->base_.n_circ_id, conn_age); + (unsigned)rendcirc->base_.n_circ_id, conn_age); return 0; } @@ -2182,10 +2216,10 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) if (retval > 0) { /* one has already sent the intro. keep waiting. */ tor_assert(introcirc); - log_info(LD_REND, "Intro circ %d present and awaiting ack (rend %d). " + log_info(LD_REND, "Intro circ %u present and awaiting ack (rend %u). " "Stalling. (stream %d sec old)", - introcirc->base_.n_circ_id, - rendcirc ? rendcirc->base_.n_circ_id : 0, + (unsigned)introcirc->base_.n_circ_id, + rendcirc ? (unsigned)rendcirc->base_.n_circ_id : 0, conn_age); return 0; } @@ -2195,16 +2229,17 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) if (rendcirc && introcirc && rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY) { log_info(LD_REND, - "ready rend circ %d already here (no intro-ack yet on " - "intro %d). (stream %d sec old)", - rendcirc->base_.n_circ_id, - introcirc->base_.n_circ_id, conn_age); + "ready rend circ %u already here (no intro-ack yet on " + "intro %u). (stream %d sec old)", + (unsigned)rendcirc->base_.n_circ_id, + (unsigned)introcirc->base_.n_circ_id, conn_age); tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); if (introcirc->base_.state == CIRCUIT_STATE_OPEN) { - log_info(LD_REND,"found open intro circ %d (rend %d); sending " + log_info(LD_REND,"found open intro circ %u (rend %u); sending " "introduction. (stream %d sec old)", - introcirc->base_.n_circ_id, rendcirc->base_.n_circ_id, + (unsigned)introcirc->base_.n_circ_id, + (unsigned)rendcirc->base_.n_circ_id, conn_age); switch (rend_client_send_introduction(introcirc, rendcirc)) { case 0: /* success */ @@ -2228,10 +2263,10 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) } } - log_info(LD_REND, "Intro (%d) and rend (%d) circs are not both ready. " + log_info(LD_REND, "Intro (%u) and rend (%u) circs are not both ready. " "Stalling conn. (%d sec old)", - introcirc ? introcirc->base_.n_circ_id : 0, - rendcirc ? rendcirc->base_.n_circ_id : 0, conn_age); + introcirc ? (unsigned)introcirc->base_.n_circ_id : 0, + rendcirc ? (unsigned)rendcirc->base_.n_circ_id : 0, conn_age); return 0; } } @@ -2272,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/command.c b/src/or/command.c index dfe4f65916..876ff526a6 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -16,7 +16,6 @@ * callbacks registered in command_setup_channel(), * called when channels are created in circuitbuild.c */ - #include "or.h" #include "channel.h" #include "circuitbuild.h" @@ -195,9 +194,9 @@ command_process_create_cell(cell_t *cell, channel_t *chan) tor_assert(chan); log_debug(LD_OR, - "Got a CREATE cell for circ_id %d on channel " U64_FORMAT + "Got a CREATE cell for circ_id %u on channel " U64_FORMAT " (%p)", - cell->circ_id, + (unsigned)cell->circ_id, U64_PRINTF_ARG(chan->global_identifier), chan); if (we_are_hibernating()) { @@ -240,8 +239,8 @@ command_process_create_cell(cell_t *cell, channel_t *chan) (!id_is_high && chan->circ_id_type == CIRC_ID_TYPE_LOWER)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received create cell with unexpected circ_id %d. Closing.", - cell->circ_id); + "Received create cell with unexpected circ_id %u. Closing.", + (unsigned)cell->circ_id); channel_send_destroy(cell->circ_id, chan, END_CIRC_REASON_TORPROTOCOL); return; @@ -250,9 +249,10 @@ command_process_create_cell(cell_t *cell, channel_t *chan) if (circuit_id_in_use_on_channel(cell->circ_id, chan)) { const node_t *node = node_get_by_id(chan->identity_digest); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received CREATE cell (circID %d) for known circ. " + "Received CREATE cell (circID %u) for known circ. " "Dropping (age %d).", - cell->circ_id, (int)(time(NULL) - channel_when_created(chan))); + (unsigned)cell->circ_id, + (int)(time(NULL) - channel_when_created(chan))); if (node) { char *p = esc_for_log(node_get_platform(node)); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, @@ -341,8 +341,8 @@ command_process_created_cell(cell_t *cell, channel_t *chan) if (!circ) { log_info(LD_OR, - "(circID %d) unknown circ (probably got a destroy earlier). " - "Dropping.", cell->circ_id); + "(circID %u) unknown circ (probably got a destroy earlier). " + "Dropping.", (unsigned)cell->circ_id); return; } @@ -412,8 +412,9 @@ command_process_relay_cell(cell_t *cell, channel_t *chan) if (!circ) { log_debug(LD_OR, - "unknown circuit %d on connection from %s. Dropping.", - cell->circ_id, channel_get_canonical_remote_descr(chan)); + "unknown circuit %u on connection from %s. Dropping.", + (unsigned)cell->circ_id, + channel_get_canonical_remote_descr(chan)); return; } @@ -447,9 +448,9 @@ command_process_relay_cell(cell_t *cell, channel_t *chan) or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); if (or_circ->remaining_relay_early_cells == 0) { log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Received too many RELAY_EARLY cells on circ %d from %s." + "Received too many RELAY_EARLY cells on circ %u from %s." " Closing circuit.", - cell->circ_id, + (unsigned)cell->circ_id, safe_str(channel_get_canonical_remote_descr(chan))); circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); return; @@ -487,11 +488,12 @@ command_process_destroy_cell(cell_t *cell, channel_t *chan) circ = circuit_get_by_circid_channel(cell->circ_id, chan); if (!circ) { - log_info(LD_OR,"unknown circuit %d on connection from %s. Dropping.", - cell->circ_id, channel_get_canonical_remote_descr(chan)); + log_info(LD_OR,"unknown circuit %u on connection from %s. Dropping.", + (unsigned)cell->circ_id, + channel_get_canonical_remote_descr(chan)); return; } - log_debug(LD_OR,"Received for circID %d.",cell->circ_id); + log_debug(LD_OR,"Received for circID %u.",(unsigned)cell->circ_id); reason = (uint8_t)cell->payload[0]; diff --git a/src/or/config.c b/src/or/config.c index f88842624c..20a3c20fb9 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. */ @@ -213,6 +213,7 @@ static config_var_t option_vars_[] = { V(DisableAllSwap, BOOL, "0"), V(DisableDebuggerAttachment, BOOL, "1"), V(DisableIOCP, BOOL, "1"), + V(DisableV2DirectoryInfo_, BOOL, "0"), V(DynamicDHGroups, BOOL, "0"), VPORT(DNSPort, LINELIST, NULL), V(DNSListenAddress, LINELIST, NULL), @@ -254,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), @@ -299,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"), @@ -338,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"), @@ -379,6 +384,7 @@ static config_var_t option_vars_[] = { V(SocksPolicy, LINELIST, NULL), VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), + V(SSLKeyLifetime, INTERVAL, "0"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), OBSOLETE("SysLog"), @@ -1500,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; } @@ -2379,6 +2385,10 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive."); } + if (options->DisableV2DirectoryInfo_ && ! authdir_mode(options)) { + REJECT("DisableV2DirectoryInfo_ set, but we aren't an authority."); + } + if (options->ExcludeExitNodes || options->ExcludeNodes) { options->ExcludeExitNodesUnion_ = routerset_new(); routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes); @@ -2475,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; @@ -2595,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) { @@ -2715,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) { @@ -4995,6 +5009,7 @@ parse_port_config(smartlist_t *out, int port; int sessiongroup = SESSION_GROUP_UNSET; unsigned isolation = ISO_DEFAULT; + int prefer_no_auth = 0; char *addrport; uint16_t ptmp=0; @@ -5162,6 +5177,9 @@ parse_port_config(smartlist_t *out, } else if (!strcasecmp(elt, "PreferIPv6Automap")) { prefer_ipv6_automap = ! no; continue; + } else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) { + prefer_no_auth = ! no; + continue; } if (!strcasecmpend(elt, "s")) @@ -5221,6 +5239,9 @@ parse_port_config(smartlist_t *out, cfg->use_cached_ipv4_answers = use_cached_ipv4; cfg->use_cached_ipv6_answers = use_cached_ipv6; cfg->prefer_ipv6_virtaddr = prefer_ipv6_automap; + cfg->socks_prefer_no_auth = prefer_no_auth; + if (! (isolation & ISO_SOCKSAUTH)) + cfg->socks_prefer_no_auth = 1; smartlist_add(out, cfg); } 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..2520d559b1 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); @@ -1139,6 +1145,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, lis_conn->use_cached_ipv4_answers = port_cfg->use_cached_ipv4_answers; lis_conn->use_cached_ipv6_answers = port_cfg->use_cached_ipv6_answers; lis_conn->prefer_ipv6_virtaddr = port_cfg->prefer_ipv6_virtaddr; + lis_conn->socks_prefer_no_auth = port_cfg->socks_prefer_no_auth; if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for listener failed. Giving up."); @@ -1265,7 +1272,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); @@ -1316,6 +1326,11 @@ connection_handle_listener_read(connection_t *conn, int new_type) newconn->port = port; newconn->address = tor_dup_addr(&addr); + if (new_type == CONN_TYPE_AP) { + TO_ENTRY_CONN(newconn)->socks_request->socks_prefer_no_auth = + TO_LISTENER_CONN(conn)->socks_prefer_no_auth; + } + } else if (conn->socket_family == AF_UNIX) { /* For now only control ports can be Unix domain sockets * and listeners at the same time */ @@ -1494,7 +1509,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); @@ -2935,7 +2954,20 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, case TOR_TLS_WANTWRITE: connection_start_writing(conn); return 0; - case TOR_TLS_WANTREAD: /* we're already reading */ + case TOR_TLS_WANTREAD: + if (conn->in_connection_handle_write) { + /* We've been invoked from connection_handle_write, because we're + * waiting for a TLS renegotiation, the renegotiation started, and + * SSL_read returned WANTWRITE. But now SSL_read is saying WANTREAD + * again. Stop waiting for write events now, or else we'll + * busy-loop until data arrives for us to read. */ + connection_stop_writing(conn); + if (!connection_is_reading(conn)) + connection_start_reading(conn); + } + /* we're already reading, one hopes */ + result = 0; + break; case TOR_TLS_DONE: /* no data read, so nothing to process */ result = 0; break; /* so we call bucket_decrement below */ @@ -3426,6 +3458,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); @@ -3490,7 +3526,9 @@ connection_handle_write(connection_t *conn, int force) { int res; tor_gettimeofday_cache_clear(); + conn->in_connection_handle_write = 1; res = connection_handle_write_impl(conn, force); + conn->in_connection_handle_write = 0; return res; } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index fcbcb95919..926fcab90c 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -218,8 +218,8 @@ int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn) { if (!conn->base_.marked_for_close) { - log_info(LD_EDGE, - "CircID %d: At an edge. Marking connection for close.", circ_id); + log_info(LD_EDGE, "CircID %u: At an edge. Marking connection for close.", + (unsigned) circ_id); if (conn->base_.type == CONN_TYPE_AP) { entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DESTROY); @@ -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; } @@ -1847,8 +1845,8 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn) edge_conn->deliver_window = STREAMWINDOW_START; base_conn->state = AP_CONN_STATE_CONNECT_WAIT; log_info(LD_APP,"Address/port sent, ap socket "TOR_SOCKET_T_FORMAT - ", n_circ_id %d", - base_conn->s, circ->base_.n_circ_id); + ", n_circ_id %u", + base_conn->s, (unsigned)circ->base_.n_circ_id); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0); /* If there's queued-up data, send it now */ @@ -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 %d", - base_conn->s, circ->base_.n_circ_id); - control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0); + ", n_circ_id %u", + base_conn->s, (unsigned)circ->base_.n_circ_id); 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/connection_or.c b/src/or/connection_or.c index c4415c5f88..3616363505 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -9,7 +9,6 @@ * \brief Functions to handle OR connections, TLS handshaking, and * cells on the network. **/ - #include "or.h" #include "buffers.h" /* diff --git a/src/or/control.c b/src/or/control.c index 03e5d79c8e..390b8d1502 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; @@ -4717,6 +4715,9 @@ control_event_bootstrap_problem(const char *warn, int reason) !any_pending_bridge_descriptor_fetches()) recommendation = "warn"; + if (we_are_hibernating()) + recommendation = "ignore"; + while (status>=0 && bootstrap_status_to_string(status, &tag, &summary) < 0) status--; /* find a recognized status string based on current progress */ status = bootstrap_percent; /* set status back to the actual number */ 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 af5f91a623..61f9faa394 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -11,7 +11,6 @@ * * Right now, we only use this for processing onionskins. **/ - #include "or.h" #include "buffers.h" #include "channel.h" @@ -341,8 +340,8 @@ connection_cpu_process_inbuf(connection_t *conn) circ = NULL; log_debug(LD_OR, "Unpacking cpuworker reply, chan_id is " U64_FORMAT - ", circ_id is %d", - U64_PRINTF_ARG(chan_id), circ_id); + ", circ_id is %u", + U64_PRINTF_ARG(chan_id), (unsigned)circ_id); p_chan = channel_find_by_global_id(chan_id); if (p_chan) @@ -536,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/directory.c b/src/or/directory.c index 6b61fc6a99..38a423cb8e 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2805,6 +2805,19 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, const char *key = url + strlen("/tor/status/"); long lifetime = NETWORKSTATUS_CACHE_LIFETIME; + if (options->DisableV2DirectoryInfo_ && !is_v3) { + static ratelim_t reject_v2_ratelim = RATELIM_INIT(1800); + char *m; + write_http_status_line(conn, 404, "Not found"); + smartlist_free(dir_fps); + geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND); + if ((m = rate_limit_log(&reject_v2_ratelim, approx_time()))) { + log_notice(LD_DIR, "Rejected a v2 networkstatus request.%s", m); + tor_free(m); + } + goto done; + } + if (!is_v3) { dirserv_get_networkstatus_v2_fingerprints(dir_fps, key); if (!strcmpstart(key, "fp/")) diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 173c8cd14a..3755720500 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_kb(const routerinfo_t *ri); +static uint32_t dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri); /************** Fingerprint handling code ************/ @@ -1770,17 +1776,13 @@ static double guard_wfu = 0.0; * many seconds. */ static long guard_tk = 0; /** Any router with a bandwidth at least this high is "Fast" */ -static uint32_t fast_bandwidth = 0; +static uint32_t fast_bandwidth_kb = 0; /** If exits can be guards, then all guards must have a bandwidth this * high. */ -static uint32_t guard_bandwidth_including_exits = 0; +static uint32_t guard_bandwidth_including_exits_kb = 0; /** If exits can't be guards, then all guards must have a bandwidth this * high. */ -static uint32_t guard_bandwidth_excluding_exits = 0; -/** Total bandwidth of all the routers we're considering. */ -static uint64_t total_bandwidth = 0; -/** Total bandwidth of all the exit routers we're considering. */ -static uint64_t total_exit_bandwidth = 0; +static uint32_t guard_bandwidth_excluding_exits_kb = 0; /** Helper: estimate the uptime of a router given its stated uptime and the * amount of time since it last stated its stated uptime. */ @@ -1824,8 +1826,8 @@ dirserv_thinks_router_is_unreliable(time_t now, } } if (need_capacity) { - uint32_t bw = router_get_advertised_bandwidth(router); - if (bw < fast_bandwidth) + uint32_t bw_kb = dirserv_get_credible_bandwidth_kb(router); + if (bw_kb < fast_bandwidth_kb) return 1; } return 0; @@ -1873,18 +1875,32 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, /** Don't consider routers with less bandwidth than this when computing * thresholds. */ -#define ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER 4096 +#define ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB 4 /** 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_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB; + const or_options_t *options = get_options(); + + if (options->TestingTorNetwork) { + min_bw_kb = (int64_t)options->TestingMinExitFlagThreshold / 1000; + } + 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_kb(node->ri) >= min_bw_kb) && + (have_mbw || !require_mbw); } /** Look through the routerlist, the Mean Time Between Failure history, and @@ -1892,7 +1908,6 @@ router_counts_toward_thresholds(const node_t *node, time_t now, * the Stable, Fast, and Guard flags. Update the fields stable_uptime, * stable_mtbf, enough_mtbf_info, guard_wfu, guard_tk, fast_bandwidth, * guard_bandwidh_including_exits, guard_bandwidth_excluding_exits, - * total_bandwidth, and total_exit_bandwidth. * * Also, set the is_exit flag of each router appropriately. */ static void @@ -1900,22 +1915,25 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, digestmap_t *omit_as_sybil) { int n_active, n_active_nonexit, n_familiar; - uint32_t *uptimes, *bandwidths, *bandwidths_excluding_exits; + uint32_t *uptimes, *bandwidths_kb, *bandwidths_excluding_exits_kb; long *tks; double *mtbfs, *wfus; 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; - fast_bandwidth = 0; - guard_bandwidth_including_exits = 0; - guard_bandwidth_excluding_exits = 0; + fast_bandwidth_kb = 0; + guard_bandwidth_including_exits_kb = 0; + guard_bandwidth_excluding_exits_kb = 0; guard_tk = 0; guard_wfu = 0; - total_bandwidth = 0; - total_exit_bandwidth = 0; /* Initialize arrays that will hold values for each router. We'll * sort them and use that to compute thresholds. */ @@ -1923,9 +1941,9 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, /* Uptime for every active router. */ uptimes = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); /* Bandwidth for every active router. */ - bandwidths = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + bandwidths_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); /* Bandwidth for every active non-exit router. */ - bandwidths_excluding_exits = + bandwidths_excluding_exits_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); /* Weighted mean time between failure for each active router. */ mtbfs = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); @@ -1938,21 +1956,19 @@ 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; + uint32_t bw_kb; node->is_exit = (!router_exit_policy_rejects_all(ri) && exit_policy_is_general_exit(ri->exit_policy)); 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); - total_bandwidth += bw; - if (node->is_exit && !node->is_bad_exit) { - total_exit_bandwidth += bw; - } else { - bandwidths_excluding_exits[n_active_nonexit] = bw; + bandwidths_kb[n_active] = bw_kb = dirserv_get_credible_bandwidth_kb(ri); + if (!node->is_exit || node->is_bad_exit) { + bandwidths_excluding_exits_kb[n_active_nonexit] = bw_kb; ++n_active_nonexit; } ++n_active; @@ -1966,11 +1982,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, /* The median mtbf is stable, if we have enough mtbf info */ stable_mtbf = median_double(mtbfs, n_active); /* The 12.5th percentile bandwidth is fast. */ - fast_bandwidth = find_nth_uint32(bandwidths, n_active, n_active/8); + fast_bandwidth_kb = find_nth_uint32(bandwidths_kb, n_active, n_active/8); /* (Now bandwidths is sorted.) */ - if (fast_bandwidth < ROUTER_REQUIRED_MIN_BANDWIDTH/2) - fast_bandwidth = bandwidths[n_active/4]; - guard_bandwidth_including_exits = bandwidths[(n_active-1)/2]; + if (fast_bandwidth_kb < ROUTER_REQUIRED_MIN_BANDWIDTH/(2 * 1000)) + fast_bandwidth_kb = bandwidths_kb[n_active/4]; + guard_bandwidth_including_exits_kb = bandwidths_kb[(n_active-1)/2]; guard_tk = find_nth_long(tks, n_active, n_active/8); } @@ -1979,31 +1995,38 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, { /* We can vote on a parameter for the minimum and maximum. */ -#define ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG 4096 - int32_t min_fast, max_fast; +#define ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG 4 + int32_t min_fast_kb, max_fast_kb, min_fast, max_fast; min_fast = networkstatus_get_param(NULL, "FastFlagMinThreshold", 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) - fast_bandwidth = min_fast; - if (fast_bandwidth > (uint32_t)max_fast) - fast_bandwidth = max_fast; + min_fast_kb = min_fast / 1000; + max_fast_kb = max_fast / 1000; + + if (fast_bandwidth_kb < (uint32_t)min_fast_kb) + fast_bandwidth_kb = min_fast_kb; + if (fast_bandwidth_kb > (uint32_t)max_fast_kb) + fast_bandwidth_kb = max_fast_kb; } /* Protect sufficiently fast nodes from being pushed out of the set * of Fast nodes. */ if (options->AuthDirFastGuarantee && - fast_bandwidth > options->AuthDirFastGuarantee) - fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee; + fast_bandwidth_kb > options->AuthDirFastGuarantee/1000) + fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000; /* Now that we have a time-known that 7/8 routers are known longer than, * fill wfus with the wfu of every such "familiar" router. */ 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); @@ -2020,32 +2043,230 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, enough_mtbf_info = rep_hist_have_measured_enough_stability(); if (n_active_nonexit) { - guard_bandwidth_excluding_exits = - median_uint32(bandwidths_excluding_exits, n_active_nonexit); + guard_bandwidth_excluding_exits_kb = + median_uint32(bandwidths_excluding_exits_kb, n_active_nonexit); } log_info(LD_DIRSERV, "Cutoffs: For Stable, %lu sec uptime, %lu sec MTBF. " - "For Fast: %lu bytes/sec. " + "For Fast: %lu kilobytes/sec. " "For Guard: WFU %.03f%%, time-known %lu sec, " - "and bandwidth %lu or %lu bytes/sec. We%s have enough stability data.", + "and bandwidth %lu or %lu kilobytes/sec. " + "We%s have enough stability data.", (unsigned long)stable_uptime, (unsigned long)stable_mtbf, - (unsigned long)fast_bandwidth, + (unsigned long)fast_bandwidth_kb, guard_wfu*100, (unsigned long)guard_tk, - (unsigned long)guard_bandwidth_including_exits, - (unsigned long)guard_bandwidth_excluding_exits, + (unsigned long)guard_bandwidth_including_exits_kb, + (unsigned long)guard_bandwidth_excluding_exits_kb, enough_mtbf_info ? "" : " don't "); tor_free(uptimes); tor_free(mtbfs); - tor_free(bandwidths); - tor_free(bandwidths_excluding_exits); + tor_free(bandwidths_kb); + tor_free(bandwidths_excluding_exits_kb); tor_free(tks); tor_free(wfus); } +/** Measured bandwidth cache entry */ +typedef struct mbw_cache_entry_s { + long mbw_kb; + 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_kb = parsed_line->bw_kb; + e->as_of = as_of; + } + } else { + /* We'll have to insert a new entry */ + e = tor_malloc(sizeof(*e)); + e->mbw_kb = parsed_line->bw_kb; + 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_kb(const char *node_id, long *bw_kb_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_kb_out) *bw_kb_out = v->mbw_kb; + 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_kb(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_kb(const routerinfo_t *ri) +{ + uint32_t bw_kb = 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_kb = 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_kb(ri->cache_info.identity_digest, + &mbw_kb, NULL)) { + /* Got one! */ + bw_kb = (uint32_t)mbw_kb; + } else { + /* If not, fall back to advertised */ + bw_kb = router_get_advertised_bandwidth(ri) / 1000; + } + } + + return bw_kb; +} + +/** 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_kb(const routerinfo_t *ri) +{ + int threshold; + uint32_t bw_kb = 0; + long mbw_kb; + + tor_assert(ri); + /* Check if we have a measured bandwidth, and check the threshold if not */ + if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest, + &mbw_kb, NULL))) { + threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; + if (routers_with_measured_bw > threshold) { + /* Return zero for unmeasured bandwidth if we are above threshold */ + bw_kb = 0; + } else { + /* Return an advertised bandwidth otherwise */ + bw_kb = router_get_advertised_bandwidth_capped(ri) / 1000; + } + } else { + /* We have the measured bandwidth in mbw */ + bw_kb = (uint32_t)mbw_kb; + } + + return bw_kb; +} + /** Give a statement of our current performance thresholds for inclusion * in a vote document. */ char * @@ -2060,11 +2281,11 @@ dirserv_get_flag_thresholds_line(void) "enough-mtbf=%d", (unsigned long)stable_uptime, (unsigned long)stable_mtbf, - (unsigned long)fast_bandwidth, + (unsigned long)fast_bandwidth_kb*1000, guard_wfu*100, (unsigned long)guard_tk, - (unsigned long)guard_bandwidth_including_exits, - (unsigned long)guard_bandwidth_excluding_exits, + (unsigned long)guard_bandwidth_including_exits_kb*1000, + (unsigned long)guard_bandwidth_excluding_exits_kb*1000, enough_mtbf_info ? 1 : 0); return result; @@ -2176,7 +2397,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, if (format != NS_V2) { const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest); - uint32_t bw; + uint32_t bw_kb; if (format != NS_CONTROL_PORT) { /* Blow up more or less nicely if we didn't get anything or not the @@ -2194,9 +2415,10 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, goto err; } - /* 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)) { @@ -2220,17 +2442,17 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, } if (format == NS_CONTROL_PORT && rs->has_bandwidth) { - bw = rs->bandwidth; + bw_kb = rs->bandwidth_kb; } else { tor_assert(desc); - bw = router_get_advertised_bandwidth_capped(desc) / 1000; + bw_kb = router_get_advertised_bandwidth_capped(desc) / 1000; } smartlist_add_asprintf(chunks, - "w Bandwidth=%d", bw); + "w Bandwidth=%d", bw_kb); if (format == NS_V3_VOTE && vrs && vrs->has_measured_bw) { smartlist_add_asprintf(chunks, - " Measured=%d", vrs->measured_bw); + " Measured=%d", vrs->measured_bw_kb); } smartlist_add(chunks, tor_strdup("\n")); @@ -2263,7 +2485,7 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b) { routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; int first_is_auth, second_is_auth; - uint32_t bw_first, bw_second; + uint32_t bw_kb_first, bw_kb_second; const node_t *node_first, *node_second; int first_is_running, second_is_running; @@ -2298,12 +2520,12 @@ 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_kb_first = dirserv_get_bandwidth_for_router_kb(first); + bw_kb_second = dirserv_get_bandwidth_for_router_kb(second); - if (bw_first > bw_second) + if (bw_kb_first > bw_kb_second) return -1; - else if (bw_first < bw_second) + else if (bw_kb_first < bw_kb_second) return 1; /* They're equal! Compare by identity digest, so there's a @@ -2439,7 +2661,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_kb = dirserv_get_credible_bandwidth_kb(ri); memset(rs, 0, sizeof(routerstatus_t)); @@ -2466,9 +2688,9 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, if (node->is_fast && ((options->AuthDirGuardBWGuarantee && - routerbw >= options->AuthDirGuardBWGuarantee) || - routerbw >= MIN(guard_bandwidth_including_exits, - guard_bandwidth_excluding_exits)) && + routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) || + routerbw_kb >= MIN(guard_bandwidth_including_exits_kb, + guard_bandwidth_excluding_exits_kb)) && is_router_version_good_for_possible_guard(ri->platform)) { long tk = rep_hist_get_weighted_time_known( node->identity, now); @@ -2563,7 +2785,7 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line) } cp+=strlen("bw="); - out->bw = tor_parse_long(cp, 0, 0, LONG_MAX, &parse_ok, &endptr); + out->bw_kb = tor_parse_long(cp, 0, 0, LONG_MAX, &parse_ok, &endptr); if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) { log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s", escaped(orig_line)); @@ -2621,7 +2843,7 @@ measured_bw_line_apply(measured_bw_line_t *parsed_line, if (rs) { rs->has_measured_bw = 1; - rs->measured_bw = (uint32_t)parsed_line->bw; + rs->measured_bw_kb = (uint32_t)parsed_line->bw_kb; } else { log_info(LD_DIRSERV, "Node ID %s not found in routerstatus list", parsed_line->node_hex); @@ -2641,8 +2863,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); @@ -2666,7 +2889,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); @@ -2680,12 +2904,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. " @@ -2749,6 +2978,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, { @@ -2765,6 +3010,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(); @@ -2809,9 +3058,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)); @@ -3875,5 +4133,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 cc4ac2e0a4..f9d36d760f 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -54,7 +54,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); @@ -116,10 +115,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_kb(const char *node_id, long *bw_out, + time_t *as_of_out); +int dirserv_has_measured_bw(const char *node_id); cached_dir_t *generate_v2_networkstatus_opinion(void); #endif diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 8ae0bb8613..b02434c892 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -1321,7 +1321,7 @@ networkstatus_compute_consensus(smartlist_t *votes, char *client_versions = NULL, *server_versions = NULL; smartlist_t *flags; const char *flavor_name; - uint32_t max_unmeasured_bw = DEFAULT_MAX_UNMEASURED_BW; + uint32_t max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB; int64_t G=0, M=0, E=0, D=0, T=0; /* For bandwidth weights */ const routerstatus_format_type_t rs_format = flavor == FLAV_NS ? NS_V3_CONSENSUS : NS_V3_CONSENSUS_MICRODESC; @@ -1533,12 +1533,12 @@ networkstatus_compute_consensus(smartlist_t *votes, int ok = 0; char *eq = strchr(max_unmeasured_param, '='); if (eq) { - max_unmeasured_bw = (uint32_t) + max_unmeasured_bw_kb = (uint32_t) tor_parse_ulong(eq+1, 10, 1, UINT32_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIR, "Bad element '%s' in max unmeasured bw param", escaped(max_unmeasured_param)); - max_unmeasured_bw = DEFAULT_MAX_UNMEASURED_BW; + max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB; } } } @@ -1555,9 +1555,10 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_t *chosen_flags = smartlist_new(); smartlist_t *versions = smartlist_new(); smartlist_t *exitsummaries = smartlist_new(); - uint32_t *bandwidths = tor_malloc(sizeof(uint32_t) * smartlist_len(votes)); - uint32_t *measured_bws = tor_malloc(sizeof(uint32_t) * - smartlist_len(votes)); + uint32_t *bandwidths_kb = tor_malloc(sizeof(uint32_t) * + smartlist_len(votes)); + uint32_t *measured_bws_kb = tor_malloc(sizeof(uint32_t) * + smartlist_len(votes)); int num_bandwidths; int num_mbws; @@ -1737,10 +1738,10 @@ networkstatus_compute_consensus(smartlist_t *votes, /* count bandwidths */ if (rs->has_measured_bw) - measured_bws[num_mbws++] = rs->measured_bw; + measured_bws_kb[num_mbws++] = rs->measured_bw_kb; if (rs->status.has_bandwidth) - bandwidths[num_bandwidths++] = rs->status.bandwidth; + bandwidths_kb[num_bandwidths++] = rs->status.bandwidth_kb; } SMARTLIST_FOREACH_END(v); /* We don't include this router at all unless more than half of @@ -1831,36 +1832,36 @@ networkstatus_compute_consensus(smartlist_t *votes, if (consensus_method >= 6 && num_mbws > 2) { rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 0; - rs_out.bandwidth = median_uint32(measured_bws, num_mbws); + rs_out.bandwidth_kb = median_uint32(measured_bws_kb, num_mbws); } else if (consensus_method >= 5 && num_bandwidths > 0) { rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 1; - rs_out.bandwidth = median_uint32(bandwidths, num_bandwidths); + rs_out.bandwidth_kb = median_uint32(bandwidths_kb, num_bandwidths); if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW && n_authorities_measuring_bandwidth > 2) { /* Cap non-measured bandwidths. */ - if (rs_out.bandwidth > max_unmeasured_bw) { - rs_out.bandwidth = max_unmeasured_bw; + if (rs_out.bandwidth_kb > max_unmeasured_bw_kb) { + rs_out.bandwidth_kb = max_unmeasured_bw_kb; } } } /* 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; } if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { if (rs_out.has_bandwidth) { - T += rs_out.bandwidth; + T += rs_out.bandwidth_kb; if (is_exit && is_guard) - D += rs_out.bandwidth; + D += rs_out.bandwidth_kb; else if (is_exit) - E += rs_out.bandwidth; + E += rs_out.bandwidth_kb; else if (is_guard) - G += rs_out.bandwidth; + G += rs_out.bandwidth_kb; else - M += rs_out.bandwidth; + M += rs_out.bandwidth_kb; } else { log_warn(LD_BUG, "Missing consensus bandwidth for router %s", rs_out.nickname); @@ -1986,7 +1987,8 @@ networkstatus_compute_consensus(smartlist_t *votes, if (rs_out.has_bandwidth) { int unmeasured = rs_out.bw_is_unmeasured && consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW; - smartlist_add_asprintf(chunks, "w Bandwidth=%d%s\n", rs_out.bandwidth, + smartlist_add_asprintf(chunks, "w Bandwidth=%d%s\n", + rs_out.bandwidth_kb, unmeasured?" Unmeasured=1":""); } @@ -2013,8 +2015,8 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_free(chosen_flags); smartlist_free(versions); smartlist_free(exitsummaries); - tor_free(bandwidths); - tor_free(measured_bws); + tor_free(bandwidths_kb); + tor_free(measured_bws_kb); } if (consensus_method >= MIN_METHOD_FOR_FOOTER) { @@ -2140,7 +2142,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..b236452122 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 @@ -58,7 +61,7 @@ /** Default bandwidth to clip unmeasured bandwidths to using method >= * MIN_METHOD_TO_CLIP_UNMEASURED_BW */ -#define DEFAULT_MAX_UNMEASURED_BW 20 +#define DEFAULT_MAX_UNMEASURED_BW_KB 20 void dirvote_free_all(void); 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 51c3a56742..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" @@ -133,6 +134,8 @@ entry_guard_set_status(entry_guard_t *e, const node_t *node, if (node) { int is_dir = node_is_dir(node) && node->rs && node->rs->version_supports_microdesc_cache; + if (options->UseBridges && node_is_a_configured_bridge(node)) + is_dir = 1; if (e->is_dir_cache != is_dir) { e->is_dir_cache = is_dir; changed = 1; @@ -330,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. @@ -354,6 +360,8 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, } entry->is_dir_cache = node->rs && node->rs->version_supports_microdesc_cache; + if (get_options()->UseBridges && node_is_a_configured_bridge(node)) + entry->is_dir_cache = 1; return NULL; } } else if (!for_directory) { @@ -363,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)); @@ -377,6 +394,8 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, memcpy(entry->identity, node->identity, DIGEST_LEN); entry->is_dir_cache = node_is_dir(node) && node->rs && node->rs->version_supports_microdesc_cache; + if (get_options()->UseBridges && node_is_a_configured_bridge(node)) + entry->is_dir_cache = 1; /* Choose expiry time smudged over the past month. The goal here * is to a) spread out when Tor clients rotate their guards, so they @@ -385,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 @@ -429,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. */ @@ -438,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); @@ -468,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; } @@ -724,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 @@ -808,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); @@ -1147,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; @@ -1197,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; @@ -1263,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/include.am b/src/or/include.am index 241015488a..d2be1fb1ef 100644 --- a/src/or/include.am +++ b/src/or/include.am @@ -188,6 +188,6 @@ src/or/or_sha1.i: $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS) touch src/or/or_sha1.i; \ fi -CLEANFILES+= micro-revision.i +CLEANFILES+= micro-revision.i src/or/micro-revision.i FORCE: 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 cde146907c..f5428f165d 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 b821caf310..f2f27eea5f 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -177,8 +177,6 @@ #define MIN_ONION_KEY_LIFETIME (7*24*60*60) /** How often do we rotate TLS contexts? */ #define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60) -/** What expiry time shall we place on our SSL certs? */ -#define MAX_SSL_KEY_LIFETIME_ADVERTISED (365*24*60*60) /** How old do we allow a router to get before removing it * from the router list? In seconds. */ @@ -1165,6 +1163,9 @@ typedef struct connection_t { /** Set to 1 when we're inside connection_flushed_some to keep us from * calling connection_handle_write() recursively. */ unsigned int in_flushed_some:1; + /** True if connection_handle_write is currently running on this connection. + */ + unsigned int in_connection_handle_write:1; /* For linked connections: */ @@ -1249,6 +1250,10 @@ typedef struct listener_connection_t { /** One or more ISO_ flags to describe how to isolate streams. */ uint8_t isolation_flags; /**@}*/ + /** For SOCKS connections only: If this is set, we will choose "no + * authentication" instead of "username/password" authentication if both + * are offered. Used as input to parse_socks. */ + unsigned int socks_prefer_no_auth : 1; /** For a SOCKS listeners, these fields describe whether we should * allow IPv4 and IPv6 addresses from our exit nodes, respectively. @@ -1419,8 +1424,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. */ @@ -2094,7 +2099,7 @@ typedef struct routerstatus_t { unsigned int bw_is_unmeasured:1; /**< This is a consensus entry, with * the Unmeasured flag set. */ - uint32_t bandwidth; /**< Bandwidth (capacity) of the router as reported in + uint32_t bandwidth_kb; /**< Bandwidth (capacity) of the router as reported in * the vote/consensus, in kilobytes/sec. */ char *exitsummary; /**< exit policy summary - * XXX weasel: this probably should not stay a string. */ @@ -2251,6 +2256,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. */ @@ -2338,7 +2346,7 @@ typedef struct vote_routerstatus_t { char *version; /**< The version that the authority says this router is * running. */ unsigned int has_measured_bw:1; /**< The vote had a measured bw */ - uint32_t measured_bw; /**< Measured bandwidth (capacity) of the router */ + uint32_t measured_bw_kb; /**< Measured bandwidth (capacity) of the router */ /** The hash or hashes that the authority claims this microdesc has. */ vote_microdesc_hash_t *microdesc; } vote_routerstatus_t; @@ -2945,6 +2953,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 @@ -3062,6 +3074,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; @@ -3235,6 +3251,10 @@ typedef struct port_cfg_t { uint8_t isolation_flags; /**< Zero or more isolation flags */ int session_group; /**< A session group, or -1 if this port is not in a * session group. */ + /* Socks only: */ + /** When both no-auth and user/pass are advertised by a SOCKS client, select + * no-auth. */ + unsigned int socks_prefer_no_auth : 1; /* Server port types (or, dir) only: */ unsigned int no_advertise : 1; @@ -3871,6 +3891,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; @@ -3898,6 +3922,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. */ @@ -4000,6 +4030,23 @@ typedef struct { /** Fraction: */ double PathsNeededToBuildCircuits; + + /** Do we serve v2 directory info at all? This is a temporary option, since + * we'd like to disable v2 directory serving entirely, but we need a way to + * make it temporarily disableable, in order to do fast testing and be + * able to turn it back on if it turns out to be non-workable. + * + * XXXX025 Make this always-on, or always-off. Right now, it's only + * enableable for authorities. + */ + int DisableV2DirectoryInfo_; + + /** What expiry time shall we place on our SSL certs? "0" means we + * 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. */ @@ -4124,6 +4171,10 @@ struct socks_request_t { * make sure we send back a socks reply for * every connection. */ unsigned int got_auth : 1; /**< Have we received any authentication data? */ + /** If this is set, we will choose "no authentication" instead of + * "username/password" authentication if both are offered. Used as input to + * parse_socks. */ + unsigned int socks_prefer_no_auth : 1; /** Number of bytes in username; 0 if username is NULL */ size_t usernamelen; @@ -4431,7 +4482,7 @@ typedef enum { typedef struct measured_bw_line_t { char node_id[DIGEST_LEN]; char node_hex[MAX_HEX_NICKNAME_LEN+1]; - long int bw; + long int bw_kb; } measured_bw_line_t; #endif @@ -4453,15 +4504,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. @@ -4781,6 +4823,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..52ff32f0ca 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. */ @@ -374,15 +379,22 @@ relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, static int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, cell_direction_t cell_direction, - crypt_path_t *layer_hint, streamid_t on_stream) + crypt_path_t *layer_hint, streamid_t on_stream, + const char *filename, int lineno) { channel_t *chan; /* where to send the cell */ if (cell_direction == CELL_DIRECTION_OUT) { crypt_path_t *thishop; /* counter for repeated crypts */ chan = circ->n_chan; - if (!CIRCUIT_IS_ORIGIN(circ) || !chan) { - log_warn(LD_BUG,"outgoing relay cell has n_chan==NULL. Dropping."); + if (!chan) { + log_warn(LD_BUG,"outgoing relay cell sent from %s:%d has n_chan==NULL." + " Dropping.", filename, lineno); + return 0; /* just drop it */ + } + if (!CIRCUIT_IS_ORIGIN(circ)) { + log_warn(LD_BUG,"outgoing relay cell sent from %s:%d on non-origin " + "circ. Dropping.", filename, lineno); return 0; /* just drop it */ } @@ -543,9 +555,10 @@ relay_command_to_string(uint8_t command) * return 0. */ int -relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, - uint8_t relay_command, const char *payload, - size_t payload_len, crypt_path_t *cpath_layer) +relay_send_command_from_edge_(streamid_t stream_id, circuit_t *circ, + uint8_t relay_command, const char *payload, + size_t payload_len, crypt_path_t *cpath_layer, + const char *filename, int lineno) { cell_t cell; relay_header_t rh; @@ -628,7 +641,7 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, } if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer, - stream_id) < 0) { + stream_id, filename, lineno) < 0) { log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing."); circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; @@ -710,7 +723,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 +765,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 +820,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 +844,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 +859,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 +907,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->address field on conn to the * dotted-quad representation of <b>new_addr</b>, * and send an appropriate REMAP event. */ @@ -1101,12 +1148,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 +1448,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/relay.h b/src/or/relay.h index 7e59838f95..229fb4f737 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -20,9 +20,15 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, void relay_header_pack(uint8_t *dest, const relay_header_t *src); void relay_header_unpack(relay_header_t *dest, const uint8_t *src); -int relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, +int relay_send_command_from_edge_(streamid_t stream_id, circuit_t *circ, uint8_t relay_command, const char *payload, - size_t payload_len, crypt_path_t *cpath_layer); + size_t payload_len, crypt_path_t *cpath_layer, + const char *filename, int lineno); +#define relay_send_command_from_edge(stream_id, circ, relay_command, payload, \ + payload_len, cpath_layer) \ + relay_send_command_from_edge_((stream_id), (circ), (relay_command), \ + (payload), (payload_len), (cpath_layer), \ + __FILE__, __LINE__) int connection_edge_send_command(edge_connection_t *fromconn, uint8_t relay_command, const char *payload, size_t payload_len); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 61e3b917e3..7115bf2080 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -111,14 +111,14 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ) // XXX: should we not re-extend if hs_circ_has_timed_out? if (circ->remaining_relay_early_cells) { log_info(LD_REND, - "Re-extending circ %d, this time to %s.", - circ->base_.n_circ_id, + "Re-extending circ %u, this time to %s.", + (unsigned)circ->base_.n_circ_id, safe_str_client(extend_info_describe(extend_info))); result = circuit_extend_to_new_exit(circ, extend_info); } else { log_info(LD_REND, - "Closing intro circ %d (out of RELAY_EARLY cells).", - circ->base_.n_circ_id); + "Closing intro circ %u (out of RELAY_EARLY cells).", + (unsigned)circ->base_.n_circ_id); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); /* connection_ap_handshake_attach_circuit will launch a new intro circ. */ result = 0; @@ -386,8 +386,8 @@ rend_client_introduction_acked(origin_circuit_t *circ, if (circ->base_.purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { log_warn(LD_PROTOCOL, - "Received REND_INTRODUCE_ACK on unexpected circuit %d.", - circ->base_.n_circ_id); + "Received REND_INTRODUCE_ACK on unexpected circuit %u.", + (unsigned)circ->base_.n_circ_id); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); return -1; } 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/rendmid.c b/src/or/rendmid.c index 1046ce3814..1bd11f6dc0 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -32,8 +32,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, int reason = END_CIRC_REASON_INTERNAL; log_info(LD_REND, - "Received an ESTABLISH_INTRO request on circuit %d", - circ->p_circ_id); + "Received an ESTABLISH_INTRO request on circuit %u", + (unsigned) circ->p_circ_id); if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, @@ -114,8 +114,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, memcpy(circ->rend_token, pk_digest, DIGEST_LEN); log_info(LD_REND, - "Established introduction point on circuit %d for service %s", - circ->p_circ_id, safe_str(serviceid)); + "Established introduction point on circuit %u for service %s", + (unsigned) circ->p_circ_id, safe_str(serviceid)); return 0; truncated: @@ -139,13 +139,13 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, char serviceid[REND_SERVICE_ID_LEN_BASE32+1]; char nak_body[1]; - log_info(LD_REND, "Received an INTRODUCE1 request on circuit %d", - circ->p_circ_id); + log_info(LD_REND, "Received an INTRODUCE1 request on circuit %u", + (unsigned)circ->p_circ_id); if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_warn(LD_PROTOCOL, - "Rejecting INTRODUCE1 on non-OR or non-edge circuit %d.", - circ->p_circ_id); + "Rejecting INTRODUCE1 on non-OR or non-edge circuit %u.", + (unsigned)circ->p_circ_id); goto err; } @@ -155,9 +155,9 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, */ if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+ DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) { - log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %d; " + log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %u; " "responding with nack.", - circ->p_circ_id); + (unsigned)circ->p_circ_id); goto err; } @@ -168,17 +168,17 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, intro_circ = circuit_get_intro_point((char*)request); if (!intro_circ) { log_info(LD_REND, - "No intro circ found for INTRODUCE1 cell (%s) from circuit %d; " + "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; " "responding with nack.", - safe_str(serviceid), circ->p_circ_id); + safe_str(serviceid), (unsigned)circ->p_circ_id); goto err; } log_info(LD_REND, "Sending introduction request for service %s " - "from circ %d to circ %d", - safe_str(serviceid), circ->p_circ_id, - intro_circ->p_circ_id); + "from circ %u to circ %u", + safe_str(serviceid), (unsigned)circ->p_circ_id, + (unsigned)intro_circ->p_circ_id); /* Great. Now we just relay the cell down the circuit. */ if (relay_send_command_from_edge(0, TO_CIRCUIT(intro_circ), @@ -221,8 +221,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, char hexid[9]; int reason = END_CIRC_REASON_TORPROTOCOL; - log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %d", - circ->p_circ_id); + log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u", + (unsigned)circ->p_circ_id); if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_warn(LD_PROTOCOL, @@ -256,8 +256,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, base16_encode(hexid,9,(char*)request,4); log_info(LD_REND, - "Established rendezvous point on circuit %d for cookie %s", - circ->p_circ_id, hexid); + "Established rendezvous point on circuit %u for cookie %s", + (unsigned)circ->p_circ_id, hexid); return 0; err: @@ -279,16 +279,16 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_info(LD_REND, - "Tried to complete rendezvous on non-OR or non-edge circuit %d.", - circ->p_circ_id); + "Tried to complete rendezvous on non-OR or non-edge circuit %u.", + (unsigned)circ->p_circ_id); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } if (request_len != REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %d.", - (int)request_len, circ->p_circ_id); + "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.", + (int)request_len, (unsigned)circ->p_circ_id); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } @@ -296,8 +296,8 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, base16_encode(hexid, sizeof(hexid), (const char*)request, 4); log_info(LD_REND, - "Got request for rendezvous from circuit %d to cookie %s.", - circ->p_circ_id, hexid); + "Got request for rendezvous from circuit %u to cookie %s.", + (unsigned)circ->p_circ_id, hexid); rend_circ = circuit_get_rendezvous((char*)request); if (!rend_circ) { @@ -314,15 +314,15 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, (char*)(request+REND_COOKIE_LEN), request_len-REND_COOKIE_LEN, NULL)) { log_warn(LD_GENERAL, - "Unable to send RENDEZVOUS2 cell to client on circuit %d.", - rend_circ->p_circ_id); + "Unable to send RENDEZVOUS2 cell to client on circuit %u.", + (unsigned)rend_circ->p_circ_id); goto err; } /* Join the circuits. */ log_info(LD_REND, - "Completing rendezvous: circuit %d joins circuit %d (cookie %s)", - circ->p_circ_id, rend_circ->p_circ_id, hexid); + "Completing rendezvous: circuit %u joins circuit %u (cookie %s)", + (unsigned)circ->p_circ_id, (unsigned)rend_circ->p_circ_id, hexid); circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED); circuit_change_purpose(TO_CIRCUIT(rend_circ), diff --git a/src/or/rendservice.c b/src/or/rendservice.c index a066e02024..a8f63ddf66 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1126,8 +1126,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, /* Do some initial validation and logging before we parse the cell */ if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) { log_warn(LD_PROTOCOL, - "Got an INTRODUCE2 over a non-introduction circuit %d.", - circuit->base_.n_circ_id); + "Got an INTRODUCE2 over a non-introduction circuit %u.", + (unsigned) circuit->base_.n_circ_id); goto err; } @@ -1161,8 +1161,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, goto err; } - log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.", - escaped(serviceid), circuit->base_.n_circ_id); + log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %u.", + escaped(serviceid), (unsigned)circuit->base_.n_circ_id); /* use intro key instead of service key. */ intro_key = circuit->intro_key; @@ -1177,7 +1177,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (!parsed_req) { goto log_error; } else if (err_msg) { - log_info(LD_REND, "%s on circ %d.", err_msg, circuit->base_.n_circ_id); + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); tor_free(err_msg); } @@ -1187,7 +1188,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (result < 0) { goto log_error; } else if (err_msg) { - log_info(LD_REND, "%s on circ %d.", err_msg, circuit->base_.n_circ_id); + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); tor_free(err_msg); } @@ -1223,7 +1225,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (result < 0) { goto log_error; } else if (err_msg) { - log_info(LD_REND, "%s on circ %d.", err_msg, circuit->base_.n_circ_id); + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); tor_free(err_msg); } @@ -1233,7 +1236,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (result < 0) { goto log_error; } else if (err_msg) { - log_info(LD_REND, "%s on circ %d.", err_msg, circuit->base_.n_circ_id); + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); tor_free(err_msg); } @@ -1243,7 +1247,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (result < 0) { goto log_error; } else if (err_msg) { - log_info(LD_REND, "%s on circ %d.", err_msg, circuit->base_.n_circ_id); + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); tor_free(err_msg); } stage_descr = NULL; @@ -1393,7 +1398,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, } } - log_warn(LD_REND, "%s on circ %d", err_msg, circuit->base_.n_circ_id); + log_warn(LD_REND, "%s on circ %u", err_msg, + (unsigned)circuit->base_.n_circ_id); err: status = -1; if (dh) crypto_dh_free(dh); @@ -2417,8 +2423,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) service = rend_service_get_by_pk_digest( circuit->rend_data->rend_pk_digest); if (!service) { - log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.", - serviceid, circuit->base_.n_circ_id); + log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %u.", + serviceid, (unsigned)circuit->base_.n_circ_id); reason = END_CIRC_REASON_NOSUCHSERVICE; goto err; } @@ -2461,8 +2467,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) } log_info(LD_REND, - "Established circuit %d as introduction point for service %s", - circuit->base_.n_circ_id, serviceid); + "Established circuit %u as introduction point for service %s", + (unsigned)circuit->base_.n_circ_id, serviceid); /* Use the intro key instead of the service key in ESTABLISH_INTRO. */ intro_key = circuit->intro_key; @@ -2496,8 +2502,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) RELAY_COMMAND_ESTABLISH_INTRO, buf, len, circuit->cpath->prev)<0) { log_info(LD_GENERAL, - "Couldn't send introduction request for service %s on circuit %d", - serviceid, circuit->base_.n_circ_id); + "Couldn't send introduction request for service %s on circuit %u", + serviceid, (unsigned)circuit->base_.n_circ_id); reason = END_CIRC_REASON_INTERNAL; goto err; } @@ -2539,8 +2545,8 @@ rend_service_intro_established(origin_circuit_t *circuit, service = rend_service_get_by_pk_digest( circuit->rend_data->rend_pk_digest); if (!service) { - log_warn(LD_REND, "Unknown service on introduction circuit %d.", - circuit->base_.n_circ_id); + log_warn(LD_REND, "Unknown service on introduction circuit %u.", + (unsigned)circuit->base_.n_circ_id); goto err; } service->desc_is_dirty = time(NULL); @@ -2549,8 +2555,8 @@ rend_service_intro_established(origin_circuit_t *circuit, base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1, circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); log_info(LD_REND, - "Received INTRO_ESTABLISHED cell on circuit %d for service %s", - circuit->base_.n_circ_id, serviceid); + "Received INTRO_ESTABLISHED cell on circuit %u for service %s", + (unsigned)circuit->base_.n_circ_id, serviceid); /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully * used the circ */ @@ -2597,9 +2603,9 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); log_info(LD_REND, - "Done building circuit %d to rendezvous with " + "Done building circuit %u to rendezvous with " "cookie %s for service %s", - circuit->base_.n_circ_id, hexcookie, serviceid); + (unsigned)circuit->base_.n_circ_id, hexcookie, serviceid); /* Clear the 'in-progress HS circ has timed out' flag for * consistency with what happens on the client side; this line has @@ -3339,8 +3345,8 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, circ->rend_data->rend_pk_digest); if (!service) { log_warn(LD_REND, "Couldn't find any service associated with pk %s on " - "rendezvous circuit %d; closing.", - serviceid, circ->base_.n_circ_id); + "rendezvous circuit %u; closing.", + serviceid, (unsigned)circ->base_.n_circ_id); return -1; } matching_ports = smartlist_new(); diff --git a/src/or/router.c b/src/or/router.c index e5d53e0215..b9d5b7b54a 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -650,6 +650,7 @@ router_initialize_tls_context(void) { unsigned int flags = 0; const or_options_t *options = get_options(); + int lifetime = options->SSLKeyLifetime; if (public_server_mode(options)) flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER; if (options->TLSECGroup) { @@ -658,12 +659,28 @@ router_initialize_tls_context(void) else if (!strcasecmp(options->TLSECGroup, "P224")) flags |= TOR_TLS_CTX_USE_ECDHE_P224; } + if (!lifetime) { /* we should guess a good ssl cert lifetime */ + /* choose between 5 and 365 days, and round to the day */ + lifetime = 5*24*3600 + crypto_rand_int(361*24*3600); + lifetime -= lifetime % (24*3600); + + if (crypto_rand_int(2)) { + /* Half the time we expire at midnight, and half the time we expire + * one second before midnight. (Some CAs wobble their expiry times a + * bit in practice, perhaps to reduce collision attacks; see ticket + * 8443 for details about observed certs in the wild.) */ + lifetime--; + } + } + + /* It's ok to pass lifetime in as an unsigned int, since + * config_parse_interval() checked it. */ return tor_tls_context_init(flags, get_tlsclient_identity_key(), - server_mode(get_options()) ? + server_mode(options) ? get_server_identity_key() : NULL, - MAX_SSL_KEY_LIFETIME_ADVERTISED); + (unsigned int)lifetime); } /** Initialize all OR private keys, and the TLS context, as necessary. @@ -2936,23 +2953,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 7a093019ff..93ca22a933 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..6ed168e553 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. */ @@ -1817,7 +1793,7 @@ compute_weighted_bandwidths(const smartlist_t *sl, "old router selection algorithm."); return -1; } - this_bw = kb_to_bytes(node->rs->bandwidth); + this_bw = kb_to_bytes(node->rs->bandwidth_kb); } else if (node->ri) { /* bridge or other descriptor not in our consensus */ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri); @@ -1968,7 +1944,7 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl, is_guard = node->is_possible_guard; if (node->rs) { if (node->rs->has_bandwidth) { - this_bw = kb_to_bytes(node->rs->bandwidth); + this_bw = kb_to_bytes(node->rs->bandwidth_kb); } else { /* guess */ is_known = 0; } @@ -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 dfbd2d54e6..890d59660a 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1520,7 +1520,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, extrainfo = tor_malloc_zero(sizeof(extrainfo_t)); extrainfo->cache_info.is_extrainfo = 1; if (cache_copy) - extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s); + extrainfo->cache_info.signed_descriptor_body = tor_memdup_nulterm(s,end-s); extrainfo->cache_info.signed_descriptor_len = end-s; memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN); @@ -1979,7 +1979,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]); @@ -1992,9 +1992,10 @@ routerstatus_parse_entry_from_string(memarea_t *area, for (i=0; i < tok->n_args; ++i) { if (!strcmpstart(tok->args[i], "Bandwidth=")) { int ok; - rs->bandwidth = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, - 10, 0, UINT32_MAX, - &ok, NULL); + rs->bandwidth_kb = + (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, + 10, 0, UINT32_MAX, + &ok, NULL); if (!ok) { log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i])); goto err; @@ -2002,7 +2003,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->has_bandwidth = 1; } else if (!strcmpstart(tok->args[i], "Measured=") && vote_rs) { int ok; - vote_rs->measured_bw = + vote_rs->measured_bw_kb = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, 10, 0, UINT32_MAX, &ok, NULL); if (!ok) { @@ -2056,7 +2057,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); } @@ -2283,7 +2284,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; @@ -2369,24 +2370,31 @@ 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) { - D += rs->bandwidth; - Gtotal += Wgd*rs->bandwidth; - Mtotal += Wmd*rs->bandwidth; - Etotal += Wed*rs->bandwidth; - } else if (rs->is_exit) { - E += rs->bandwidth; - Mtotal += Wme*rs->bandwidth; - Etotal += Wee*rs->bandwidth; + T += rs->bandwidth_kb; + if (is_exit && rs->is_possible_guard) { + D += rs->bandwidth_kb; + Gtotal += Wgd*rs->bandwidth_kb; + Mtotal += Wmd*rs->bandwidth_kb; + Etotal += Wed*rs->bandwidth_kb; + } else if (is_exit) { + E += rs->bandwidth_kb; + Mtotal += Wme*rs->bandwidth_kb; + Etotal += Wee*rs->bandwidth_kb; } else if (rs->is_possible_guard) { - G += rs->bandwidth; - Gtotal += Wgg*rs->bandwidth; - Mtotal += Wmg*rs->bandwidth; + G += rs->bandwidth_kb; + Gtotal += Wgg*rs->bandwidth_kb; + Mtotal += Wmg*rs->bandwidth_kb; } else { - M += rs->bandwidth; - Mtotal += Wmm*rs->bandwidth; + M += rs->bandwidth_kb; + Mtotal += Wmm*rs->bandwidth_kb; } } else { log_warn(LD_BUG, "Missing consensus bandwidth for router %s", @@ -3939,8 +3947,15 @@ tokenize_string(memarea_t *area, tor_assert(area); s = &start; - if (!end) + if (!end) { end = start+strlen(start); + } else { + /* it's only meaningful to check for nuls if we got an end-of-string ptr */ + if (memchr(start, '\0', end-start)) { + log_warn(LD_DIR, "parse error: internal NUL character."); + return -1; + } + } for (i = 0; i < NIL_; ++i) counts[i] = 0; @@ -4274,7 +4289,7 @@ microdescs_parse_from_string(const char *s, const char *eos, md->bodylen = start_of_next_microdesc - cp; if (copy_body) - md->body = tor_strndup(cp, md->bodylen); + md->body = tor_memdup_nulterm(cp, md->bodylen); else md->body = (char*)cp; md->off = cp - start; diff --git a/src/or/routerparse.h b/src/or/routerparse.h index a5f4e370fa..c65cdc996c 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -55,7 +55,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/routerset.c b/src/or/routerset.c index 1eca5b6f6f..2e41f7f6c4 100644 --- a/src/or/routerset.c +++ b/src/or/routerset.c @@ -141,7 +141,7 @@ routerset_parse(routerset_t *target, const char *s, const char *description) log_debug(LD_CONFIG, "Adding address %s to %s", nick, description); smartlist_add(target->policies, p); } else { - log_warn(LD_CONFIG, "Entry '%s' in %s is misformed.", nick, + log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick, description); r = -1; tor_free(nick); diff --git a/src/or/status.c b/src/or/status.c index 126167dcb9..d239e6ee75 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -14,6 +14,7 @@ #include "router.h" #include "circuitlist.h" #include "main.h" +#include "hibernate.h" /** Return the total number of circuits. */ static int @@ -85,11 +86,13 @@ log_heartbeat(time_t now) char *bw_rcvd = NULL; char *uptime = NULL; const routerinfo_t *me; + double r = tls_get_write_overhead_ratio(); + const int hibernating = we_are_hibernating(); const or_options_t *options = get_options(); (void)now; - if (public_server_mode(options)) { + if (public_server_mode(options) && !hibernating) { /* Let's check if we are in the current cached consensus. */ if (!(me = router_get_my_routerinfo())) return -1; /* Something stinks, we won't even attempt this. */ @@ -104,14 +107,20 @@ log_heartbeat(time_t now) bw_sent = bytes_to_usage(get_bytes_written()); log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d " - "circuits open. I've sent %s and received %s.", - uptime, count_circuits(),bw_sent,bw_rcvd); + "circuits open. I've sent %s and received %s.%s", + uptime, count_circuits(),bw_sent,bw_rcvd, + hibernating?" We are currently hibernating.":""); - if (stats_n_data_cells_packaged) + if (stats_n_data_cells_packaged && !hibernating) log_notice(LD_HEARTBEAT, "Average packaged cell fullness: %2.3f%%", 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/tor_main.c b/src/or/tor_main.c index 806b5ebb38..05dc0bf0bf 100644 --- a/src/or/tor_main.c +++ b/src/or/tor_main.c @@ -3,9 +3,9 @@ * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -/** String describing which Tor subversion repository version the source was - * built from. This string is generated by a bit of shell kludging int - * src/or/Makefile.am, and is usually right. +/** String describing which Tor Git repository version the source was + * built from. This string is generated by a bit of shell kludging in + * src/or/include.am, and is usually right. */ const char tor_git_revision[] = #ifndef _MSC_VER diff --git a/src/or/transports.c b/src/or/transports.c index 647b293168..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 @@ -339,12 +335,12 @@ transport_add_from_config(const tor_addr_t *addr, uint16_t port, transport_free(t); return -1; case 1: - log_info(LD_GENERAL, "Succesfully registered transport %s at %s.", + log_info(LD_GENERAL, "Successfully registered transport %s at %s.", t->name, fmt_addrport(&t->addr, t->port)); transport_free(t); /* falling */ return 0; case 0: - log_info(LD_GENERAL, "Succesfully registered transport %s at %s.", + log_info(LD_GENERAL, "Successfully registered transport %s at %s.", t->name, fmt_addrport(&t->addr, t->port)); return 0; } @@ -676,10 +672,10 @@ register_client_proxy(const managed_proxy_t *mp) transport_free(transport_tmp); break; case 0: - log_info(LD_GENERAL, "Succesfully registered transport %s", t->name); + log_info(LD_GENERAL, "Successfully registered transport %s", t->name); break; case 1: - log_info(LD_GENERAL, "Succesfully registered transport %s", t->name); + log_info(LD_GENERAL, "Successfully registered transport %s", t->name); transport_free(transport_tmp); break; } |