Back to index

tor  0.2.3.19-rc
circuitlist.c
Go to the documentation of this file.
00001 /* Copyright 2001 Matej Pfajfar.
00002  * Copyright (c) 2001-2004, Roger Dingledine.
00003  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00004  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00005 /* See LICENSE for licensing information */
00006 
00012 #include "or.h"
00013 #include "circuitbuild.h"
00014 #include "circuitlist.h"
00015 #include "circuituse.h"
00016 #include "connection.h"
00017 #include "config.h"
00018 #include "connection_edge.h"
00019 #include "connection_or.h"
00020 #include "control.h"
00021 #include "networkstatus.h"
00022 #include "nodelist.h"
00023 #include "onion.h"
00024 #include "relay.h"
00025 #include "rendclient.h"
00026 #include "rendcommon.h"
00027 #include "rephist.h"
00028 #include "routerlist.h"
00029 #include "ht.h"
00030 
00031 /********* START VARIABLES **********/
00032 
00034 circuit_t *global_circuitlist=NULL;
00035 
00037 static smartlist_t *circuits_pending_or_conns=NULL;
00038 
00039 static void circuit_free(circuit_t *circ);
00040 static void circuit_free_cpath(crypt_path_t *cpath);
00041 static void circuit_free_cpath_node(crypt_path_t *victim);
00042 static void cpath_ref_decref(crypt_path_reference_t *cpath_ref);
00043 
00044 /********* END VARIABLES ************/
00045 
00048 typedef struct orconn_circid_circuit_map_t {
00049   HT_ENTRY(orconn_circid_circuit_map_t) node;
00050   or_connection_t *or_conn;
00051   circid_t circ_id;
00052   circuit_t *circuit;
00053 } orconn_circid_circuit_map_t;
00054 
00058 static INLINE int
00059 _orconn_circid_entries_eq(orconn_circid_circuit_map_t *a,
00060                           orconn_circid_circuit_map_t *b)
00061 {
00062   return a->or_conn == b->or_conn && a->circ_id == b->circ_id;
00063 }
00064 
00067 static INLINE unsigned int
00068 _orconn_circid_entry_hash(orconn_circid_circuit_map_t *a)
00069 {
00070   return (((unsigned)a->circ_id)<<8) ^ (unsigned)(uintptr_t)(a->or_conn);
00071 }
00072 
00074 static HT_HEAD(orconn_circid_map, orconn_circid_circuit_map_t)
00075      orconn_circid_circuit_map = HT_INITIALIZER();
00076 HT_PROTOTYPE(orconn_circid_map, orconn_circid_circuit_map_t, node,
00077              _orconn_circid_entry_hash, _orconn_circid_entries_eq)
00078 HT_GENERATE(orconn_circid_map, orconn_circid_circuit_map_t, node,
00079             _orconn_circid_entry_hash, _orconn_circid_entries_eq, 0.6,
00080             malloc, realloc, free)
00081 
00086 orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
00087 
00092 static void
00093 circuit_set_circid_orconn_helper(circuit_t *circ, int direction,
00094                                  circid_t id,
00095                                  or_connection_t *conn)
00096 {
00097   orconn_circid_circuit_map_t search;
00098   orconn_circid_circuit_map_t *found;
00099   or_connection_t *old_conn, **conn_ptr;
00100   circid_t old_id, *circid_ptr;
00101   int was_active, make_active;
00102 
00103   if (direction == CELL_DIRECTION_OUT) {
00104     conn_ptr = &circ->n_conn;
00105     circid_ptr = &circ->n_circ_id;
00106     was_active = circ->next_active_on_n_conn != NULL;
00107     make_active = circ->n_conn_cells.n > 0;
00108   } else {
00109     or_circuit_t *c = TO_OR_CIRCUIT(circ);
00110     conn_ptr = &c->p_conn;
00111     circid_ptr = &c->p_circ_id;
00112     was_active = c->next_active_on_p_conn != NULL;
00113     make_active = c->p_conn_cells.n > 0;
00114   }
00115   old_conn = *conn_ptr;
00116   old_id = *circid_ptr;
00117 
00118   if (id == old_id && conn == old_conn)
00119     return;
00120 
00121   if (_last_circid_orconn_ent &&
00122       ((old_id == _last_circid_orconn_ent->circ_id &&
00123         old_conn == _last_circid_orconn_ent->or_conn) ||
00124        (id == _last_circid_orconn_ent->circ_id &&
00125         conn == _last_circid_orconn_ent->or_conn))) {
00126     _last_circid_orconn_ent = NULL;
00127   }
00128 
00129   if (old_conn) { /* we may need to remove it from the conn-circid map */
00130     tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC);
00131     search.circ_id = old_id;
00132     search.or_conn = old_conn;
00133     found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search);
00134     if (found) {
00135       tor_free(found);
00136       --old_conn->n_circuits;
00137     }
00138     if (was_active && old_conn != conn)
00139       make_circuit_inactive_on_conn(circ,old_conn);
00140   }
00141 
00142   /* Change the values only after we have possibly made the circuit inactive
00143    * on the previous conn. */
00144   *conn_ptr = conn;
00145   *circid_ptr = id;
00146 
00147   if (conn == NULL)
00148     return;
00149 
00150   /* now add the new one to the conn-circid map */
00151   search.circ_id = id;
00152   search.or_conn = conn;
00153   found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search);
00154   if (found) {
00155     found->circuit = circ;
00156   } else {
00157     found = tor_malloc_zero(sizeof(orconn_circid_circuit_map_t));
00158     found->circ_id = id;
00159     found->or_conn = conn;
00160     found->circuit = circ;
00161     HT_INSERT(orconn_circid_map, &orconn_circid_circuit_map, found);
00162   }
00163   if (make_active && old_conn != conn)
00164     make_circuit_active_on_conn(circ,conn);
00165 
00166   ++conn->n_circuits;
00167 }
00168 
00172 void
00173 circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id,
00174                             or_connection_t *conn)
00175 {
00176   circuit_set_circid_orconn_helper(TO_CIRCUIT(circ), CELL_DIRECTION_IN,
00177                                    id, conn);
00178 
00179   if (conn)
00180     tor_assert(bool_eq(circ->p_conn_cells.n, circ->next_active_on_p_conn));
00181 }
00182 
00186 void
00187 circuit_set_n_circid_orconn(circuit_t *circ, circid_t id,
00188                             or_connection_t *conn)
00189 {
00190   circuit_set_circid_orconn_helper(circ, CELL_DIRECTION_OUT, id, conn);
00191 
00192   if (conn)
00193     tor_assert(bool_eq(circ->n_conn_cells.n, circ->next_active_on_n_conn));
00194 }
00195 
00198 void
00199 circuit_set_state(circuit_t *circ, uint8_t state)
00200 {
00201   tor_assert(circ);
00202   if (state == circ->state)
00203     return;
00204   if (!circuits_pending_or_conns)
00205     circuits_pending_or_conns = smartlist_new();
00206   if (circ->state == CIRCUIT_STATE_OR_WAIT) {
00207     /* remove from waiting-circuit list. */
00208     smartlist_remove(circuits_pending_or_conns, circ);
00209   }
00210   if (state == CIRCUIT_STATE_OR_WAIT) {
00211     /* add to waiting-circuit list. */
00212     smartlist_add(circuits_pending_or_conns, circ);
00213   }
00214   if (state == CIRCUIT_STATE_OPEN)
00215     tor_assert(!circ->n_conn_onionskin);
00216   circ->state = state;
00217 }
00218 
00222 static void
00223 circuit_add(circuit_t *circ)
00224 {
00225   if (!global_circuitlist) { /* first one */
00226     global_circuitlist = circ;
00227     circ->next = NULL;
00228   } else {
00229     circ->next = global_circuitlist;
00230     global_circuitlist = circ;
00231   }
00232 }
00233 
00236 void
00237 circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn)
00238 {
00239   tor_assert(out);
00240   tor_assert(or_conn);
00241 
00242   if (!circuits_pending_or_conns)
00243     return;
00244 
00245   SMARTLIST_FOREACH_BEGIN(circuits_pending_or_conns, circuit_t *, circ) {
00246     if (circ->marked_for_close)
00247       continue;
00248     if (!circ->n_hop)
00249       continue;
00250     tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
00251     if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
00252       /* Look at addr/port. This is an unkeyed connection. */
00253       if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) ||
00254           circ->n_hop->port != or_conn->_base.port)
00255         continue;
00256     } else {
00257       /* We expected a key. See if it's the right one. */
00258       if (tor_memneq(or_conn->identity_digest,
00259                  circ->n_hop->identity_digest, DIGEST_LEN))
00260         continue;
00261     }
00262     smartlist_add(out, circ);
00263   } SMARTLIST_FOREACH_END(circ);
00264 }
00265 
00268 int
00269 circuit_count_pending_on_or_conn(or_connection_t *or_conn)
00270 {
00271   int cnt;
00272   smartlist_t *sl = smartlist_new();
00273   circuit_get_all_pending_on_or_conn(sl, or_conn);
00274   cnt = smartlist_len(sl);
00275   smartlist_free(sl);
00276   log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
00277             or_conn->nickname ? or_conn->nickname : "NULL",
00278             or_conn->_base.address,
00279             cnt);
00280   return cnt;
00281 }
00282 
00286 void
00287 circuit_close_all_marked(void)
00288 {
00289   circuit_t *tmp,*m;
00290 
00291   while (global_circuitlist && global_circuitlist->marked_for_close) {
00292     tmp = global_circuitlist->next;
00293     circuit_free(global_circuitlist);
00294     global_circuitlist = tmp;
00295   }
00296 
00297   tmp = global_circuitlist;
00298   while (tmp && tmp->next) {
00299     if (tmp->next->marked_for_close) {
00300       m = tmp->next->next;
00301       circuit_free(tmp->next);
00302       tmp->next = m;
00303       /* Need to check new tmp->next; don't advance tmp. */
00304     } else {
00305       /* Advance tmp. */
00306       tmp = tmp->next;
00307     }
00308   }
00309 }
00310 
00312 circuit_t *
00313 _circuit_get_global_list(void)
00314 {
00315   return global_circuitlist;
00316 }
00317 
00319 const char *
00320 circuit_state_to_string(int state)
00321 {
00322   static char buf[64];
00323   switch (state) {
00324     case CIRCUIT_STATE_BUILDING: return "doing handshakes";
00325     case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion";
00326     case CIRCUIT_STATE_OR_WAIT: return "connecting to server";
00327     case CIRCUIT_STATE_OPEN: return "open";
00328     default:
00329       log_warn(LD_BUG, "Unknown circuit state %d", state);
00330       tor_snprintf(buf, sizeof(buf), "unknown state [%d]", state);
00331       return buf;
00332   }
00333 }
00334 
00337 const char *
00338 circuit_purpose_to_controller_string(uint8_t purpose)
00339 {
00340   static char buf[32];
00341   switch (purpose) {
00342     case CIRCUIT_PURPOSE_OR:
00343     case CIRCUIT_PURPOSE_INTRO_POINT:
00344     case CIRCUIT_PURPOSE_REND_POINT_WAITING:
00345     case CIRCUIT_PURPOSE_REND_ESTABLISHED:
00346       return "SERVER"; /* A controller should never see these, actually. */
00347 
00348     case CIRCUIT_PURPOSE_C_GENERAL:
00349       return "GENERAL";
00350     case CIRCUIT_PURPOSE_C_INTRODUCING:
00351     case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
00352     case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
00353       return "HS_CLIENT_INTRO";
00354 
00355     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
00356     case CIRCUIT_PURPOSE_C_REND_READY:
00357     case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
00358     case CIRCUIT_PURPOSE_C_REND_JOINED:
00359       return "HS_CLIENT_REND";
00360 
00361     case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
00362     case CIRCUIT_PURPOSE_S_INTRO:
00363       return "HS_SERVICE_INTRO";
00364 
00365     case CIRCUIT_PURPOSE_S_CONNECT_REND:
00366     case CIRCUIT_PURPOSE_S_REND_JOINED:
00367       return "HS_SERVICE_REND";
00368 
00369     case CIRCUIT_PURPOSE_TESTING:
00370       return "TESTING";
00371     case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
00372       return "MEASURE_TIMEOUT";
00373     case CIRCUIT_PURPOSE_CONTROLLER:
00374       return "CONTROLLER";
00375 
00376     default:
00377       tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
00378       return buf;
00379   }
00380 }
00381 
00385 const char *
00386 circuit_purpose_to_controller_hs_state_string(uint8_t purpose)
00387 {
00388   switch (purpose)
00389     {
00390     default:
00391       log_fn(LOG_WARN, LD_BUG,
00392              "Unrecognized circuit purpose: %d",
00393              (int)purpose);
00394       tor_fragile_assert();
00395       /* fall through */
00396 
00397     case CIRCUIT_PURPOSE_OR:
00398     case CIRCUIT_PURPOSE_C_GENERAL:
00399     case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
00400     case CIRCUIT_PURPOSE_TESTING:
00401     case CIRCUIT_PURPOSE_CONTROLLER:
00402       return NULL;
00403 
00404     case CIRCUIT_PURPOSE_INTRO_POINT:
00405       return "OR_HSSI_ESTABLISHED";
00406     case CIRCUIT_PURPOSE_REND_POINT_WAITING:
00407       return "OR_HSCR_ESTABLISHED";
00408     case CIRCUIT_PURPOSE_REND_ESTABLISHED:
00409       return "OR_HS_R_JOINED";
00410 
00411     case CIRCUIT_PURPOSE_C_INTRODUCING:
00412       return "HSCI_CONNECTING";
00413     case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
00414       return "HSCI_INTRO_SENT";
00415     case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
00416       return "HSCI_DONE";
00417 
00418     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
00419       return "HSCR_CONNECTING";
00420     case CIRCUIT_PURPOSE_C_REND_READY:
00421       return "HSCR_ESTABLISHED_IDLE";
00422     case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
00423       return "HSCR_ESTABLISHED_WAITING";
00424     case CIRCUIT_PURPOSE_C_REND_JOINED:
00425       return "HSCR_JOINED";
00426 
00427     case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
00428       return "HSSI_CONNECTING";
00429     case CIRCUIT_PURPOSE_S_INTRO:
00430       return "HSSI_ESTABLISHED";
00431 
00432     case CIRCUIT_PURPOSE_S_CONNECT_REND:
00433       return "HSSR_CONNECTING";
00434     case CIRCUIT_PURPOSE_S_REND_JOINED:
00435       return "HSSR_JOINED";
00436     }
00437 }
00438 
00440 const char *
00441 circuit_purpose_to_string(uint8_t purpose)
00442 {
00443   static char buf[32];
00444 
00445   switch (purpose)
00446     {
00447     case CIRCUIT_PURPOSE_OR:
00448       return "Circuit at relay";
00449     case CIRCUIT_PURPOSE_INTRO_POINT:
00450       return "Acting as intro point";
00451     case CIRCUIT_PURPOSE_REND_POINT_WAITING:
00452       return "Acting as rendevous (pending)";
00453     case CIRCUIT_PURPOSE_REND_ESTABLISHED:
00454       return "Acting as rendevous (established)";
00455     case CIRCUIT_PURPOSE_C_GENERAL:
00456       return "General-purpose client";
00457     case CIRCUIT_PURPOSE_C_INTRODUCING:
00458       return "Hidden service client: Connecting to intro point";
00459     case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
00460       return "Hidden service client: Waiting for ack from intro point";
00461     case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
00462       return "Hidden service client: Received ack from intro point";
00463     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
00464       return "Hidden service client: Establishing rendezvous point";
00465     case CIRCUIT_PURPOSE_C_REND_READY:
00466       return "Hidden service client: Pending rendezvous point";
00467     case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
00468       return "Hidden service client: Pending rendezvous point (ack received)";
00469     case CIRCUIT_PURPOSE_C_REND_JOINED:
00470       return "Hidden service client: Active rendezvous point";
00471     case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
00472       return "Measuring circuit timeout";
00473 
00474     case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
00475       return "Hidden service: Establishing introduction point";
00476     case CIRCUIT_PURPOSE_S_INTRO:
00477       return "Hidden service: Introduction point";
00478     case CIRCUIT_PURPOSE_S_CONNECT_REND:
00479       return "Hidden service: Connecting to rendezvous point";
00480     case CIRCUIT_PURPOSE_S_REND_JOINED:
00481       return "Hidden service: Active rendezvous point";
00482 
00483     case CIRCUIT_PURPOSE_TESTING:
00484       return "Testing circuit";
00485 
00486     case CIRCUIT_PURPOSE_CONTROLLER:
00487       return "Circuit made by controller";
00488 
00489     default:
00490       tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
00491       return buf;
00492   }
00493 }
00494 
00498 int32_t
00499 circuit_initial_package_window(void)
00500 {
00501   int32_t num = networkstatus_get_param(NULL, "circwindow", CIRCWINDOW_START,
00502                                         CIRCWINDOW_START_MIN,
00503                                         CIRCWINDOW_START_MAX);
00504   /* If the consensus tells us a negative number, we'd assert. */
00505   if (num < 0)
00506     num = CIRCWINDOW_START;
00507   return num;
00508 }
00509 
00512 static void
00513 init_circuit_base(circuit_t *circ)
00514 {
00515   tor_gettimeofday(&circ->timestamp_created);
00516 
00517   circ->package_window = circuit_initial_package_window();
00518   circ->deliver_window = CIRCWINDOW_START;
00519 
00520   /* Initialize the cell_ewma_t structure */
00521   circ->n_cell_ewma.last_adjusted_tick = cell_ewma_get_tick();
00522   circ->n_cell_ewma.cell_count = 0.0;
00523   circ->n_cell_ewma.heap_index = -1;
00524   circ->n_cell_ewma.is_for_p_conn = 0;
00525 
00526   circuit_add(circ);
00527 }
00528 
00532 origin_circuit_t *
00533 origin_circuit_new(void)
00534 {
00535   origin_circuit_t *circ;
00536   /* never zero, since a global ID of 0 is treated specially by the
00537    * controller */
00538   static uint32_t n_circuits_allocated = 1;
00539 
00540   circ = tor_malloc_zero(sizeof(origin_circuit_t));
00541   circ->_base.magic = ORIGIN_CIRCUIT_MAGIC;
00542 
00543   circ->next_stream_id = crypto_rand_int(1<<16);
00544   circ->global_identifier = n_circuits_allocated++;
00545   circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
00546   circ->remaining_relay_early_cells -= crypto_rand_int(2);
00547 
00548   init_circuit_base(TO_CIRCUIT(circ));
00549 
00550   circ_times.last_circ_at = approx_time();
00551 
00552   return circ;
00553 }
00554 
00557 or_circuit_t *
00558 or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn)
00559 {
00560   /* CircIDs */
00561   or_circuit_t *circ;
00562 
00563   circ = tor_malloc_zero(sizeof(or_circuit_t));
00564   circ->_base.magic = OR_CIRCUIT_MAGIC;
00565 
00566   if (p_conn)
00567     circuit_set_p_circid_orconn(circ, p_circ_id, p_conn);
00568 
00569   circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
00570 
00571   init_circuit_base(TO_CIRCUIT(circ));
00572 
00573   /* Initialize the cell_ewma_t structure */
00574 
00575   /* Initialize the cell counts to 0 */
00576   circ->p_cell_ewma.cell_count = 0.0;
00577   circ->p_cell_ewma.last_adjusted_tick = cell_ewma_get_tick();
00578   circ->p_cell_ewma.is_for_p_conn = 1;
00579 
00580   /* It's not in any heap yet. */
00581   circ->p_cell_ewma.heap_index = -1;
00582 
00583   return circ;
00584 }
00585 
00588 static void
00589 circuit_free(circuit_t *circ)
00590 {
00591   void *mem;
00592   size_t memlen;
00593   if (!circ)
00594     return;
00595 
00596   if (CIRCUIT_IS_ORIGIN(circ)) {
00597     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
00598     mem = ocirc;
00599     memlen = sizeof(origin_circuit_t);
00600     tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
00601     if (ocirc->build_state) {
00602         extend_info_free(ocirc->build_state->chosen_exit);
00603         circuit_free_cpath_node(ocirc->build_state->pending_final_cpath);
00604         cpath_ref_decref(ocirc->build_state->service_pending_final_cpath_ref);
00605     }
00606     tor_free(ocirc->build_state);
00607 
00608     circuit_free_cpath(ocirc->cpath);
00609 
00610     crypto_pk_free(ocirc->intro_key);
00611     rend_data_free(ocirc->rend_data);
00612 
00613     tor_free(ocirc->dest_address);
00614     if (ocirc->socks_username) {
00615       memset(ocirc->socks_username, 0x12, ocirc->socks_username_len);
00616       tor_free(ocirc->socks_username);
00617     }
00618     if (ocirc->socks_password) {
00619       memset(ocirc->socks_password, 0x06, ocirc->socks_password_len);
00620       tor_free(ocirc->socks_password);
00621     }
00622   } else {
00623     or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
00624     /* Remember cell statistics for this circuit before deallocating. */
00625     if (get_options()->CellStatistics)
00626       rep_hist_buffer_stats_add_circ(circ, time(NULL));
00627     mem = ocirc;
00628     memlen = sizeof(or_circuit_t);
00629     tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
00630 
00631     crypto_cipher_free(ocirc->p_crypto);
00632     crypto_digest_free(ocirc->p_digest);
00633     crypto_cipher_free(ocirc->n_crypto);
00634     crypto_digest_free(ocirc->n_digest);
00635 
00636     if (ocirc->rend_splice) {
00637       or_circuit_t *other = ocirc->rend_splice;
00638       tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC);
00639       other->rend_splice = NULL;
00640     }
00641 
00642     /* remove from map. */
00643     circuit_set_p_circid_orconn(ocirc, 0, NULL);
00644 
00645     /* Clear cell queue _after_ removing it from the map.  Otherwise our
00646      * "active" checks will be violated. */
00647     cell_queue_clear(&ocirc->p_conn_cells);
00648   }
00649 
00650   extend_info_free(circ->n_hop);
00651   tor_free(circ->n_conn_onionskin);
00652 
00653   /* Remove from map. */
00654   circuit_set_n_circid_orconn(circ, 0, NULL);
00655 
00656   /* Clear cell queue _after_ removing it from the map.  Otherwise our
00657    * "active" checks will be violated. */
00658   cell_queue_clear(&circ->n_conn_cells);
00659 
00660   memset(mem, 0xAA, memlen); /* poison memory */
00661   tor_free(mem);
00662 }
00663 
00665 static void
00666 circuit_free_cpath(crypt_path_t *cpath)
00667 {
00668   crypt_path_t *victim, *head=cpath;
00669 
00670   if (!cpath)
00671     return;
00672 
00673   /* it's a doubly linked list, so we have to notice when we've
00674    * gone through it once. */
00675   while (cpath->next && cpath->next != head) {
00676     victim = cpath;
00677     cpath = victim->next;
00678     circuit_free_cpath_node(victim);
00679   }
00680 
00681   circuit_free_cpath_node(cpath);
00682 }
00683 
00685 void
00686 circuit_free_all(void)
00687 {
00688   circuit_t *next;
00689   while (global_circuitlist) {
00690     next = global_circuitlist->next;
00691     if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) {
00692       or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist);
00693       while (or_circ->resolving_streams) {
00694         edge_connection_t *next_conn;
00695         next_conn = or_circ->resolving_streams->next_stream;
00696         connection_free(TO_CONN(or_circ->resolving_streams));
00697         or_circ->resolving_streams = next_conn;
00698       }
00699     }
00700     circuit_free(global_circuitlist);
00701     global_circuitlist = next;
00702   }
00703 
00704   smartlist_free(circuits_pending_or_conns);
00705   circuits_pending_or_conns = NULL;
00706 
00707   HT_CLEAR(orconn_circid_map, &orconn_circid_circuit_map);
00708 }
00709 
00711 static void
00712 circuit_free_cpath_node(crypt_path_t *victim)
00713 {
00714   if (!victim)
00715     return;
00716 
00717   crypto_cipher_free(victim->f_crypto);
00718   crypto_cipher_free(victim->b_crypto);
00719   crypto_digest_free(victim->f_digest);
00720   crypto_digest_free(victim->b_digest);
00721   crypto_dh_free(victim->dh_handshake_state);
00722   extend_info_free(victim->extend_info);
00723 
00724   memset(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
00725   tor_free(victim);
00726 }
00727 
00729 static void
00730 cpath_ref_decref(crypt_path_reference_t *cpath_ref)
00731 {
00732   if (cpath_ref != NULL) {
00733     if (--(cpath_ref->refcount) == 0) {
00734       circuit_free_cpath_node(cpath_ref->cpath);
00735       tor_free(cpath_ref);
00736     }
00737   }
00738 }
00739 
00743 static void
00744 circuit_dump_details(int severity, circuit_t *circ, int conn_array_index,
00745                      const char *type, int this_circid, int other_circid)
00746 {
00747   log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
00748       "state %d (%s), born %ld:",
00749       conn_array_index, type, this_circid, other_circid, circ->state,
00750       circuit_state_to_string(circ->state),
00751       (long)circ->timestamp_created.tv_sec);
00752   if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
00753     circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ));
00754   }
00755 }
00756 
00760 void
00761 circuit_dump_by_conn(connection_t *conn, int severity)
00762 {
00763   circuit_t *circ;
00764   edge_connection_t *tmpconn;
00765 
00766   for (circ=global_circuitlist;circ;circ = circ->next) {
00767     circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
00768     if (circ->marked_for_close)
00769       continue;
00770 
00771     if (! CIRCUIT_IS_ORIGIN(circ))
00772       p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
00773 
00774     if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_conn &&
00775         TO_CONN(TO_OR_CIRCUIT(circ)->p_conn) == conn)
00776       circuit_dump_details(severity, circ, conn->conn_array_index, "App-ward",
00777                            p_circ_id, n_circ_id);
00778     if (CIRCUIT_IS_ORIGIN(circ)) {
00779       for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
00780            tmpconn=tmpconn->next_stream) {
00781         if (TO_CONN(tmpconn) == conn) {
00782           circuit_dump_details(severity, circ, conn->conn_array_index,
00783                                "App-ward", p_circ_id, n_circ_id);
00784         }
00785       }
00786     }
00787     if (circ->n_conn && TO_CONN(circ->n_conn) == conn)
00788       circuit_dump_details(severity, circ, conn->conn_array_index, "Exit-ward",
00789                            n_circ_id, p_circ_id);
00790     if (! CIRCUIT_IS_ORIGIN(circ)) {
00791       for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
00792            tmpconn=tmpconn->next_stream) {
00793         if (TO_CONN(tmpconn) == conn) {
00794           circuit_dump_details(severity, circ, conn->conn_array_index,
00795                                "Exit-ward", n_circ_id, p_circ_id);
00796         }
00797       }
00798     }
00799     if (!circ->n_conn && circ->n_hop &&
00800         tor_addr_eq(&circ->n_hop->addr, &conn->addr) &&
00801         circ->n_hop->port == conn->port &&
00802         conn->type == CONN_TYPE_OR &&
00803         tor_memeq(TO_OR_CONN(conn)->identity_digest,
00804                 circ->n_hop->identity_digest, DIGEST_LEN)) {
00805       circuit_dump_details(severity, circ, conn->conn_array_index,
00806                            (circ->state == CIRCUIT_STATE_OPEN &&
00807                             !CIRCUIT_IS_ORIGIN(circ)) ?
00808                              "Endpoint" : "Pending",
00809                            n_circ_id, p_circ_id);
00810     }
00811   }
00812 }
00813 
00816 origin_circuit_t *
00817 circuit_get_by_global_id(uint32_t id)
00818 {
00819   circuit_t *circ;
00820   for (circ=global_circuitlist;circ;circ = circ->next) {
00821     if (CIRCUIT_IS_ORIGIN(circ) &&
00822         TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) {
00823       if (circ->marked_for_close)
00824         return NULL;
00825       else
00826         return TO_ORIGIN_CIRCUIT(circ);
00827     }
00828   }
00829   return NULL;
00830 }
00831 
00837 static INLINE circuit_t *
00838 circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn)
00839 {
00840   orconn_circid_circuit_map_t search;
00841   orconn_circid_circuit_map_t *found;
00842 
00843   if (_last_circid_orconn_ent &&
00844       circ_id == _last_circid_orconn_ent->circ_id &&
00845       conn == _last_circid_orconn_ent->or_conn) {
00846     found = _last_circid_orconn_ent;
00847   } else {
00848     search.circ_id = circ_id;
00849     search.or_conn = conn;
00850     found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search);
00851     _last_circid_orconn_ent = found;
00852   }
00853   if (found && found->circuit)
00854     return found->circuit;
00855 
00856   return NULL;
00857   /* The rest of this checks for bugs. Disabled by default. */
00858   /* We comment it out because coverity complains otherwise.
00859   {
00860     circuit_t *circ;
00861     for (circ=global_circuitlist;circ;circ = circ->next) {
00862       if (! CIRCUIT_IS_ORIGIN(circ)) {
00863         or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
00864         if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) {
00865           log_warn(LD_BUG,
00866                    "circuit matches p_conn, but not in hash table (Bug!)");
00867           return circ;
00868         }
00869       }
00870       if (circ->n_conn == conn && circ->n_circ_id == circ_id) {
00871         log_warn(LD_BUG,
00872                  "circuit matches n_conn, but not in hash table (Bug!)");
00873         return circ;
00874       }
00875     }
00876     return NULL;
00877   } */
00878 }
00879 
00886 circuit_t *
00887 circuit_get_by_circid_orconn(circid_t circ_id, or_connection_t *conn)
00888 {
00889   circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn);
00890   if (!circ || circ->marked_for_close)
00891     return NULL;
00892   else
00893     return circ;
00894 }
00895 
00898 int
00899 circuit_id_in_use_on_orconn(circid_t circ_id, or_connection_t *conn)
00900 {
00901   return circuit_get_by_circid_orconn_impl(circ_id, conn) != NULL;
00902 }
00903 
00905 circuit_t *
00906 circuit_get_by_edge_conn(edge_connection_t *conn)
00907 {
00908   circuit_t *circ;
00909 
00910   circ = conn->on_circuit;
00911   tor_assert(!circ ||
00912              (CIRCUIT_IS_ORIGIN(circ) ? circ->magic == ORIGIN_CIRCUIT_MAGIC
00913                                       : circ->magic == OR_CIRCUIT_MAGIC));
00914 
00915   return circ;
00916 }
00917 
00922 void
00923 circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason)
00924 {
00925   circuit_t *circ;
00926 
00927   connection_or_unlink_all_active_circs(conn);
00928 
00929   for (circ = global_circuitlist; circ; circ = circ->next) {
00930     int mark = 0;
00931     if (circ->n_conn == conn) {
00932         circuit_set_n_circid_orconn(circ, 0, NULL);
00933         mark = 1;
00934     }
00935     if (! CIRCUIT_IS_ORIGIN(circ)) {
00936       or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
00937       if (or_circ->p_conn == conn) {
00938         circuit_set_p_circid_orconn(or_circ, 0, NULL);
00939         mark = 1;
00940       }
00941     }
00942     if (mark && !circ->marked_for_close)
00943       circuit_mark_for_close(circ, reason);
00944   }
00945 }
00946 
00956 origin_circuit_t *
00957 circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
00958 {
00959   circuit_t *circ;
00960 
00961   for (circ = global_circuitlist; circ; circ = circ->next) {
00962     if (!circ->marked_for_close &&
00963         circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
00964       origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
00965       if (ocirc->rend_data &&
00966           !rend_cmp_service_ids(rend_data->onion_address,
00967                                 ocirc->rend_data->onion_address) &&
00968           tor_memeq(ocirc->rend_data->rend_cookie,
00969                     rend_data->rend_cookie,
00970                     REND_COOKIE_LEN))
00971         return ocirc;
00972     }
00973   }
00974   return NULL;
00975 }
00976 
00982 origin_circuit_t *
00983 circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
00984                                    const char *digest, uint8_t purpose)
00985 {
00986   circuit_t *circ;
00987   tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose));
00988   if (start == NULL)
00989     circ = global_circuitlist;
00990   else
00991     circ = TO_CIRCUIT(start)->next;
00992 
00993   for ( ; circ; circ = circ->next) {
00994     if (circ->marked_for_close)
00995       continue;
00996     if (circ->purpose != purpose)
00997       continue;
00998     if (!digest)
00999       return TO_ORIGIN_CIRCUIT(circ);
01000     else if (TO_ORIGIN_CIRCUIT(circ)->rend_data &&
01001              tor_memeq(TO_ORIGIN_CIRCUIT(circ)->rend_data->rend_pk_digest,
01002                      digest, DIGEST_LEN))
01003       return TO_ORIGIN_CIRCUIT(circ);
01004   }
01005   return NULL;
01006 }
01007 
01011 static or_circuit_t *
01012 circuit_get_by_rend_token_and_purpose(uint8_t purpose, const char *token,
01013                                       size_t len)
01014 {
01015   circuit_t *circ;
01016   for (circ = global_circuitlist; circ; circ = circ->next) {
01017     if (! circ->marked_for_close &&
01018         circ->purpose == purpose &&
01019         tor_memeq(TO_OR_CIRCUIT(circ)->rend_token, token, len))
01020       return TO_OR_CIRCUIT(circ);
01021   }
01022   return NULL;
01023 }
01024 
01028 or_circuit_t *
01029 circuit_get_rendezvous(const char *cookie)
01030 {
01031   return circuit_get_by_rend_token_and_purpose(
01032                                      CIRCUIT_PURPOSE_REND_POINT_WAITING,
01033                                      cookie, REND_COOKIE_LEN);
01034 }
01035 
01039 or_circuit_t *
01040 circuit_get_intro_point(const char *digest)
01041 {
01042   return circuit_get_by_rend_token_and_purpose(
01043                                      CIRCUIT_PURPOSE_INTRO_POINT, digest,
01044                                      DIGEST_LEN);
01045 }
01046 
01058 origin_circuit_t *
01059 circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
01060                             int flags)
01061 {
01062   circuit_t *_circ;
01063   origin_circuit_t *best=NULL;
01064   int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0;
01065   int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0;
01066   int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0;
01067   const or_options_t *options = get_options();
01068 
01069   /* Make sure we're not trying to create a onehop circ by
01070    * cannibalization. */
01071   tor_assert(!(flags & CIRCLAUNCH_ONEHOP_TUNNEL));
01072 
01073   log_debug(LD_CIRC,
01074             "Hunting for a circ to cannibalize: purpose %d, uptime %d, "
01075             "capacity %d, internal %d",
01076             purpose, need_uptime, need_capacity, internal);
01077 
01078   for (_circ=global_circuitlist; _circ; _circ = _circ->next) {
01079     if (CIRCUIT_IS_ORIGIN(_circ) &&
01080         _circ->state == CIRCUIT_STATE_OPEN &&
01081         !_circ->marked_for_close &&
01082         _circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
01083         !_circ->timestamp_dirty) {
01084       origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(_circ);
01085       if ((!need_uptime || circ->build_state->need_uptime) &&
01086           (!need_capacity || circ->build_state->need_capacity) &&
01087           (internal == circ->build_state->is_internal) &&
01088           circ->remaining_relay_early_cells &&
01089           circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN &&
01090           !circ->build_state->onehop_tunnel &&
01091           !circ->isolation_values_set) {
01092         if (info) {
01093           /* need to make sure we don't duplicate hops */
01094           crypt_path_t *hop = circ->cpath;
01095           const node_t *ri1 = node_get_by_id(info->identity_digest);
01096           do {
01097             const node_t *ri2;
01098             if (tor_memeq(hop->extend_info->identity_digest,
01099                         info->identity_digest, DIGEST_LEN))
01100               goto next;
01101             if (ri1 &&
01102                 (ri2 = node_get_by_id(hop->extend_info->identity_digest))
01103                 && nodes_in_same_family(ri1, ri2))
01104               goto next;
01105             hop=hop->next;
01106           } while (hop!=circ->cpath);
01107         }
01108         if (options->ExcludeNodes) {
01109           /* Make sure no existing nodes in the circuit are excluded for
01110            * general use.  (This may be possible if StrictNodes is 0, and we
01111            * thought we needed to use an otherwise excluded node for, say, a
01112            * directory operation.) */
01113           crypt_path_t *hop = circ->cpath;
01114           do {
01115             if (routerset_contains_extendinfo(options->ExcludeNodes,
01116                                               hop->extend_info))
01117               goto next;
01118             hop = hop->next;
01119           } while (hop != circ->cpath);
01120         }
01121         if (!best || (best->build_state->need_uptime && !need_uptime))
01122           best = circ;
01123       next: ;
01124       }
01125     }
01126   }
01127   return best;
01128 }
01129 
01131 int
01132 circuit_get_cpath_len(origin_circuit_t *circ)
01133 {
01134   int n = 0;
01135   if (circ && circ->cpath) {
01136     crypt_path_t *cpath, *cpath_next = NULL;
01137     for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) {
01138       cpath_next = cpath->next;
01139       ++n;
01140     }
01141   }
01142   return n;
01143 }
01144 
01147 crypt_path_t *
01148 circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum)
01149 {
01150   if (circ && circ->cpath && hopnum > 0) {
01151     crypt_path_t *cpath, *cpath_next = NULL;
01152     for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) {
01153       cpath_next = cpath->next;
01154       if (--hopnum <= 0)
01155         return cpath;
01156     }
01157   }
01158   return NULL;
01159 }
01160 
01163 void
01164 circuit_mark_all_unused_circs(void)
01165 {
01166   circuit_t *circ;
01167 
01168   for (circ=global_circuitlist; circ; circ = circ->next) {
01169     if (CIRCUIT_IS_ORIGIN(circ) &&
01170         !circ->marked_for_close &&
01171         !circ->timestamp_dirty)
01172       circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
01173   }
01174 }
01175 
01183 /* XXX024 this is a bad name for what this function does */
01184 void
01185 circuit_expire_all_dirty_circs(void)
01186 {
01187   circuit_t *circ;
01188   const or_options_t *options = get_options();
01189 
01190   for (circ=global_circuitlist; circ; circ = circ->next) {
01191     if (CIRCUIT_IS_ORIGIN(circ) &&
01192         !circ->marked_for_close &&
01193         circ->timestamp_dirty)
01194       /* XXXX024 This is a screwed-up way to say "This is too dirty
01195        * for new circuits. */
01196       circ->timestamp_dirty -= options->MaxCircuitDirtiness;
01197   }
01198 }
01199 
01217 void
01218 _circuit_mark_for_close(circuit_t *circ, int reason, int line,
01219                         const char *file)
01220 {
01221   int orig_reason = reason; /* Passed to the controller */
01222   assert_circuit_ok(circ);
01223   tor_assert(line);
01224   tor_assert(file);
01225 
01226   if (circ->marked_for_close) {
01227     log(LOG_WARN,LD_BUG,
01228         "Duplicate call to circuit_mark_for_close at %s:%d"
01229         " (first at %s:%d)", file, line,
01230         circ->marked_for_close_file, circ->marked_for_close);
01231     return;
01232   }
01233   if (reason == END_CIRC_AT_ORIGIN) {
01234     if (!CIRCUIT_IS_ORIGIN(circ)) {
01235       log_warn(LD_BUG, "Specified 'at-origin' non-reason for ending circuit, "
01236                "but circuit was not at origin. (called %s:%d, purpose=%d)",
01237                file, line, circ->purpose);
01238     }
01239     reason = END_CIRC_REASON_NONE;
01240   }
01241   if (CIRCUIT_IS_ORIGIN(circ)) {
01242     /* We don't send reasons when closing circuits at the origin. */
01243     reason = END_CIRC_REASON_NONE;
01244   }
01245 
01246   if (reason & END_CIRC_REASON_FLAG_REMOTE)
01247     reason &= ~END_CIRC_REASON_FLAG_REMOTE;
01248 
01249   if (reason < _END_CIRC_REASON_MIN || reason > _END_CIRC_REASON_MAX) {
01250     if (!(orig_reason & END_CIRC_REASON_FLAG_REMOTE))
01251       log_warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line);
01252     reason = END_CIRC_REASON_NONE;
01253   }
01254 
01255   if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
01256     onion_pending_remove(TO_OR_CIRCUIT(circ));
01257   }
01258   /* If the circuit ever became OPEN, we sent it to the reputation history
01259    * module then.  If it isn't OPEN, we send it there now to remember which
01260    * links worked and which didn't.
01261    */
01262   if (circ->state != CIRCUIT_STATE_OPEN) {
01263     if (CIRCUIT_IS_ORIGIN(circ)) {
01264       origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
01265       circuit_build_failed(ocirc); /* take actions if necessary */
01266       circuit_rep_hist_note_result(ocirc);
01267     }
01268   }
01269   if (circ->state == CIRCUIT_STATE_OR_WAIT) {
01270     if (circuits_pending_or_conns)
01271       smartlist_remove(circuits_pending_or_conns, circ);
01272   }
01273   if (CIRCUIT_IS_ORIGIN(circ)) {
01274     control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
01275      (circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
01276      orig_reason);
01277   }
01278   if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
01279     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
01280     int timed_out = (reason == END_CIRC_REASON_TIMEOUT);
01281     tor_assert(circ->state == CIRCUIT_STATE_OPEN);
01282     tor_assert(ocirc->build_state->chosen_exit);
01283     tor_assert(ocirc->rend_data);
01284     /* treat this like getting a nack from it */
01285     log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
01286            safe_str_client(ocirc->rend_data->onion_address),
01287            safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
01288            timed_out ? "Recording timeout." : "Removing from descriptor.");
01289     rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
01290                                            ocirc->rend_data,
01291                                            timed_out ?
01292                                            INTRO_POINT_FAILURE_TIMEOUT :
01293                                            INTRO_POINT_FAILURE_GENERIC);
01294   } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
01295              reason != END_CIRC_REASON_TIMEOUT) {
01296     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
01297     if (ocirc->build_state->chosen_exit && ocirc->rend_data) {
01298       log_info(LD_REND, "Failed intro circ %s to %s "
01299                "(building circuit to intro point). "
01300                "Marking intro point as possibly unreachable.",
01301                safe_str_client(ocirc->rend_data->onion_address),
01302            safe_str_client(build_state_get_exit_nickname(ocirc->build_state)));
01303       rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
01304                                              ocirc->rend_data,
01305                                              INTRO_POINT_FAILURE_UNREACHABLE);
01306     }
01307   }
01308   if (circ->n_conn) {
01309     circuit_clear_cell_queue(circ, circ->n_conn);
01310     connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
01311   }
01312 
01313   if (! CIRCUIT_IS_ORIGIN(circ)) {
01314     or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
01315     edge_connection_t *conn;
01316     for (conn=or_circ->n_streams; conn; conn=conn->next_stream)
01317       connection_edge_destroy(or_circ->p_circ_id, conn);
01318     or_circ->n_streams = NULL;
01319 
01320     while (or_circ->resolving_streams) {
01321       conn = or_circ->resolving_streams;
01322       or_circ->resolving_streams = conn->next_stream;
01323       if (!conn->_base.marked_for_close) {
01324         /* The client will see a DESTROY, and infer that the connections
01325          * are closing because the circuit is getting torn down.  No need
01326          * to send an end cell. */
01327         conn->edge_has_sent_end = 1;
01328         conn->end_reason = END_STREAM_REASON_DESTROY;
01329         conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
01330         connection_mark_for_close(TO_CONN(conn));
01331       }
01332       conn->on_circuit = NULL;
01333     }
01334 
01335     if (or_circ->p_conn) {
01336       circuit_clear_cell_queue(circ, or_circ->p_conn);
01337       connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason);
01338     }
01339   } else {
01340     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
01341     edge_connection_t *conn;
01342     for (conn=ocirc->p_streams; conn; conn=conn->next_stream)
01343       connection_edge_destroy(circ->n_circ_id, conn);
01344     ocirc->p_streams = NULL;
01345   }
01346 
01347   circ->marked_for_close = line;
01348   circ->marked_for_close_file = file;
01349 
01350   if (!CIRCUIT_IS_ORIGIN(circ)) {
01351     or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
01352     if (or_circ->rend_splice) {
01353       if (!or_circ->rend_splice->_base.marked_for_close) {
01354         /* do this after marking this circuit, to avoid infinite recursion. */
01355         circuit_mark_for_close(TO_CIRCUIT(or_circ->rend_splice), reason);
01356       }
01357       or_circ->rend_splice = NULL;
01358     }
01359   }
01360 }
01361 
01365 void
01366 assert_cpath_layer_ok(const crypt_path_t *cp)
01367 {
01368 //  tor_assert(cp->addr); /* these are zero for rendezvous extra-hops */
01369 //  tor_assert(cp->port);
01370   tor_assert(cp);
01371   tor_assert(cp->magic == CRYPT_PATH_MAGIC);
01372   switch (cp->state)
01373     {
01374     case CPATH_STATE_OPEN:
01375       tor_assert(cp->f_crypto);
01376       tor_assert(cp->b_crypto);
01377       /* fall through */
01378     case CPATH_STATE_CLOSED:
01379       tor_assert(!cp->dh_handshake_state);
01380       break;
01381     case CPATH_STATE_AWAITING_KEYS:
01382       /* tor_assert(cp->dh_handshake_state); */
01383       break;
01384     default:
01385       log_fn(LOG_ERR, LD_BUG, "Unexpected state %d", cp->state);
01386       tor_assert(0);
01387     }
01388   tor_assert(cp->package_window >= 0);
01389   tor_assert(cp->deliver_window >= 0);
01390 }
01391 
01395 static void
01396 assert_cpath_ok(const crypt_path_t *cp)
01397 {
01398   const crypt_path_t *start = cp;
01399 
01400   do {
01401     assert_cpath_layer_ok(cp);
01402     /* layers must be in sequence of: "open* awaiting? closed*" */
01403     if (cp != start) {
01404       if (cp->state == CPATH_STATE_AWAITING_KEYS) {
01405         tor_assert(cp->prev->state == CPATH_STATE_OPEN);
01406       } else if (cp->state == CPATH_STATE_OPEN) {
01407         tor_assert(cp->prev->state == CPATH_STATE_OPEN);
01408       }
01409     }
01410     cp = cp->next;
01411     tor_assert(cp);
01412   } while (cp != start);
01413 }
01414 
01418 void
01419 assert_circuit_ok(const circuit_t *c)
01420 {
01421   edge_connection_t *conn;
01422   const or_circuit_t *or_circ = NULL;
01423   const origin_circuit_t *origin_circ = NULL;
01424 
01425   tor_assert(c);
01426   tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC);
01427   tor_assert(c->purpose >= _CIRCUIT_PURPOSE_MIN &&
01428              c->purpose <= _CIRCUIT_PURPOSE_MAX);
01429 
01430   {
01431     /* Having a separate variable for this pleases GCC 4.2 in ways I hope I
01432      * never understand. -NM. */
01433     circuit_t *nonconst_circ = (circuit_t*) c;
01434     if (CIRCUIT_IS_ORIGIN(c))
01435       origin_circ = TO_ORIGIN_CIRCUIT(nonconst_circ);
01436     else
01437       or_circ = TO_OR_CIRCUIT(nonconst_circ);
01438   }
01439 
01440   if (c->n_conn) {
01441     tor_assert(!c->n_hop);
01442 
01443     if (c->n_circ_id) {
01444       /* We use the _impl variant here to make sure we don't fail on marked
01445        * circuits, which would not be returned by the regular function. */
01446       circuit_t *c2 = circuit_get_by_circid_orconn_impl(c->n_circ_id,
01447                                                         c->n_conn);
01448       tor_assert(c == c2);
01449     }
01450   }
01451   if (or_circ && or_circ->p_conn) {
01452     if (or_circ->p_circ_id) {
01453       /* ibid */
01454       circuit_t *c2 = circuit_get_by_circid_orconn_impl(or_circ->p_circ_id,
01455                                                         or_circ->p_conn);
01456       tor_assert(c == c2);
01457     }
01458   }
01459   if (or_circ)
01460     for (conn = or_circ->n_streams; conn; conn = conn->next_stream)
01461       tor_assert(conn->_base.type == CONN_TYPE_EXIT);
01462 
01463   tor_assert(c->deliver_window >= 0);
01464   tor_assert(c->package_window >= 0);
01465   if (c->state == CIRCUIT_STATE_OPEN) {
01466     tor_assert(!c->n_conn_onionskin);
01467     if (or_circ) {
01468       tor_assert(or_circ->n_crypto);
01469       tor_assert(or_circ->p_crypto);
01470       tor_assert(or_circ->n_digest);
01471       tor_assert(or_circ->p_digest);
01472     }
01473   }
01474   if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) {
01475     tor_assert(circuits_pending_or_conns &&
01476                smartlist_isin(circuits_pending_or_conns, c));
01477   } else {
01478     tor_assert(!circuits_pending_or_conns ||
01479                !smartlist_isin(circuits_pending_or_conns, c));
01480   }
01481   if (origin_circ && origin_circ->cpath) {
01482     assert_cpath_ok(origin_circ->cpath);
01483   }
01484   if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) {
01485     tor_assert(or_circ);
01486     if (!c->marked_for_close) {
01487       tor_assert(or_circ->rend_splice);
01488       tor_assert(or_circ->rend_splice->rend_splice == or_circ);
01489     }
01490     tor_assert(or_circ->rend_splice != or_circ);
01491   } else {
01492     tor_assert(!or_circ || !or_circ->rend_splice);
01493   }
01494 }
01495