[tor-commits] [tor/master] Merge branch 'split_circuitbuild'

nickm at torproject.org nickm at torproject.org
Mon Oct 22 15:36:59 UTC 2012


commit 86258df65d35b82ad4ee7480eec5d5434a28c9a8
Merge: 20912fb 907db00
Author: Nick Mathewson <nickm at torproject.org>
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;
  }



More information about the tor-commits mailing list