/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell * down introcirc if possible. */ int rend_client_send_introduction(origin_circuit_t *introcirc, origin_circuit_t *rendcirc) { const or_options_t *options = get_options(); size_t payload_len; int r, v3_shift = 0; char payload[RELAY_PAYLOAD_SIZE]; char tmp[RELAY_PAYLOAD_SIZE]; rend_cache_entry_t *entry = NULL; crypt_path_t *cpath; off_t dh_offset; crypto_pk_t *intro_key = NULL; int status = 0; const char *onion_address; tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY); tor_assert(introcirc->rend_data); tor_assert(rendcirc->rend_data); tor_assert(!rend_cmp_service_ids(rend_data_get_address(introcirc->rend_data), rend_data_get_address(rendcirc->rend_data))); assert_circ_anonymity_ok(introcirc, options); assert_circ_anonymity_ok(rendcirc, options); onion_address = rend_data_get_address(introcirc->rend_data); r = rend_cache_lookup_entry(onion_address, -1, &entry); /* An invalid onion address is not possible else we have a big issue. */ tor_assert(r != -EINVAL); if (r < 0 || !rend_client_any_intro_points_usable(entry)) { /* If the descriptor is not found or the intro points are not usable * anymore, trigger a fetch. */ log_info(LD_REND, "query %s didn't have valid rend desc in cache. " "Refetching descriptor.", safe_str_client(onion_address)); rend_client_refetch_v2_renddesc(introcirc->rend_data); { connection_t *conn; while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, AP_CONN_STATE_CIRCUIT_WAIT, onion_address))) { connection_ap_mark_as_waiting_for_renddesc(TO_ENTRY_CONN(conn)); } } status = -1; goto cleanup; } /* first 20 bytes of payload are the hash of the service's pk */ intro_key = NULL; SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { intro_key = intro->intro_key; break; } });
/** If we aren't currently dormant, close all connections and become * dormant. */ static void hibernate_go_dormant(time_t now) { connection_t *conn; if (hibernate_state == HIBERNATE_STATE_DORMANT) return; else if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) hibernate_state = HIBERNATE_STATE_DORMANT; else hibernate_begin(HIBERNATE_STATE_DORMANT, now); log_notice(LD_ACCT,"Going dormant. Blowing away remaining connections."); /* Close all OR/AP/exit conns. Leave dir conns because we still want * to be able to upload server descriptors so people know we're still * running, and download directories so we can detect if we're obsolete. * Leave control conns because we still want to be controllable. */ while ((conn = connection_get_by_type(CONN_TYPE_OR)) || (conn = connection_get_by_type(CONN_TYPE_AP)) || (conn = connection_get_by_type(CONN_TYPE_EXIT))) { if (CONN_IS_EDGE(conn)) connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING); log_info(LD_NET,"Closing conn type %d", conn->type); if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */ connection_mark_unattached_ap(TO_ENTRY_CONN(conn), END_STREAM_REASON_HIBERNATING); else if (conn->type == CONN_TYPE_OR) { if (TO_OR_CONN(conn)->chan) { channel_mark_for_close(TLS_CHAN_TO_BASE(TO_OR_CONN(conn)->chan)); } else { connection_mark_for_close(conn); } } else connection_mark_for_close(conn); } if (now < interval_wakeup_time) hibernate_end_time = interval_wakeup_time; else hibernate_end_time = interval_end_time; accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), get_options()->AvoidDiskWrites ? now+600 : 0); }
static int test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg) { (void)tc; connection_t *conn = arg; tt_assert(conn); assert_connection_ok(conn, time(NULL)); /* teardown the connection as fast as possible */ if (conn->linked_conn) { assert_connection_ok(conn->linked_conn, time(NULL)); /* We didn't call tor_libevent_initialize(), so event_base was NULL, * so we can't rely on connection_unregister_events() use of event_del(). */ if (conn->linked_conn->read_event) { tor_free(conn->linked_conn->read_event); conn->linked_conn->read_event = NULL; } if (conn->linked_conn->write_event) { tor_free(conn->linked_conn->write_event); conn->linked_conn->write_event = NULL; } if (!conn->linked_conn->marked_for_close) { connection_close_immediate(conn->linked_conn); if (CONN_IS_EDGE(conn->linked_conn)) { /* Suppress warnings about all the stuff we didn't do */ TO_EDGE_CONN(conn->linked_conn)->edge_has_sent_end = 1; TO_EDGE_CONN(conn->linked_conn)->end_reason = END_STREAM_REASON_INTERNAL; if (conn->linked_conn->type == CONN_TYPE_AP) { TO_ENTRY_CONN(conn->linked_conn)->socks_request->has_finished = 1; } } connection_mark_for_close(conn->linked_conn); } close_closeable_connections(); } /* We didn't set the events up properly, so we can't use event_del() in * close_closeable_connections() > connection_free() * > connection_unregister_events() */ if (conn->read_event) { tor_free(conn->read_event); conn->read_event = NULL; } if (conn->write_event) { tor_free(conn->write_event); conn->write_event = NULL; } if (!conn->marked_for_close) { connection_close_immediate(conn); if (CONN_IS_EDGE(conn)) { /* Suppress warnings about all the stuff we didn't do */ TO_EDGE_CONN(conn)->edge_has_sent_end = 1; TO_EDGE_CONN(conn)->end_reason = END_STREAM_REASON_INTERNAL; if (conn->type == CONN_TYPE_AP) { TO_ENTRY_CONN(conn)->socks_request->has_finished = 1; } } connection_mark_for_close(conn); } close_closeable_connections(); /* The unit test will fail if we return 0 */ return 1; /* When conn == NULL, we can't cleanup anything */ done: return 0; }