static void test_relay_close_circuit(void *arg) { channel_t *nchan = NULL, *pchan = NULL; or_circuit_t *orcirc = NULL; cell_t *cell = NULL; int old_count, new_count; (void)arg; /* Make fake channels to be nchan and pchan for the circuit */ nchan = new_fake_channel(); tt_assert(nchan); pchan = new_fake_channel(); tt_assert(pchan); /* Make a fake orcirc */ orcirc = new_fake_orcirc(nchan, pchan); tt_assert(orcirc); circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc), CELL_DIRECTION_OUT); circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc), CELL_DIRECTION_IN); /* Make a cell */ cell = tor_malloc_zero(sizeof(cell_t)); make_fake_cell(cell); MOCK(scheduler_channel_has_waiting_cells, scheduler_channel_has_waiting_cells_mock); MOCK(assert_circuit_ok, assert_circuit_ok_mock); /* Append it */ old_count = get_mock_scheduler_has_waiting_cells_count(); append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell, CELL_DIRECTION_OUT, 0); new_count = get_mock_scheduler_has_waiting_cells_count(); tt_int_op(new_count, OP_EQ, old_count + 1); /* Now try the reverse direction */ old_count = get_mock_scheduler_has_waiting_cells_count(); append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell, CELL_DIRECTION_IN, 0); new_count = get_mock_scheduler_has_waiting_cells_count(); tt_int_op(new_count, OP_EQ, old_count + 1); /* Ensure our write totals are 0 */ tt_u64_op(find_largest_max(write_array), OP_EQ, 0); /* Mark the circuit for close */ circuit_mark_for_close(TO_CIRCUIT(orcirc), 0); /* Check our write totals. */ advance_obs(write_array); commit_max(write_array); /* Check for two cells plus overhead */ tt_u64_op(find_largest_max(write_array), OP_EQ, 2*(get_cell_network_size(nchan->wide_circ_ids) +TLS_PER_CELL_OVERHEAD)); UNMOCK(scheduler_channel_has_waiting_cells); /* Get rid of the fake channels */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); channel_mark_for_close(nchan); channel_mark_for_close(pchan); UNMOCK(scheduler_release_channel); /* Shut down channels */ channel_free_all(); done: tor_free(cell); if (orcirc) { circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc)); circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc)); cell_queue_clear(&orcirc->base_.n_chan_cells); cell_queue_clear(&orcirc->p_chan_cells); } tor_free(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); UNMOCK(assert_circuit_ok); return; }
static void test_relay_append_cell_to_circuit_queue(void *arg) { channel_t *nchan = NULL, *pchan = NULL; or_circuit_t *orcirc = NULL; cell_t *cell = NULL; int old_count, new_count; (void)arg; /* Make fake channels to be nchan and pchan for the circuit */ nchan = new_fake_channel(); tt_assert(nchan); pchan = new_fake_channel(); tt_assert(pchan); /* Make a fake orcirc */ orcirc = new_fake_orcirc(nchan, pchan); tt_assert(orcirc); circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc), CELL_DIRECTION_OUT); circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc), CELL_DIRECTION_IN); /* Make a cell */ cell = tor_malloc_zero(sizeof(cell_t)); make_fake_cell(cell); MOCK(scheduler_channel_has_waiting_cells, scheduler_channel_has_waiting_cells_mock); /* Append it */ old_count = get_mock_scheduler_has_waiting_cells_count(); append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell, CELL_DIRECTION_OUT, 0); new_count = get_mock_scheduler_has_waiting_cells_count(); tt_int_op(new_count, OP_EQ, old_count + 1); /* Now try the reverse direction */ old_count = get_mock_scheduler_has_waiting_cells_count(); append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell, CELL_DIRECTION_IN, 0); new_count = get_mock_scheduler_has_waiting_cells_count(); tt_int_op(new_count, OP_EQ, old_count + 1); UNMOCK(scheduler_channel_has_waiting_cells); /* Get rid of the fake channels */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); channel_mark_for_close(nchan); channel_mark_for_close(pchan); UNMOCK(scheduler_release_channel); /* Shut down channels */ channel_free_all(); done: tor_free(cell); if (orcirc) { circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc)); circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc)); cell_queue_clear(&orcirc->base_.n_chan_cells); cell_queue_clear(&orcirc->p_chan_cells); } tor_free(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); return; }
/** Deallocate space associated with circ. */ static void circuit_free(circuit_t *circ) { void *mem; size_t memlen; if (!circ) return; if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); mem = ocirc; memlen = sizeof(origin_circuit_t); tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC); if (ocirc->build_state) { extend_info_free(ocirc->build_state->chosen_exit); circuit_free_cpath_node(ocirc->build_state->pending_final_cpath); cpath_ref_decref(ocirc->build_state->service_pending_final_cpath_ref); } tor_free(ocirc->build_state); circuit_free_cpath(ocirc->cpath); crypto_pk_free(ocirc->intro_key); rend_data_free(ocirc->rend_data); tor_free(ocirc->dest_address); if (ocirc->socks_username) { memwipe(ocirc->socks_username, 0x12, ocirc->socks_username_len); tor_free(ocirc->socks_username); } if (ocirc->socks_password) { memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len); tor_free(ocirc->socks_password); } } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); /* Remember cell statistics for this circuit before deallocating. */ if (get_options()->CellStatistics) rep_hist_buffer_stats_add_circ(circ, time(NULL)); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); crypto_cipher_free(ocirc->p_crypto); crypto_digest_free(ocirc->p_digest); crypto_cipher_free(ocirc->n_crypto); crypto_digest_free(ocirc->n_digest); if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC); other->rend_splice = NULL; } /* remove from map. */ circuit_set_p_circid_orconn(ocirc, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(ô->p_conn_cells); } extend_info_free(circ->n_hop); tor_free(circ->n_conn_onionskin); /* Remove from map. */ circuit_set_n_circid_orconn(circ, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(&circ->n_conn_cells); memwipe(mem, 0xAA, memlen); /* poison memory */ tor_free(mem); }
/** Deallocate space associated with circ. */ static void circuit_free(circuit_t *circ) { void *mem; size_t memlen; tor_assert(circ); if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); mem = ocirc; memlen = sizeof(origin_circuit_t); tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC); if (ocirc->build_state) { if (ocirc->build_state->chosen_exit) extend_info_free(ocirc->build_state->chosen_exit); if (ocirc->build_state->pending_final_cpath) circuit_free_cpath_node(ocirc->build_state->pending_final_cpath); } tor_free(ocirc->build_state); circuit_free_cpath(ocirc->cpath); if (ocirc->intro_key) crypto_free_pk_env(ocirc->intro_key); if (ocirc->rend_data) rend_data_free(ocirc->rend_data); } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); if (ocirc->p_crypto) crypto_free_cipher_env(ocirc->p_crypto); if (ocirc->p_digest) crypto_free_digest_env(ocirc->p_digest); if (ocirc->n_crypto) crypto_free_cipher_env(ocirc->n_crypto); if (ocirc->n_digest) crypto_free_digest_env(ocirc->n_digest); if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC); other->rend_splice = NULL; } /* remove from map. */ circuit_set_p_circid_orconn(ocirc, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(ô->p_conn_cells); } if (circ->n_hop) extend_info_free(circ->n_hop); tor_free(circ->n_conn_onionskin); /* Remove from map. */ circuit_set_n_circid_orconn(circ, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(&circ->n_conn_cells); memset(circ, 0xAA, memlen); /* poison memory */ tor_free(mem); }
static void test_cq_manip(void *arg) { packed_cell_t *pc1=NULL, *pc2=NULL, *pc3=NULL, *pc4=NULL, *pc_tmp=NULL; cell_queue_t cq; cell_t cell; (void) arg; cell_queue_init(&cq); tt_int_op(cq.n, OP_EQ, 0); pc1 = packed_cell_new(); pc2 = packed_cell_new(); pc3 = packed_cell_new(); pc4 = packed_cell_new(); tt_assert(pc1 && pc2 && pc3 && pc4); tt_ptr_op(NULL, OP_EQ, cell_queue_pop(&cq)); /* Add and remove a singleton. */ cell_queue_append(&cq, pc1); tt_int_op(cq.n, OP_EQ, 1); tt_ptr_op(pc1, OP_EQ, cell_queue_pop(&cq)); tt_int_op(cq.n, OP_EQ, 0); /* Add and remove four items */ cell_queue_append(&cq, pc4); cell_queue_append(&cq, pc3); cell_queue_append(&cq, pc2); cell_queue_append(&cq, pc1); tt_int_op(cq.n, OP_EQ, 4); tt_ptr_op(pc4, OP_EQ, cell_queue_pop(&cq)); tt_ptr_op(pc3, OP_EQ, cell_queue_pop(&cq)); tt_ptr_op(pc2, OP_EQ, cell_queue_pop(&cq)); tt_ptr_op(pc1, OP_EQ, cell_queue_pop(&cq)); tt_int_op(cq.n, OP_EQ, 0); tt_ptr_op(NULL, OP_EQ, cell_queue_pop(&cq)); /* Try a packed copy (wide, then narrow, which is a bit of a cheat, since a * real cell queue has only one type.) */ memset(&cell, 0, sizeof(cell)); cell.circ_id = 0x12345678; cell.command = 10; strlcpy((char*)cell.payload, "Lorax ipsum gruvvulus thneed amet, snergelly " "once-ler lerkim, sed do barbaloot tempor gluppitus ut labore et " "truffula magna aliqua.", sizeof(cell.payload)); cell_queue_append_packed_copy(NULL /*circ*/, &cq, 0 /*exitward*/, &cell, 1 /*wide*/, 0 /*stats*/); cell.circ_id = 0x2013; cell_queue_append_packed_copy(NULL /*circ*/, &cq, 0 /*exitward*/, &cell, 0 /*wide*/, 0 /*stats*/); tt_int_op(cq.n, OP_EQ, 2); pc_tmp = cell_queue_pop(&cq); tt_int_op(cq.n, OP_EQ, 1); tt_ptr_op(pc_tmp, OP_NE, NULL); tt_mem_op(pc_tmp->body, OP_EQ, "\x12\x34\x56\x78\x0a", 5); tt_mem_op(pc_tmp->body+5, OP_EQ, cell.payload, sizeof(cell.payload)); packed_cell_free(pc_tmp); pc_tmp = cell_queue_pop(&cq); tt_int_op(cq.n, OP_EQ, 0); tt_ptr_op(pc_tmp, OP_NE, NULL); tt_mem_op(pc_tmp->body, OP_EQ, "\x20\x13\x0a", 3); tt_mem_op(pc_tmp->body+3, OP_EQ, cell.payload, sizeof(cell.payload)); packed_cell_free(pc_tmp); pc_tmp = NULL; tt_ptr_op(NULL, OP_EQ, cell_queue_pop(&cq)); /* Now make sure cell_queue_clear works. */ cell_queue_append(&cq, pc2); cell_queue_append(&cq, pc1); tt_int_op(cq.n, OP_EQ, 2); cell_queue_clear(&cq); pc2 = pc1 = NULL; /* prevent double-free */ tt_int_op(cq.n, OP_EQ, 0); done: packed_cell_free(pc1); packed_cell_free(pc2); packed_cell_free(pc3); packed_cell_free(pc4); packed_cell_free(pc_tmp); cell_queue_clear(&cq); }