diff options
Diffstat (limited to 'src/or/circuitbuild.c')
-rw-r--r-- | src/or/circuitbuild.c | 734 |
1 files changed, 302 insertions, 432 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index f8521c5cf..b16dab2cc 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -12,10 +12,13 @@ #define CIRCUIT_PRIVATE #include "or.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" +#include "command.h" #include "config.h" +#include "confparse.h" #include "connection.h" #include "connection_edge.h" #include "connection_or.h" @@ -32,6 +35,8 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "routerset.h" +#include "statefile.h" #include "crypto.h" #undef log #include <math.h> @@ -122,6 +127,9 @@ static int unit_tests = 0; /********* END VARIABLES ************/ +static channel_t * channel_connect_for_circuit(const tor_addr_t *addr, + uint16_t port, + const char *id_digest); static int circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, const char *payload); static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit); @@ -138,6 +146,22 @@ static void bridge_free(bridge_info_t *bridge); static int entry_guard_inc_first_hop_count(entry_guard_t *guard); static void pathbias_count_success(origin_circuit_t *circ); +/** This function tries to get a channel to the specified endpoint, + * and then calls command_setup_channel() to give it the right + * callbacks. + */ +static channel_t * +channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port, + const char *id_digest) +{ + channel_t *chan; + + chan = channel_connect(addr, port, id_digest); + if (chan) command_setup_channel(chan); + + return chan; +} + /** * This function decides if CBT learning should be disabled. It returns * true if one or more of the following four conditions are met: @@ -1680,26 +1704,29 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt) * Return it, or 0 if can't get a unique circ_id. */ static circid_t -get_unique_circ_id_by_conn(or_connection_t *conn) +get_unique_circ_id_by_chan(channel_t *chan) { circid_t test_circ_id; circid_t attempts=0; circid_t high_bit; - tor_assert(conn); - if (conn->circ_id_type == CIRC_ID_TYPE_NEITHER) { - log_warn(LD_BUG, "Trying to pick a circuit ID for a connection from " + tor_assert(chan); + + if (chan->circ_id_type == CIRC_ID_TYPE_NEITHER) { + log_warn(LD_BUG, + "Trying to pick a circuit ID for a connection from " "a client with no identity."); return 0; } - high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; + high_bit = + (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; do { /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a * circID such that (high_bit|test_circ_id) is not already used. */ - test_circ_id = conn->next_circ_id++; + test_circ_id = chan->next_circ_id++; if (test_circ_id == 0 || test_circ_id >= 1<<15) { test_circ_id = 1; - conn->next_circ_id = 2; + chan->next_circ_id = 2; } if (++attempts > 1<<15) { /* Make sure we don't loop forever if all circ_id's are used. This @@ -1709,7 +1736,7 @@ get_unique_circ_id_by_conn(or_connection_t *conn) return 0; } test_circ_id |= high_bit; - } while (circuit_id_in_use_on_orconn(test_circ_id, conn)); + } while (circuit_id_in_use_on_channel(test_circ_id, chan)); return test_circ_id; } @@ -1736,8 +1763,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) circ->build_state->is_internal ? "internal" : "exit", circ->build_state->need_uptime ? " (high-uptime)" : "", circ->build_state->desired_path_len, - circ->_base.state == CIRCUIT_STATE_OPEN ? "" : ", last hop ", - circ->_base.state == CIRCUIT_STATE_OPEN ? "" : + circ->base_.state == CIRCUIT_STATE_OPEN ? "" : ", last hop ", + circ->base_.state == CIRCUIT_STATE_OPEN ? "" : (nickname?nickname:"*unnamed*")); } @@ -1888,9 +1915,9 @@ onion_populate_cpath(origin_circuit_t *circ) origin_circuit_t * origin_circuit_init(uint8_t purpose, int flags) { - /* sets circ->p_circ_id and circ->p_conn */ + /* sets circ->p_circ_id and circ->p_chan */ origin_circuit_t *circ = origin_circuit_new(); - circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT); + circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_CHAN_WAIT); circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); circ->build_state->onehop_tunnel = ((flags & CIRCLAUNCH_ONEHOP_TUNNEL) ? 1 : 0); @@ -1900,7 +1927,7 @@ origin_circuit_init(uint8_t purpose, int flags) ((flags & CIRCLAUNCH_NEED_CAPACITY) ? 1 : 0); circ->build_state->is_internal = ((flags & CIRCLAUNCH_IS_INTERNAL) ? 1 : 0); - circ->_base.purpose = purpose; + circ->base_.purpose = purpose; return circ; } @@ -1942,7 +1969,7 @@ int circuit_handle_first_hop(origin_circuit_t *circ) { crypt_path_t *firsthop; - or_connection_t *n_conn; + channel_t *n_chan; int err_reason = 0; const char *msg = NULL; int should_launch = 0; @@ -1952,29 +1979,30 @@ circuit_handle_first_hop(origin_circuit_t *circ) tor_assert(firsthop->extend_info); /* now see if we're already connected to the first OR in 'route' */ - log_debug(LD_CIRC,"Looking for firsthop '%s:%u'", - fmt_addr(&firsthop->extend_info->addr), - firsthop->extend_info->port); + log_debug(LD_CIRC,"Looking for firsthop '%s'", + fmt_addrport(&firsthop->extend_info->addr, + firsthop->extend_info->port)); - n_conn = connection_or_get_for_extend(firsthop->extend_info->identity_digest, - &firsthop->extend_info->addr, - &msg, - &should_launch); + n_chan = channel_get_for_extend(firsthop->extend_info->identity_digest, + &firsthop->extend_info->addr, + &msg, + &should_launch); - if (!n_conn) { + if (!n_chan) { /* not currently connected in a useful way. */ log_info(LD_CIRC, "Next router is %s: %s", safe_str_client(extend_info_describe(firsthop->extend_info)), msg?msg:"???"); - circ->_base.n_hop = extend_info_dup(firsthop->extend_info); + circ->base_.n_hop = extend_info_dup(firsthop->extend_info); if (should_launch) { if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); - n_conn = connection_or_connect(&firsthop->extend_info->addr, - firsthop->extend_info->port, - firsthop->extend_info->identity_digest); - if (!n_conn) { /* connect failed, forget the whole thing */ + n_chan = channel_connect_for_circuit( + &firsthop->extend_info->addr, + firsthop->extend_info->port, + firsthop->extend_info->identity_digest); + if (!n_chan) { /* connect failed, forget the whole thing */ log_info(LD_CIRC,"connect to firsthop failed. Closing."); return -END_CIRC_REASON_CONNECTFAILED; } @@ -1982,13 +2010,13 @@ circuit_handle_first_hop(origin_circuit_t *circ) log_debug(LD_CIRC,"connecting in progress (or finished). Good."); /* return success. The onion/circuit/etc will be taken care of - * automatically (may already have been) whenever n_conn reaches + * automatically (may already have been) whenever n_chan reaches * OR_CONN_STATE_OPEN. */ return 0; } else { /* it's already open. use it. */ - tor_assert(!circ->_base.n_hop); - circ->_base.n_conn = n_conn; + tor_assert(!circ->base_.n_hop); + circ->base_.n_chan = n_chan; log_debug(LD_CIRC,"Conn open. Delivering first onion skin."); if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) { log_info(LD_CIRC,"circuit_send_next_onion_skin failed."); @@ -2004,48 +2032,49 @@ circuit_handle_first_hop(origin_circuit_t *circ) * Status is 1 if connect succeeded, or 0 if connect failed. */ void -circuit_n_conn_done(or_connection_t *or_conn, int status) +circuit_n_chan_done(channel_t *chan, int status) { smartlist_t *pending_circs; int err_reason = 0; - log_debug(LD_CIRC,"or_conn to %s/%s, status=%d", - or_conn->nickname ? or_conn->nickname : "NULL", - or_conn->_base.address, status); + tor_assert(chan); + + log_debug(LD_CIRC,"chan to %s/%s, status=%d", + chan->nickname ? chan->nickname : "NULL", + channel_get_canonical_remote_descr(chan), status); pending_circs = smartlist_new(); - circuit_get_all_pending_on_or_conn(pending_circs, or_conn); + circuit_get_all_pending_on_channel(pending_circs, chan); SMARTLIST_FOREACH_BEGIN(pending_circs, circuit_t *, circ) { /* These checks are redundant wrt get_all_pending_on_or_conn, but I'm * leaving them in in case it's possible for the status of a circuit to * change as we're going down the list. */ - if (circ->marked_for_close || circ->n_conn || !circ->n_hop || - circ->state != CIRCUIT_STATE_OR_WAIT) + if (circ->marked_for_close || circ->n_chan || !circ->n_hop || + circ->state != CIRCUIT_STATE_CHAN_WAIT) continue; if (tor_digest_is_zero(circ->n_hop->identity_digest)) { /* Look at addr/port. This is an unkeyed connection. */ - if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) || - circ->n_hop->port != or_conn->_base.port) + if (!channel_matches_extend_info(chan, circ->n_hop)) continue; } else { /* We expected a key. See if it's the right one. */ - if (tor_memneq(or_conn->identity_digest, + if (tor_memneq(chan->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } - if (!status) { /* or_conn failed; close circ */ - log_info(LD_CIRC,"or_conn failed. Closing circ."); - circuit_mark_for_close(circ, END_CIRC_REASON_OR_CONN_CLOSED); + if (!status) { /* chan failed; close circ */ + log_info(LD_CIRC,"Channel failed; closing circ."); + circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED); continue; } log_debug(LD_CIRC, "Found circ, sending create cell."); /* circuit_deliver_create_cell will set n_circ_id and add us to - * orconn_circuid_circuit_map, so we don't need to call - * set_circid_orconn here. */ - circ->n_conn = or_conn; + * chan_circuid_circuit_map, so we don't need to call + * set_circid_chan here. */ + circ->n_chan = chan; extend_info_free(circ->n_hop); circ->n_hop = NULL; @@ -2061,13 +2090,13 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) } } else { /* pull the create cell out of circ->onionskin, and send it */ - tor_assert(circ->n_conn_onionskin); + tor_assert(circ->n_chan_onionskin); if (circuit_deliver_create_cell(circ,CELL_CREATE, - circ->n_conn_onionskin)<0) { + circ->n_chan_onionskin)<0) { circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); continue; } - tor_free(circ->n_conn_onionskin); + tor_free(circ->n_chan_onionskin); circuit_set_state(circ, CIRCUIT_STATE_OPEN); } } @@ -2076,7 +2105,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) smartlist_free(pending_circs); } -/** Find a new circid that isn't currently in use on the circ->n_conn +/** Find a new circid that isn't currently in use on the circ->n_chan * for the outgoing * circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b> * (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b> @@ -2091,29 +2120,29 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, circid_t id; tor_assert(circ); - tor_assert(circ->n_conn); + tor_assert(circ->n_chan); tor_assert(payload); tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST); - id = get_unique_circ_id_by_conn(circ->n_conn); + id = get_unique_circ_id_by_chan(circ->n_chan); if (!id) { log_warn(LD_CIRC,"failed to get unique circID."); return -1; } log_debug(LD_CIRC,"Chosen circID %u.", id); - circuit_set_n_circid_orconn(circ, id, circ->n_conn); + circuit_set_n_circid_chan(circ, id, circ->n_chan); memset(&cell, 0, sizeof(cell_t)); cell.command = cell_type; cell.circ_id = circ->n_circ_id; memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN); - append_cell_to_circuit_queue(circ, circ->n_conn, &cell, + append_cell_to_circuit_queue(circ, circ->n_chan, &cell, CELL_DIRECTION_OUT, 0); if (CIRCUIT_IS_ORIGIN(circ)) { /* mark it so it gets better rate limiting treatment. */ - circ->n_conn->client_used = time(NULL); + channel_timestamp_client(circ->n_chan); } return 0; @@ -2215,7 +2244,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) else control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0); - node = node_get_by_id(circ->_base.n_conn->identity_digest); + node = node_get_by_id(circ->base_.n_chan->identity_digest); fast = should_use_create_fast_for_circuit(circ); if (!fast) { /* We are an OR and we know the right onion key: we should @@ -2252,7 +2281,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) node ? node_describe(node) : "<unnamed>"); } else { tor_assert(circ->cpath->state == CPATH_STATE_OPEN); - tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING); + tor_assert(circ->base_.state == CIRCUIT_STATE_BUILDING); log_debug(LD_CIRC,"starting to send subsequent skin."); hop = onion_next_hop_in_cpath(circ->cpath); if (!hop) { @@ -2262,7 +2291,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) struct timeval end; long timediff; tor_gettimeofday(&end); - timediff = tv_mdiff(&circ->_base.timestamp_created, &end); + timediff = tv_mdiff(&circ->base_.timestamp_created, &end); /* * If the circuit build time is much greater than we would have cut @@ -2272,8 +2301,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) if (timediff < 0 || timediff > 2*circ_times.close_ms+1000) { log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. " "Assuming clock jump. Purpose %d (%s)", timediff, - circ->_base.purpose, - circuit_purpose_to_string(circ->_base.purpose)); + circ->base_.purpose, + circuit_purpose_to_string(circ->base_.purpose)); } else if (!circuit_build_times_disabled()) { /* Only count circuit times if the network is live */ if (circuit_build_times_network_check_live(&circ_times)) { @@ -2281,7 +2310,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) circuit_build_times_set_timeout(&circ_times); } - if (circ->_base.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { circuit_build_times_network_circ_success(&circ_times); } } @@ -2314,7 +2343,7 @@ circuit_send_next_onion_skin(origin_circuit_t *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) + if (circ->base_.purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); return 0; } @@ -2383,7 +2412,7 @@ circuit_note_clock_jumped(int seconds_elapsed) int circuit_extend(cell_t *cell, circuit_t *circ) { - or_connection_t *n_conn; + channel_t *n_chan; relay_header_t rh; char *onionskin; char *id_digest=NULL; @@ -2393,9 +2422,9 @@ circuit_extend(cell_t *cell, circuit_t *circ) const char *msg = NULL; int should_launch = 0; - if (circ->n_conn) { + if (circ->n_chan) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "n_conn already set. Bug/attack. Closing."); + "n_chan already set. Bug/attack. Closing."); return -1; } if (circ->n_hop) { @@ -2454,52 +2483,54 @@ circuit_extend(cell_t *cell, circuit_t *circ) /* Next, check if we're being asked to connect to the hop that the * extend cell came from. There isn't any reason for that, and it can * assist circular-path attacks. */ - if (tor_memeq(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest, - DIGEST_LEN)) { + if (tor_memeq(id_digest, + TO_OR_CIRCUIT(circ)->p_chan->identity_digest, + DIGEST_LEN)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend back to the previous hop."); return -1; } - n_conn = connection_or_get_for_extend(id_digest, - &n_addr, - &msg, - &should_launch); + n_chan = channel_get_for_extend(id_digest, + &n_addr, + &msg, + &should_launch); - if (!n_conn) { - log_debug(LD_CIRC|LD_OR,"Next router (%s:%d): %s", - fmt_addr(&n_addr), (int)n_port, msg?msg:"????"); + if (!n_chan) { + log_debug(LD_CIRC|LD_OR,"Next router (%s): %s", + fmt_addrport(&n_addr, n_port), msg?msg:"????"); - circ->n_hop = extend_info_alloc(NULL /*nickname*/, + circ->n_hop = extend_info_new(NULL /*nickname*/, id_digest, NULL /*onion_key*/, &n_addr, n_port); - circ->n_conn_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN); - memcpy(circ->n_conn_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN); - circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT); + circ->n_chan_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN); + memcpy(circ->n_chan_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN); + circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT); if (should_launch) { /* we should try to open a connection */ - n_conn = connection_or_connect(&n_addr, n_port, id_digest); - if (!n_conn) { - log_info(LD_CIRC,"Launching n_conn failed. Closing circuit."); + n_chan = channel_connect_for_circuit(&n_addr, n_port, id_digest); + if (!n_chan) { + log_info(LD_CIRC,"Launching n_chan failed. Closing circuit."); circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); return 0; } log_debug(LD_CIRC,"connecting in progress (or finished). Good."); } /* return success. The onion/circuit/etc will be taken care of - * automatically (may already have been) whenever n_conn reaches + * automatically (may already have been) whenever n_chan reaches * OR_CONN_STATE_OPEN. */ return 0; } tor_assert(!circ->n_hop); /* Connection is already established. */ - circ->n_conn = n_conn; - log_debug(LD_CIRC,"n_conn is %s:%u", - n_conn->_base.address,n_conn->_base.port); + circ->n_chan = n_chan; + log_debug(LD_CIRC, + "n_chan is %s", + channel_get_canonical_remote_descr(n_chan)); if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0) return -1; @@ -2608,12 +2639,12 @@ pathbias_get_scale_threshold(const or_options_t *options) static int pathbias_get_scale_factor(const or_options_t *options) { -#define DFLT_PATH_BIAS_SCALE_FACTOR 4 +#define DFLT_PATH_BIAS_SCALE_FACTOR 2 if (options->PathBiasScaleFactor >= 1) return options->PathBiasScaleFactor; else return networkstatus_get_param(NULL, "pb_scalefactor", - DFLT_PATH_BIAS_SCALE_THRESHOLD, 1, INT32_MAX); + DFLT_PATH_BIAS_SCALE_FACTOR, 1, INT32_MAX); } static const char * @@ -2645,6 +2676,14 @@ pathbias_count_first_hop(origin_circuit_t *circ) RATELIM_INIT(FIRST_HOP_NOTICE_INTERVAL); char *rate_msg = NULL; + /* We can't do path bias accounting without entry guards. + * Testing and controller circuits also have no guards. */ + if (get_options()->UseEntryGuards == 0 || + circ->base_.purpose == CIRCUIT_PURPOSE_TESTING || + circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER) { + return 0; + } + /* Completely ignore one hop circuits */ if (circ->build_state->onehop_tunnel || circ->build_state->desired_path_len == 1) { @@ -2653,13 +2692,13 @@ pathbias_count_first_hop(origin_circuit_t *circ) !circ->build_state->onehop_tunnel) { if ((rate_msg = rate_limit_log(&first_hop_notice_limit, approx_time()))) { - log_info(LD_BUG, + log_notice(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, pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2677,8 +2716,8 @@ pathbias_count_first_hop(origin_circuit_t *circ) "Opened circuit is in strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2688,8 +2727,8 @@ pathbias_count_first_hop(origin_circuit_t *circ) if (!circ->has_opened) { entry_guard_t *guard; - guard = entry_guard_get_by_id_digest( - circ->_base.n_conn->identity_digest); + guard = + entry_guard_get_by_id_digest(circ->base_.n_chan->identity_digest); if (guard) { if (circ->path_state == PATH_STATE_NEW_CIRC) { circ->path_state = PATH_STATE_DID_FIRST_HOP; @@ -2705,8 +2744,8 @@ pathbias_count_first_hop(origin_circuit_t *circ) "Unopened circuit has strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2717,8 +2756,8 @@ pathbias_count_first_hop(origin_circuit_t *circ) log_info(LD_BUG, "Unopened circuit has no known guard. " "Circuit is a %s currently %s.%s", - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2734,8 +2773,8 @@ pathbias_count_first_hop(origin_circuit_t *circ) "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), circ->cpath->state, circ->has_opened, - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2759,6 +2798,15 @@ pathbias_count_success(origin_circuit_t *circ) static ratelim_t success_notice_limit = RATELIM_INIT(SUCCESS_NOTICE_INTERVAL); char *rate_msg = NULL; + entry_guard_t *guard = NULL; + + /* We can't do path bias accounting without entry guards. + * Testing and controller circuits also have no guards. */ + if (get_options()->UseEntryGuards == 0 || + circ->base_.purpose == CIRCUIT_PURPOSE_TESTING || + circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER) { + return; + } /* Ignore one hop circuits */ if (circ->build_state->onehop_tunnel || @@ -2768,13 +2816,13 @@ pathbias_count_success(origin_circuit_t *circ) !circ->build_state->onehop_tunnel) { if ((rate_msg = rate_limit_log(&success_notice_limit, approx_time()))) { - log_info(LD_BUG, + log_notice(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, pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2785,8 +2833,8 @@ pathbias_count_success(origin_circuit_t *circ) /* Don't count cannibalized/reused circs for path bias */ if (!circ->has_opened) { - entry_guard_t *guard = - entry_guard_get_by_id_digest(circ->_base.n_conn->identity_digest); + guard = + entry_guard_get_by_id_digest(circ->base_.n_chan->identity_digest); if (guard) { if (circ->path_state == PATH_STATE_DID_FIRST_HOP) { @@ -2803,27 +2851,30 @@ pathbias_count_success(origin_circuit_t *circ) "Succeeded circuit is in strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } } if (guard->first_hops < guard->circuit_successes) { - log_info(LD_BUG, "Unexpectedly high circuit_successes (%u/%u) " + log_notice(LD_BUG, "Unexpectedly high circuit_successes (%u/%u) " "for guard %s=%s", guard->circuit_successes, guard->first_hops, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); } - } else { + /* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to + * CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT and have no guards here. + * No need to log that case. */ + } else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { if ((rate_msg = rate_limit_log(&success_notice_limit, approx_time()))) { log_info(LD_BUG, "Completed circuit has no known guard. " "Circuit is a %s currently %s.%s", - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2836,8 +2887,8 @@ pathbias_count_success(origin_circuit_t *circ) "Opened circuit is in strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2863,9 +2914,11 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) if (guard->circuit_successes/((double)guard->first_hops) < pathbias_get_disable_rate(options)) { - log_info(LD_PROTOCOL, + /* This message is currently disabled by default. */ + log_warn(LD_PROTOCOL, "Extremely low circuit success rate %u/%u for guard %s=%s. " - "This might indicate an attack, or a bug.", + "This indicates either an overloaded guard, an attack, or " + "a bug.", guard->circuit_successes, guard->first_hops, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); @@ -2876,7 +2929,7 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) < pathbias_get_notice_rate(options) && !guard->path_bias_notice) { guard->path_bias_notice = 1; - log_info(LD_PROTOCOL, + log_notice(LD_PROTOCOL, "Low circuit success rate %u/%u for guard %s=%s.", guard->circuit_successes, guard->first_hops, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); @@ -2886,8 +2939,18 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) /* If we get a ton of circuits, just scale everything down */ if (guard->first_hops > (unsigned)pathbias_get_scale_threshold(options)) { const int scale_factor = pathbias_get_scale_factor(options); - guard->first_hops /= scale_factor; - guard->circuit_successes /= scale_factor; + /* For now, only scale if there will be no rounding error... + * XXX024: We want to switch to a real moving average for 0.2.4. */ + if ((guard->first_hops % scale_factor) == 0 && + (guard->circuit_successes % scale_factor) == 0) { + log_info(LD_PROTOCOL, + "Scaling pathbias counts to (%u/%u)/%d for guard %s=%s", + guard->circuit_successes, guard->first_hops, + scale_factor, guard->nickname, hex_str(guard->identity, + DIGEST_LEN)); + guard->first_hops /= scale_factor; + guard->circuit_successes /= scale_factor; + } } guard->first_hops++; log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s=%s", @@ -2974,7 +3037,7 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, * just give up: for circ to close, and return 0. */ int -circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer) +circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason) { // crypt_path_t *victim; // connection_t *stream; @@ -2987,7 +3050,7 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer) * just give up. */ circuit_mark_for_close(TO_CIRCUIT(circ), - END_CIRC_REASON_FLAG_REMOTE|END_CIRC_REASON_OR_CONN_CLOSED); + END_CIRC_REASON_FLAG_REMOTE|reason); return 0; #if 0 @@ -3061,12 +3124,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, circ->is_first_hop = (cell_type == CELL_CREATED_FAST); append_cell_to_circuit_queue(TO_CIRCUIT(circ), - circ->p_conn, &cell, CELL_DIRECTION_IN, 0); + circ->p_chan, &cell, CELL_DIRECTION_IN, 0); log_debug(LD_CIRC,"Finished sending '%s' cell.", circ->is_first_hop ? "created_fast" : "created"); - if (!is_local_addr(&circ->p_conn->_base.addr) && - !connection_or_nonopen_was_started_here(circ->p_conn)) { + if (!channel_is_local(circ->p_chan) && + !channel_is_outgoing(circ->p_chan)) { /* record that we could process create cells from a non-local conn * that we didn't initiate; presumably this means that create cells * can reach us too. */ @@ -3268,7 +3331,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) n_supported[i] = -1; continue; } - if (routerset_contains_node(options->_ExcludeExitNodesUnion, node)) { + if (routerset_contains_node(options->ExcludeExitNodesUnion_, node)) { n_supported[i] = -1; continue; /* user asked us not to use it, no matter what */ } @@ -3285,7 +3348,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) * we'll retry later in this function with need_update and * need_capacity set to 0. */ } - if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) { + if (!(node->is_valid || options->AllowInvalid_ & ALLOW_INVALID_EXIT)) { /* if it's invalid and we don't want it */ n_supported[i] = -1; // log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.", @@ -3371,7 +3434,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) } log_notice(LD_CIRC, "All routers are down or won't exit%s -- " "choosing a doomed exit at random.", - options->_ExcludeExitNodesUnion ? " or are Excluded" : ""); + options->ExcludeExitNodesUnion_ ? " or are Excluded" : ""); } supporting = smartlist_new(); needed_ports = circuit_get_unhandled_ports(time(NULL)); @@ -3410,7 +3473,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) log_warn(LD_CIRC, "No specified %sexit routers seem to be running: " "can't choose an exit.", - options->_ExcludeExitNodesUnion ? "non-excluded " : ""); + options->ExcludeExitNodesUnion_ ? "non-excluded " : ""); } return NULL; } @@ -3438,14 +3501,14 @@ choose_good_exit_server(uint8_t purpose, switch (purpose) { case CIRCUIT_PURPOSE_C_GENERAL: - if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE) + if (options->AllowInvalid_ & ALLOW_INVALID_MIDDLE) flags |= CRN_ALLOW_INVALID; if (is_internal) /* pick it like a middle hop */ return router_choose_random_node(NULL, options->ExcludeNodes, flags); else return choose_good_exit_server_general(need_uptime,need_capacity); case CIRCUIT_PURPOSE_C_ESTABLISH_REND: - if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS) + if (options->AllowInvalid_ & ALLOW_INVALID_RENDEZVOUS) flags |= CRN_ALLOW_INVALID; return router_choose_random_node(NULL, options->ExcludeNodes, flags); } @@ -3462,7 +3525,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) const or_options_t *options = get_options(); routerset_t *rs = options->ExcludeNodes; const char *description; - uint8_t purpose = circ->_base.purpose; + uint8_t purpose = circ->base_.purpose; if (circ->build_state->onehop_tunnel) return; @@ -3482,7 +3545,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) if (circ->build_state->is_internal) return; description = "requested exit node"; - rs = options->_ExcludeExitNodesUnion; + rs = options->ExcludeExitNodesUnion_; break; case CIRCUIT_PURPOSE_C_INTRODUCING: case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: @@ -3499,7 +3562,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) description = "chosen rendezvous point"; break; case CIRCUIT_PURPOSE_CONTROLLER: - rs = options->_ExcludeExitNodesUnion; + rs = options->ExcludeExitNodesUnion_; description = "controller-selected circuit target"; break; } @@ -3541,7 +3604,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel."); state->desired_path_len = 1; } else { - int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list()); + int r = new_route_len(circ->base_.purpose, exit, nodelist_get_list()); if (r < 1) /* must be at least 1 */ return -1; state->desired_path_len = r; @@ -3554,7 +3617,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) exit = extend_info_dup(exit); } else { /* we have to decide one */ const node_t *node = - choose_good_exit_server(circ->_base.purpose, state->need_uptime, + choose_good_exit_server(circ->base_.purpose, state->need_uptime, state->need_capacity, state->is_internal); if (!node) { log_warn(LD_CIRC,"failed to choose an exit server"); @@ -3675,8 +3738,8 @@ choose_good_middle_server(uint8_t purpose, smartlist_t *excluded; const or_options_t *options = get_options(); router_crn_flags_t flags = CRN_NEED_DESC; - tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose && - purpose <= _CIRCUIT_PURPOSE_MAX); + tor_assert(CIRCUIT_PURPOSE_MIN_ <= purpose && + purpose <= CIRCUIT_PURPOSE_MAX_); log_debug(LD_CIRC, "Contemplating intermediate hop: random choice."); excluded = smartlist_new(); @@ -3693,7 +3756,7 @@ choose_good_middle_server(uint8_t purpose, flags |= CRN_NEED_UPTIME; if (state->need_capacity) flags |= CRN_NEED_CAPACITY; - if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE) + if (options->AllowInvalid_ & ALLOW_INVALID_MIDDLE) flags |= CRN_ALLOW_INVALID; choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); smartlist_free(excluded); @@ -3755,7 +3818,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) if (state->need_capacity) flags |= CRN_NEED_CAPACITY; } - if (options->_AllowInvalid & ALLOW_INVALID_ENTRY) + if (options->AllowInvalid_ & ALLOW_INVALID_ENTRY) flags |= CRN_ALLOW_INVALID; choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); @@ -3783,7 +3846,7 @@ onion_next_hop_in_cpath(crypt_path_t *cpath) static int onion_extend_cpath(origin_circuit_t *circ) { - uint8_t purpose = circ->_base.purpose; + uint8_t purpose = circ->base_.purpose; cpath_build_state_t *state = circ->build_state; int cur_len = circuit_get_cpath_len(circ); extend_info_t *info = NULL; @@ -3802,12 +3865,10 @@ onion_extend_cpath(origin_circuit_t *circ) } else if (cur_len == 0) { /* picking first node */ const node_t *r = choose_good_entry_server(purpose, state); if (r) { - /* If we're extending to a bridge, use the preferred address - rather than the primary, for potentially extending to an IPv6 - bridge. */ - int use_pref_addr = (r->ri != NULL && - r->ri->purpose == ROUTER_PURPOSE_BRIDGE); - info = extend_info_from_node(r, use_pref_addr); + /* If we're a client, use the preferred address rather than the + primary address, for potentially connecting to an IPv6 OR + port. */ + info = extend_info_from_node(r, server_mode(get_options()) == 0); tor_assert(info); } } else { @@ -3858,7 +3919,7 @@ onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice) /** Allocate a new extend_info object based on the various arguments. */ extend_info_t * -extend_info_alloc(const char *nickname, const char *digest, +extend_info_new(const char *nickname, const char *digest, crypto_pk_t *onion_key, const tor_addr_t *addr, uint16_t port) { @@ -3873,47 +3934,45 @@ extend_info_alloc(const char *nickname, const char *digest, return info; } -/** Allocate and return a new extend_info_t that can be used to build - * a circuit to or through the router <b>r</b>. Use the primary - * address of the router unless <b>for_direct_connect</b> is true, in - * which case the preferred address is used instead. */ +/** Allocate and return a new extend_info that can be used to build a + * circuit to or through the node <b>node</b>. Use the primary address + * of the node (i.e. its IPv4 address) unless + * <b>for_direct_connect</b> is true, in which case the preferred + * address is used instead. May return NULL if there is not enough + * info about <b>node</b> to extend to it--for example, if there is no + * routerinfo_t or microdesc_t. + **/ extend_info_t * -extend_info_from_router(const routerinfo_t *r, int for_direct_connect) +extend_info_from_node(const node_t *node, int for_direct_connect) { tor_addr_port_t ap; - tor_assert(r); + + if (node->ri == NULL && (node->rs == NULL || node->md == NULL)) + return NULL; if (for_direct_connect) - router_get_pref_orport(r, &ap); + node_get_pref_orport(node, &ap); else - router_get_prim_orport(r, &ap); - return extend_info_alloc(r->nickname, r->cache_info.identity_digest, - r->onion_pkey, &ap.addr, ap.port); -} + node_get_prim_orport(node, &ap); -/** Allocate and return a new extend_info that can be used to build a - * circuit to or through the node <b>node</b>. Use the primary address - * of the node unless <b>for_direct_connect</b> is true, in which case - * the preferred address is used instead. May return NULL if there is - * not enough info about <b>node</b> to extend to it--for example, if - * there is no routerinfo_t or microdesc_t. - **/ -extend_info_t * -extend_info_from_node(const node_t *node, int for_direct_connect) -{ - if (node->ri) { - return extend_info_from_router(node->ri, for_direct_connect); - } else if (node->rs && node->md) { - tor_addr_t addr; - tor_addr_from_ipv4h(&addr, node->rs->addr); - return extend_info_alloc(node->rs->nickname, + log_debug(LD_CIRC, "using %s for %s", + fmt_addrport(&ap.addr, ap.port), + node->ri ? node->ri->nickname : node->rs->nickname); + + if (node->ri) + return extend_info_new(node->ri->nickname, + node->identity, + node->ri->onion_pkey, + &ap.addr, + ap.port); + else if (node->rs && node->md) + return extend_info_new(node->rs->nickname, node->identity, node->md->onion_pkey, - &addr, - node->rs->or_port); - } else { + &ap.addr, + ap.port); + else return NULL; - } } /** Release storage held by an extend_info_t struct. */ @@ -4990,7 +5049,7 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg) if (remove_obsolete_entry_guards(now)) entry_guards_dirty = 1; } - digestmap_free(added_by, _tor_free); + digestmap_free(added_by, tor_free_); return *msg ? -1 : 0; } @@ -5191,206 +5250,37 @@ bridge_free(bridge_info_t *bridge) tor_free(bridge); } -/** A list of pluggable transports found in torrc. */ -static smartlist_t *transport_list = NULL; - -/** Mark every entry of the transport list to be removed on our next call to - * sweep_transport_list unless it has first been un-marked. */ -void -mark_transport_list(void) -{ - if (!transport_list) - transport_list = smartlist_new(); - SMARTLIST_FOREACH(transport_list, transport_t *, t, - t->marked_for_removal = 1); -} - -/** Remove every entry of the transport list that was marked with - * mark_transport_list if it has not subsequently been un-marked. */ -void -sweep_transport_list(void) -{ - if (!transport_list) - transport_list = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) { - if (t->marked_for_removal) { - SMARTLIST_DEL_CURRENT(transport_list, t); - transport_free(t); - } - } SMARTLIST_FOREACH_END(t); -} - -/** Initialize the pluggable transports list to empty, creating it if - * needed. */ -void -clear_transport_list(void) -{ - if (!transport_list) - transport_list = smartlist_new(); - SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t)); - smartlist_clear(transport_list); -} - -/** Free the pluggable transport struct <b>transport</b>. */ -void -transport_free(transport_t *transport) -{ - if (!transport) - return; - - tor_free(transport->name); - tor_free(transport); -} - -/** Returns the transport in our transport list that has the name <b>name</b>. - * Else returns NULL. */ -transport_t * -transport_get_by_name(const char *name) +/** If we have a bridge configured whose digest matches <b>digest</b>, or a + * bridge with no known digest whose address matches any of the + * tor_addr_port_t's in <b>orports</b>, return that bridge. Else return + * NULL. */ +static bridge_info_t * +get_configured_bridge_by_orports_digest(const char *digest, + const smartlist_t *orports) { - tor_assert(name); - - if (!transport_list) + if (!bridge_list) return NULL; - - SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) { - if (!strcmp(transport->name, name)) - return transport; - } SMARTLIST_FOREACH_END(transport); - - return NULL; -} - -/** Returns a transport_t struct for a transport proxy supporting the - protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using - SOCKS version <b>socks_ver</b>. */ -transport_t * -transport_new(const tor_addr_t *addr, uint16_t port, - const char *name, int socks_ver) -{ - transport_t *t = tor_malloc_zero(sizeof(transport_t)); - - tor_addr_copy(&t->addr, addr); - t->port = port; - t->name = tor_strdup(name); - t->socks_version = socks_ver; - - return t; -} - -/** Resolve any conflicts that the insertion of transport <b>t</b> - * might cause. - * Return 0 if <b>t</b> is OK and should be registered, 1 if there is - * a transport identical to <b>t</b> already registered and -1 if - * <b>t</b> cannot be added due to conflicts. */ -static int -transport_resolve_conflicts(transport_t *t) -{ - /* This is how we resolve transport conflicts: - - If there is already a transport with the same name and addrport, - we either have duplicate torrc lines OR we are here post-HUP and - this transport was here pre-HUP as well. In any case, mark the - old transport so that it doesn't get removed and ignore the new - one. Our caller has to free the new transport so we return '1' to - signify this. - - If there is already a transport with the same name but different - addrport: - * if it's marked for removal, it means that it either has a lower - priority than 't' in torrc (otherwise the mark would have been - cleared by the paragraph above), or it doesn't exist at all in - the post-HUP torrc. We destroy the old transport and register 't'. - * if it's *not* marked for removal, it means that it was newly - added in the post-HUP torrc or that it's of higher priority, in - this case we ignore 't'. */ - transport_t *t_tmp = transport_get_by_name(t->name); - if (t_tmp) { /* same name */ - if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) { - /* same name *and* addrport */ - t_tmp->marked_for_removal = 0; - return 1; - } else { /* same name but different addrport */ - char *new_transport_addr = tor_strdup(fmt_addr(&t->addr)); - if (t_tmp->marked_for_removal) { /* marked for removal */ - log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' " - "but there was already a transport marked for deletion at " - "'%s:%u'. We deleted the old transport and registered the " - "new one.", t->name, new_transport_addr, t->port, - fmt_addr(&t_tmp->addr), t_tmp->port); - smartlist_remove(transport_list, t_tmp); - transport_free(t_tmp); - tor_free(new_transport_addr); - } else { /* *not* marked for removal */ - log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' " - "but the same transport already exists at '%s:%u'. " - "Skipping.", t->name, new_transport_addr, t->port, - fmt_addr(&t_tmp->addr), t_tmp->port); - tor_free(new_transport_addr); - return -1; + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) + { + if (tor_digest_is_zero(bridge->identity)) { + SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, ap) + { + if (tor_addr_compare(&bridge->addr, &ap->addr, CMP_EXACT) == 0 && + bridge->port == ap->port) + return bridge; + } + SMARTLIST_FOREACH_END(ap); } + if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN)) + return bridge; } - } - - return 0; -} - -/** Add transport <b>t</b> to the internal list of pluggable - * transports. - * Returns 0 if the transport was added correctly, 1 if the same - * transport was already registered (in this case the caller must - * free the transport) and -1 if there was an error. */ -int -transport_add(transport_t *t) -{ - int r; - tor_assert(t); - - r = transport_resolve_conflicts(t); - - switch (r) { - case 0: /* should register transport */ - if (!transport_list) - transport_list = smartlist_new(); - smartlist_add(transport_list, t); - return 0; - default: /* let our caller know the return code */ - return r; - } -} - -/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>. - * <b>name</b> is set to the name of the protocol this proxy uses. - * <b>socks_ver</b> is set to the SOCKS version of the proxy. */ -int -transport_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *name, int socks_ver) -{ - transport_t *t = transport_new(addr, port, name, socks_ver); - - int r = transport_add(t); - - switch (r) { - case -1: - default: - log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.", - t->name, fmt_addr(&t->addr), t->port); - transport_free(t); - return -1; - case 1: - log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.", - t->name, fmt_addr(&t->addr), t->port); - transport_free(t); /* falling */ - return 0; - case 0: - log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.", - t->name, fmt_addr(&t->addr), t->port); - return 0; - } + SMARTLIST_FOREACH_END(bridge); + return NULL; } -/** Return a bridge pointer if <b>ri</b> is one of our known bridges - * (either by comparing keys if possible, else by comparing addr/port). - * Else return NULL. */ +/** If we have a bridge configured whose digest matches <b>digest</b>, or a + * bridge with no known digest whose address matches <b>addr</b>:<b>/port</b>, + * return that bridge. Else return NULL. */ static bridge_info_t * get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr, uint16_t port, @@ -5416,11 +5306,13 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr, static bridge_info_t * get_configured_bridge_by_routerinfo(const routerinfo_t *ri) { - tor_addr_port_t ap; - - router_get_pref_orport(ri, &ap); - return get_configured_bridge_by_addr_port_digest(&ap.addr, ap.port, - ri->cache_info.identity_digest); + bridge_info_t *bi = NULL; + smartlist_t *orports = router_get_all_orports(ri); + bi = get_configured_bridge_by_orports_digest(ri->cache_info.identity_digest, + orports); + SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p)); + smartlist_free(orports); + return bi; } /** Return 1 if <b>ri</b> is one of our known bridges, else 0. */ @@ -5434,30 +5326,12 @@ routerinfo_is_a_configured_bridge(const routerinfo_t *ri) int node_is_a_configured_bridge(const node_t *node) { - int retval = 0; /* Negative. */ - smartlist_t *orports = NULL; - - if (!node) - goto out; - - orports = node_get_all_orports(node); - if (orports == NULL) - goto out; - - SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, orport) { - if (get_configured_bridge_by_addr_port_digest(&orport->addr, orport->port, - node->identity) != NULL) { - retval = 1; - goto out; - } - } SMARTLIST_FOREACH_END(orport); - - out: - if (orports != NULL) { - SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p)); - smartlist_free(orports); - orports = NULL; - } + int retval = 0; + smartlist_t *orports = node_get_all_orports(node); + retval = get_configured_bridge_by_orports_digest(node->identity, + orports) != NULL; + SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p)); + smartlist_free(orports); return retval; } @@ -5473,8 +5347,8 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port, get_configured_bridge_by_addr_port_digest(addr, port, digest); if (bridge && tor_digest_is_zero(bridge->identity)) { memcpy(bridge->identity, digest, DIGEST_LEN); - log_notice(LD_DIR, "Learned fingerprint %s for bridge %s:%d", - hex_str(digest, DIGEST_LEN), fmt_addr(addr), port); + log_notice(LD_DIR, "Learned fingerprint %s for bridge %s", + hex_str(digest, DIGEST_LEN), fmt_addrport(addr, port)); } } @@ -5519,12 +5393,12 @@ bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port, strcmp_opt(bridge->transport_name, transport_name)) { /* warn the user */ char *bridge_description_new, *bridge_description_old; - tor_asprintf(&bridge_description_new, "%s:%u:%s:%s", - fmt_addr(addr), port, + tor_asprintf(&bridge_description_new, "%s:%s:%s", + fmt_addrport(addr, port), digest ? hex_str(digest, DIGEST_LEN) : "", transport_name ? transport_name : ""); - tor_asprintf(&bridge_description_old, "%s:%u:%s:%s", - fmt_addr(&bridge->addr), bridge->port, + tor_asprintf(&bridge_description_old, "%s:%s:%s", + fmt_addrport(&bridge->addr, bridge->port), tor_digest_is_zero(bridge->identity) ? "" : hex_str(bridge->identity,DIGEST_LEN), bridge->transport_name ? bridge->transport_name : ""); @@ -5581,7 +5455,7 @@ routerset_contains_bridge(const routerset_t *routerset, if (!routerset) return 0; - extinfo = extend_info_alloc( + extinfo = extend_info_new( NULL, bridge->identity, NULL, &bridge->addr, bridge->port); result = routerset_contains_extendinfo(routerset, extinfo); extend_info_free(extinfo); @@ -5667,19 +5541,18 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { download_status_mark_impossible(&bridge->fetch_status); log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", - safe_str_client(fmt_addr(&bridge->addr))); + safe_str_client(fmt_and_decorate_addr(&bridge->addr))); return; } address = tor_dup_addr(&bridge->addr); directory_initiate_command(address, &bridge->addr, - bridge->port, 0, - 0, /* does not matter */ - 1, bridge->identity, + bridge->port, 0/*no dirport*/, + bridge->identity, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, - 0, "authority.z", NULL, 0, 0); + DIRIND_ONEHOP, "authority.z", NULL, 0, 0); tor_free(address); } @@ -5721,7 +5594,7 @@ fetch_bridge_descriptors(const or_options_t *options, time_t now) if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { download_status_mark_impossible(&bridge->fetch_status); log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", - safe_str_client(fmt_addr(&bridge->addr))); + safe_str_client(fmt_and_decorate_addr(&bridge->addr))); continue; } @@ -5738,9 +5611,9 @@ fetch_bridge_descriptors(const or_options_t *options, time_t now) if (ask_bridge_directly && !fascist_firewall_allows_address_or(&bridge->addr, bridge->port)) { - log_notice(LD_DIR, "Bridge at '%s:%d' isn't reachable by our " - "firewall policy. %s.", fmt_addr(&bridge->addr), - bridge->port, + log_notice(LD_DIR, "Bridge at '%s' isn't reachable by our " + "firewall policy. %s.", + fmt_addrport(&bridge->addr, bridge->port), can_use_bridge_authority ? "Asking bridge authority instead" : "Skipping"); if (can_use_bridge_authority) @@ -5810,8 +5683,8 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node) ri->ipv6_orport = bridge->port; log_info(LD_DIR, "Adjusted bridge routerinfo for '%s' to match configured " - "address %s:%d.", - ri->nickname, fmt_addr(&ri->ipv6_addr), ri->ipv6_orport); + "address %s.", + ri->nickname, fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport)); } else { log_err(LD_BUG, "Address family not supported: %d.", tor_addr_family(&bridge->addr)); @@ -5819,22 +5692,21 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node) } } - /* Indicate that we prefer connecting to this bridge over the - protocol that the bridge address indicates. Last bridge - descriptor handled wins. */ - ri->ipv6_preferred = tor_addr_family(&bridge->addr) == AF_INET6; + /* Mark which address to use based on which bridge_t we got. */ + node->ipv6_preferred = (tor_addr_family(&bridge->addr) == AF_INET6 && + !tor_addr_is_null(&node->ri->ipv6_addr)); /* XXXipv6 we lack support for falling back to another address for the same relay, warn the user */ if (!tor_addr_is_null(&ri->ipv6_addr)) { tor_addr_port_t ap; - router_get_pref_orport(ri, &ap); + node_get_pref_orport(node, &ap); log_notice(LD_CONFIG, "Bridge '%s' has both an IPv4 and an IPv6 address. " - "Will prefer using its %s address (%s:%d).", + "Will prefer using its %s address (%s).", ri->nickname, - ri->ipv6_preferred ? "IPv6" : "IPv4", - fmt_addr(&ap.addr), ap.port); + tor_addr_family(&ap.addr) == AF_INET6 ? "IPv6" : "IPv4", + fmt_addrport(&ap.addr, ap.port)); } } if (node->rs) { @@ -5849,8 +5721,8 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node) rs->or_port = bridge->port; log_info(LD_DIR, "Adjusted bridge routerstatus for '%s' to match " - "configured address %s:%d.", - rs->nickname, fmt_addr(&bridge->addr), rs->or_port); + "configured address %s.", + rs->nickname, fmt_addrport(&bridge->addr, rs->or_port)); } } } @@ -6023,10 +5895,8 @@ entry_guards_free_all(void) entry_guards = NULL; } clear_bridge_list(); - clear_transport_list(); smartlist_free(bridge_list); - smartlist_free(transport_list); bridge_list = NULL; - transport_list = NULL; + circuit_build_times_free_timeouts(&circ_times); } |