[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Merge branch 'split_circuitbuild'
commit 86258df65d35b82ad4ee7480eec5d5434a28c9a8
Merge: 20912fb 907db00
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Mon Oct 22 11:35:32 2012 -0400
Merge branch 'split_circuitbuild'
Conflicts:
src/or/circuitbuild.c
There was a huge-looking conflict in circuitbuild.c, but the only
change that had been made to circuitbuild.c since I forked off the
split_circuitbuild branch was 17442560c44e8093f9a. So I took the
split_circuitbuild version of the conflicting part, and manually
re-applied the change from 17442560c44e8093f9a..
changes/split_circuitbuild | 4 +
src/or/channel.c | 2 +
src/or/circuitbuild.c | 7304 ++++++++++++--------------------------------
src/or/circuitbuild.h | 90 -
src/or/circuitlist.c | 1 +
src/or/circuitstats.c | 1569 ++++++++++
src/or/circuitstats.h | 65 +
src/or/circuituse.c | 2 +
src/or/config.c | 1 +
src/or/connection.c | 1 +
src/or/connection_or.c | 2 +
src/or/control.c | 2 +
src/or/directory.c | 1 +
src/or/entrynodes.c | 1945 ++++++++++++
src/or/entrynodes.h | 101 +
src/or/include.am | 4 +
src/or/main.c | 1 +
src/or/microdesc.c | 1 +
src/or/networkstatus.c | 3 +-
src/or/routerlist.c | 3 +-
src/or/routerparse.c | 2 +-
src/or/statefile.c | 3 +-
src/test/test.c | 4 +-
23 files changed, 5616 insertions(+), 5495 deletions(-)
diff --cc src/or/circuitbuild.c
index b16dab2,75f0d5b..5e85b3e
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@@ -3671,248 -1340,182 +1340,182 @@@ entry_guard_inc_first_hop_count(entry_g
return 0;
}
- /** Return the number of routers in <b>routers</b> that are currently up
- * and available for building circuits through.
+ /** A created or extended cell came back to us on the circuit, and it included
+ * <b>reply</b> as its body. (If <b>reply_type</b> is CELL_CREATED, the body
+ * contains (the second DH key, plus KH). If <b>reply_type</b> is
+ * CELL_CREATED_FAST, the body contains a secret y and a hash H(x|y).)
+ *
+ * Calculate the appropriate keys and digests, make sure KH is
+ * correct, and initialize this hop of the cpath.
+ *
+ * Return - reason if we want to mark circ for close, else return 0.
*/
- static int
- count_acceptable_nodes(smartlist_t *nodes)
+ int
+ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
+ const uint8_t *reply)
{
- int num=0;
-
- SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
- // log_debug(LD_CIRC,
- // "Contemplating whether router %d (%s) is a new option.",
- // i, r->nickname);
- if (! node->is_running)
- // log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
- continue;
- if (! node->is_valid)
- // log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
- continue;
- if (! node_has_descriptor(node))
- continue;
- /* XXX This clause makes us count incorrectly: if AllowInvalidRouters
- * allows this node in some places, then we're getting an inaccurate
- * count. For now, be conservative and don't count it. But later we
- * should try to be smarter. */
- ++num;
- } SMARTLIST_FOREACH_END(node);
+ char keys[CPATH_KEY_MATERIAL_LEN];
+ crypt_path_t *hop;
+ int rv;
- // log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num);
+ if ((rv = pathbias_count_first_hop(circ)) < 0)
+ return rv;
- return num;
- }
+ if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) {
+ hop = circ->cpath;
+ } else {
+ hop = onion_next_hop_in_cpath(circ->cpath);
+ if (!hop) { /* got an extended when we're all done? */
+ log_warn(LD_PROTOCOL,"got extended when circ already built? Closing.");
+ return - END_CIRC_REASON_TORPROTOCOL;
+ }
+ }
+ tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
- /** Add <b>new_hop</b> to the end of the doubly-linked-list <b>head_ptr</b>.
- * This function is used to extend cpath by another hop.
- */
- void
- onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
- {
- if (*head_ptr) {
- new_hop->next = (*head_ptr);
- new_hop->prev = (*head_ptr)->prev;
- (*head_ptr)->prev->next = new_hop;
- (*head_ptr)->prev = new_hop;
+ if (reply_type == CELL_CREATED && hop->dh_handshake_state) {
+ if (onion_skin_client_handshake(hop->dh_handshake_state, (char*)reply,keys,
+ DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
+ log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ /* Remember hash of g^xy */
+ memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
+ } else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) {
+ if (fast_client_handshake(hop->fast_handshake_state, reply,
+ (uint8_t*)keys,
+ DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
+ log_warn(LD_CIRC,"fast_client_handshake failed.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
} else {
- *head_ptr = new_hop;
- new_hop->prev = new_hop->next = new_hop;
+ log_warn(LD_PROTOCOL,"CREATED cell type did not match CREATE cell type.");
+ return -END_CIRC_REASON_TORPROTOCOL;
}
- }
- /** A helper function used by onion_extend_cpath(). Use <b>purpose</b>
- * and <b>state</b> and the cpath <b>head</b> (currently populated only
- * to length <b>cur_len</b> to decide a suitable middle hop for a
- * circuit. In particular, make sure we don't pick the exit node or its
- * family, and make sure we don't duplicate any previous nodes or their
- * families. */
- static const node_t *
- choose_good_middle_server(uint8_t purpose,
- cpath_build_state_t *state,
- crypt_path_t *head,
- int cur_len)
- {
- int i;
- const node_t *r, *choice;
- crypt_path_t *cpath;
- 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_);
+ crypto_dh_free(hop->dh_handshake_state); /* don't need it anymore */
+ hop->dh_handshake_state = NULL;
- log_debug(LD_CIRC, "Contemplating intermediate hop: random choice.");
- excluded = smartlist_new();
- if ((r = build_state_get_exit_node(state))) {
- nodelist_add_node_and_family(excluded, r);
- }
- for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) {
- if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
- nodelist_add_node_and_family(excluded, r);
- }
+ memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state));
+
+ if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
+ return -END_CIRC_REASON_TORPROTOCOL;
}
- if (state->need_uptime)
- flags |= CRN_NEED_UPTIME;
- if (state->need_capacity)
- flags |= CRN_NEED_CAPACITY;
- if (options->AllowInvalid_ & ALLOW_INVALID_MIDDLE)
- flags |= CRN_ALLOW_INVALID;
- choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
- smartlist_free(excluded);
- return choice;
+ hop->state = CPATH_STATE_OPEN;
+ log_info(LD_CIRC,"Finished building %scircuit hop:",
+ (reply_type == CELL_CREATED_FAST) ? "fast " : "");
+ circuit_log_path(LOG_INFO,LD_CIRC,circ);
+ control_event_circuit_status(circ, CIRC_EVENT_EXTENDED, 0);
+
+ return 0;
}
- /** Pick a good entry server for the circuit to be built according to
- * <b>state</b>. Don't reuse a chosen exit (if any), don't use this
- * router (if we're an OR), and respect firewall settings; if we're
- * configured to use entry guards, return one.
+ /** We received a relay truncated cell on circ.
*
- * If <b>state</b> is NULL, we're choosing a router to serve as an entry
- * guard, not for any particular circuit.
+ * Since we don't ask for truncates currently, getting a truncated
+ * means that a connection broke or an extend failed. For now,
+ * just give up: for circ to close, and return 0.
*/
- static const node_t *
- choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
+ int
+ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason)
{
- const node_t *choice;
- smartlist_t *excluded;
- const or_options_t *options = get_options();
- router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC;
- const node_t *node;
+ // crypt_path_t *victim;
+ // connection_t *stream;
- if (state && options->UseEntryGuards &&
- (purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) {
- /* This request is for an entry server to use for a regular circuit,
- * and we use entry guard nodes. Just return one of the guard nodes. */
- return choose_random_entry(state);
- }
+ tor_assert(circ);
+ tor_assert(layer);
- excluded = smartlist_new();
+ /* XXX Since we don't ask for truncates currently, getting a truncated
+ * means that a connection broke or an extend failed. For now,
+ * just give up.
+ */
+ circuit_mark_for_close(TO_CIRCUIT(circ),
- END_CIRC_REASON_FLAG_REMOTE|END_CIRC_REASON_CHANNEL_CLOSED|reason);
++ END_CIRC_REASON_FLAG_REMOTE|reason);
+ return 0;
- if (state && (node = build_state_get_exit_node(state))) {
- /* Exclude the exit node from the state, if we have one. Also exclude its
- * family. */
- nodelist_add_node_and_family(excluded, node);
- }
- if (firewall_is_fascist_or()) {
- /* Exclude all ORs that we can't reach through our firewall */
- smartlist_t *nodes = nodelist_get_list();
- SMARTLIST_FOREACH(nodes, const node_t *, node, {
- if (!fascist_firewall_allows_node(node))
- smartlist_add(excluded, (void*)node);
- });
- }
- /* and exclude current entry guards and their families, if applicable */
- if (options->UseEntryGuards && entry_guards) {
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
- {
- if ((node = node_get_by_id(entry->identity))) {
- nodelist_add_node_and_family(excluded, node);
- }
- });
- }
+ #if 0
+ while (layer->next != circ->cpath) {
+ /* we need to clear out layer->next */
+ victim = layer->next;
+ log_debug(LD_CIRC, "Killing a layer of the cpath.");
- if (state) {
- if (state->need_uptime)
- flags |= CRN_NEED_UPTIME;
- if (state->need_capacity)
- flags |= CRN_NEED_CAPACITY;
- }
- if (options->AllowInvalid_ & ALLOW_INVALID_ENTRY)
- flags |= CRN_ALLOW_INVALID;
+ for (stream = circ->p_streams; stream; stream=stream->next_stream) {
+ if (stream->cpath_layer == victim) {
+ log_info(LD_APP, "Marking stream %d for close because of truncate.",
+ stream->stream_id);
+ /* no need to send 'end' relay cells,
+ * because the other side's already dead
+ */
+ connection_mark_unattached_ap(stream, END_STREAM_REASON_DESTROY);
+ }
+ }
- choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
- smartlist_free(excluded);
- return choice;
- }
+ layer->next = victim->next;
+ circuit_free_cpath_node(victim);
+ }
- /** Return the first non-open hop in cpath, or return NULL if all
- * hops are open. */
- static crypt_path_t *
- onion_next_hop_in_cpath(crypt_path_t *cpath)
- {
- crypt_path_t *hop = cpath;
- do {
- if (hop->state != CPATH_STATE_OPEN)
- return hop;
- hop = hop->next;
- } while (hop != cpath);
- return NULL;
+ log_info(LD_CIRC, "finished");
+ return 0;
+ #endif
}
- /** Choose a suitable next hop in the cpath <b>head_ptr</b>,
- * based on <b>state</b>. Append the hop info to head_ptr.
+ /** Given a response payload and keys, initialize, then send a created
+ * cell back.
*/
- static int
- onion_extend_cpath(origin_circuit_t *circ)
+ int
+ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
+ const char *keys)
{
- 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;
+ cell_t cell;
+ crypt_path_t *tmp_cpath;
- if (cur_len >= state->desired_path_len) {
- log_debug(LD_CIRC, "Path is complete: %d steps long",
- state->desired_path_len);
- return 1;
- }
+ tmp_cpath = tor_malloc_zero(sizeof(crypt_path_t));
+ tmp_cpath->magic = CRYPT_PATH_MAGIC;
- log_debug(LD_CIRC, "Path is %d long; we want %d", cur_len,
- state->desired_path_len);
+ memset(&cell, 0, sizeof(cell_t));
+ cell.command = cell_type;
+ cell.circ_id = circ->p_circ_id;
- if (cur_len == state->desired_path_len - 1) { /* Picking last node */
- info = extend_info_dup(state->chosen_exit);
- } else if (cur_len == 0) { /* picking first node */
- const node_t *r = choose_good_entry_server(purpose, state);
- if (r) {
- /* 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 {
- const node_t *r =
- choose_good_middle_server(purpose, state, circ->cpath, cur_len);
- if (r) {
- info = extend_info_from_node(r, 0);
- tor_assert(info);
- }
- }
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
- if (!info) {
- log_warn(LD_CIRC,"Failed to find node for hop %d of our path. Discarding "
- "this circuit.", cur_len);
+ memcpy(cell.payload, payload,
+ cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
+
+ log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
+ (unsigned int)get_uint32(keys),
+ (unsigned int)get_uint32(keys+20));
+ if (circuit_init_cpath_crypto(tmp_cpath, keys, 0)<0) {
+ log_warn(LD_BUG,"Circuit initialization failed");
+ tor_free(tmp_cpath);
return -1;
}
+ circ->n_digest = tmp_cpath->f_digest;
+ circ->n_crypto = tmp_cpath->f_crypto;
+ circ->p_digest = tmp_cpath->b_digest;
+ circ->p_crypto = tmp_cpath->b_crypto;
+ tmp_cpath->magic = 0;
+ tor_free(tmp_cpath);
- log_debug(LD_CIRC,"Chose router %s for hop %d (exit is %s)",
- extend_info_describe(info),
- cur_len+1, build_state_get_exit_nickname(state));
-
- onion_append_hop(&circ->cpath, info);
- extend_info_free(info);
- return 0;
- }
-
- /** Create a new hop, annotate it with information about its
- * corresponding router <b>choice</b>, and append it to the
- * end of the cpath <b>head_ptr</b>. */
- static int
- onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice)
- {
- crypt_path_t *hop = tor_malloc_zero(sizeof(crypt_path_t));
-
- /* link hop into the cpath, at the end. */
- onion_append_to_cpath(head_ptr, hop);
+ if (cell_type == CELL_CREATED)
+ memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
+ else
+ memcpy(circ->handshake_digest, cell.payload+DIGEST_LEN, DIGEST_LEN);
- hop->magic = CRYPT_PATH_MAGIC;
- hop->state = CPATH_STATE_CLOSED;
+ circ->is_first_hop = (cell_type == CELL_CREATED_FAST);
- hop->extend_info = extend_info_dup(choice);
+ append_cell_to_circuit_queue(TO_CIRCUIT(circ),
+ circ->p_chan, &cell, CELL_DIRECTION_IN, 0);
+ log_debug(LD_CIRC,"Finished sending '%s' cell.",
+ circ->is_first_hop ? "created_fast" : "created");
- hop->package_window = circuit_initial_package_window();
- hop->deliver_window = CIRCWINDOW_START;
+ 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. */
+ router_orport_found_reachable();
+ }
return 0;
}
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits