mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Handle other places that use onion handshake type values
We want ntor and ntorv3 to use the same queues and stats.
This commit is contained in:
parent
812590f8aa
commit
a0eeadfba2
@ -49,7 +49,6 @@
|
||||
#include "core/or/extend_info_st.h"
|
||||
#include "trunnel/circ_params.h"
|
||||
|
||||
/* TODO-324: Add this to the specification! */
|
||||
static const uint8_t NTOR3_CIRC_VERIFICATION[] = "circuit extend";
|
||||
static const size_t NTOR3_CIRC_VERIFICATION_LEN = 14;
|
||||
|
||||
|
@ -88,6 +88,10 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
|
||||
if (cell->handshake_len != NTOR_ONIONSKIN_LEN)
|
||||
return -1;
|
||||
break;
|
||||
case ONION_HANDSHAKE_TYPE_NTOR_V3:
|
||||
/* ntor v3 has variable length fields that are checked
|
||||
* elsewhere. Fall through to always valid here. */
|
||||
break;
|
||||
default:
|
||||
if (! unknown_ok)
|
||||
return -1;
|
||||
@ -521,6 +525,11 @@ create_cell_format_impl(cell_t *cell_out, const create_cell_t *cell_in,
|
||||
|
||||
switch (cell_in->cell_type) {
|
||||
case CELL_CREATE:
|
||||
if (BUG(cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR_V3)) {
|
||||
log_warn(LD_BUG, "Create cells cannot contain ntorv3.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
|
||||
memcpy(p, NTOR_CREATE_MAGIC, 16);
|
||||
p += 16;
|
||||
@ -619,6 +628,11 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
|
||||
switch (cell_in->cell_type) {
|
||||
case RELAY_COMMAND_EXTEND:
|
||||
{
|
||||
if (BUG(cell_in->create_cell.handshake_type ==
|
||||
ONION_HANDSHAKE_TYPE_NTOR_V3)) {
|
||||
log_warn(LD_BUG, "Extend cells cannot contain ntorv3!");
|
||||
return -1;
|
||||
}
|
||||
*command_out = RELAY_COMMAND_EXTEND;
|
||||
*len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN;
|
||||
set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
|
||||
|
@ -793,7 +793,7 @@ typedef enum {
|
||||
#define ONION_HANDSHAKE_TYPE_TAP 0x0000
|
||||
#define ONION_HANDSHAKE_TYPE_FAST 0x0001
|
||||
#define ONION_HANDSHAKE_TYPE_NTOR 0x0002
|
||||
#define ONION_HANDSHAKE_TYPE_NTOR_V3 0x0003 /* TODO-324: Add to spec */
|
||||
#define ONION_HANDSHAKE_TYPE_NTOR_V3 0x0003
|
||||
#define MAX_ONION_HANDSHAKE_TYPE 0x0003
|
||||
|
||||
typedef struct onion_handshake_state_t onion_handshake_state_t;
|
||||
|
@ -42,7 +42,7 @@
|
||||
typedef struct onion_queue_t {
|
||||
TOR_TAILQ_ENTRY(onion_queue_t) next;
|
||||
or_circuit_t *circ;
|
||||
uint16_t handshake_type;
|
||||
uint16_t queue_idx;
|
||||
create_cell_t *onionskin;
|
||||
time_t when_added;
|
||||
} onion_queue_t;
|
||||
@ -53,20 +53,41 @@ typedef struct onion_queue_t {
|
||||
TOR_TAILQ_HEAD(onion_queue_head_t, onion_queue_t);
|
||||
typedef struct onion_queue_head_t onion_queue_head_t;
|
||||
|
||||
/** We have 3 queues: tap, fast, and ntor. (ntorv3 goes into ntor queue). */
|
||||
#define MAX_QUEUE_IDX ONION_HANDSHAKE_TYPE_NTOR
|
||||
|
||||
/** Array of queues of circuits waiting for CPU workers. An element is NULL
|
||||
* if that queue is empty.*/
|
||||
static onion_queue_head_t ol_list[MAX_ONION_HANDSHAKE_TYPE+1] =
|
||||
static onion_queue_head_t ol_list[MAX_QUEUE_IDX+1] =
|
||||
{ TOR_TAILQ_HEAD_INITIALIZER(ol_list[0]), /* tap */
|
||||
TOR_TAILQ_HEAD_INITIALIZER(ol_list[1]), /* fast */
|
||||
TOR_TAILQ_HEAD_INITIALIZER(ol_list[2]), /* ntor */
|
||||
};
|
||||
|
||||
/** Number of entries of each type currently in each element of ol_list[]. */
|
||||
static int ol_entries[MAX_ONION_HANDSHAKE_TYPE+1];
|
||||
static int ol_entries[MAX_QUEUE_IDX+1];
|
||||
|
||||
static int num_ntors_per_tap(void);
|
||||
static void onion_queue_entry_remove(onion_queue_t *victim);
|
||||
|
||||
/**
|
||||
* We combine ntorv3 and ntor into the same queue, so we must
|
||||
* use this function to covert the cell type to a queue index.
|
||||
*/
|
||||
static inline uint16_t
|
||||
onionskin_type_to_queue(uint16_t type)
|
||||
{
|
||||
if (type == ONION_HANDSHAKE_TYPE_NTOR_V3) {
|
||||
return ONION_HANDSHAKE_TYPE_NTOR;
|
||||
}
|
||||
|
||||
if (BUG(type > MAX_QUEUE_IDX)) {
|
||||
return MAX_QUEUE_IDX; // use ntor if out of range
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* XXXX Check lengths vs MAX_ONIONSKIN_{CHALLENGE,REPLY}_LEN.
|
||||
*
|
||||
* (By which I think I meant, "make sure that no
|
||||
@ -144,6 +165,7 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
||||
{
|
||||
onion_queue_t *tmp;
|
||||
time_t now = time(NULL);
|
||||
uint16_t queue_idx = 0;
|
||||
|
||||
if (onionskin->handshake_type > MAX_ONION_HANDSHAKE_TYPE) {
|
||||
/* LCOV_EXCL_START
|
||||
@ -154,18 +176,20 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
queue_idx = onionskin_type_to_queue(onionskin->handshake_type);
|
||||
|
||||
tmp = tor_malloc_zero(sizeof(onion_queue_t));
|
||||
tmp->circ = circ;
|
||||
tmp->handshake_type = onionskin->handshake_type;
|
||||
tmp->queue_idx = queue_idx;
|
||||
tmp->onionskin = onionskin;
|
||||
tmp->when_added = now;
|
||||
|
||||
if (!have_room_for_onionskin(onionskin->handshake_type)) {
|
||||
if (!have_room_for_onionskin(queue_idx)) {
|
||||
#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL (60)
|
||||
static ratelim_t last_warned =
|
||||
RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL);
|
||||
rep_hist_note_circuit_handshake_dropped(onionskin->handshake_type);
|
||||
if (onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
|
||||
rep_hist_note_circuit_handshake_dropped(queue_idx);
|
||||
if (queue_idx == ONION_HANDSHAKE_TYPE_NTOR) {
|
||||
char *m;
|
||||
/* Note this ntor onionskin drop as an overload */
|
||||
rep_hist_note_overload(OVERLOAD_GENERAL);
|
||||
@ -183,18 +207,18 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
||||
return -1;
|
||||
}
|
||||
|
||||
++ol_entries[onionskin->handshake_type];
|
||||
++ol_entries[queue_idx];
|
||||
log_info(LD_OR, "New create (%s). Queues now ntor=%d and tap=%d.",
|
||||
onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap",
|
||||
queue_idx == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap",
|
||||
ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
|
||||
ol_entries[ONION_HANDSHAKE_TYPE_TAP]);
|
||||
|
||||
circ->onionqueue_entry = tmp;
|
||||
TOR_TAILQ_INSERT_TAIL(&ol_list[onionskin->handshake_type], tmp, next);
|
||||
TOR_TAILQ_INSERT_TAIL(&ol_list[queue_idx], tmp, next);
|
||||
|
||||
/* cull elderly requests. */
|
||||
while (1) {
|
||||
onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[onionskin->handshake_type]);
|
||||
onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[queue_idx]);
|
||||
if (now - head->when_added < (time_t)ONIONQUEUE_WAIT_CUTOFF)
|
||||
break;
|
||||
|
||||
@ -282,15 +306,15 @@ onion_next_task(create_cell_t **onionskin_out)
|
||||
return NULL; /* no onions pending, we're done */
|
||||
|
||||
tor_assert(head->circ);
|
||||
tor_assert(head->handshake_type <= MAX_ONION_HANDSHAKE_TYPE);
|
||||
tor_assert(head->queue_idx <= MAX_QUEUE_IDX);
|
||||
// tor_assert(head->circ->p_chan); /* make sure it's still valid */
|
||||
/* XXX I only commented out the above line to make the unit tests
|
||||
* more manageable. That's probably not good long-term. -RD */
|
||||
circ = head->circ;
|
||||
if (head->onionskin)
|
||||
--ol_entries[head->handshake_type];
|
||||
--ol_entries[head->queue_idx];
|
||||
log_info(LD_OR, "Processing create (%s). Queues now ntor=%d and tap=%d.",
|
||||
head->handshake_type == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap",
|
||||
head->queue_idx == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap",
|
||||
ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
|
||||
ol_entries[ONION_HANDSHAKE_TYPE_TAP]);
|
||||
|
||||
@ -306,7 +330,7 @@ onion_next_task(create_cell_t **onionskin_out)
|
||||
int
|
||||
onion_num_pending(uint16_t handshake_type)
|
||||
{
|
||||
return ol_entries[handshake_type];
|
||||
return ol_entries[onionskin_type_to_queue(handshake_type)];
|
||||
}
|
||||
|
||||
/** Go through ol_list, find the onion_queue_t element which points to
|
||||
@ -332,23 +356,23 @@ onion_pending_remove(or_circuit_t *circ)
|
||||
static void
|
||||
onion_queue_entry_remove(onion_queue_t *victim)
|
||||
{
|
||||
if (victim->handshake_type > MAX_ONION_HANDSHAKE_TYPE) {
|
||||
if (victim->queue_idx > MAX_QUEUE_IDX) {
|
||||
/* LCOV_EXCL_START
|
||||
* We should have rejected this far before this point */
|
||||
log_warn(LD_BUG, "Handshake %d out of range! Dropping.",
|
||||
victim->handshake_type);
|
||||
victim->queue_idx);
|
||||
/* XXX leaks */
|
||||
return;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
TOR_TAILQ_REMOVE(&ol_list[victim->handshake_type], victim, next);
|
||||
TOR_TAILQ_REMOVE(&ol_list[victim->queue_idx], victim, next);
|
||||
|
||||
if (victim->circ)
|
||||
victim->circ->onionqueue_entry = NULL;
|
||||
|
||||
if (victim->onionskin)
|
||||
--ol_entries[victim->handshake_type];
|
||||
--ol_entries[victim->queue_idx];
|
||||
|
||||
tor_free(victim->onionskin);
|
||||
tor_free(victim);
|
||||
@ -360,7 +384,7 @@ clear_pending_onions(void)
|
||||
{
|
||||
onion_queue_t *victim, *next;
|
||||
int i;
|
||||
for (i=0; i<=MAX_ONION_HANDSHAKE_TYPE; i++) {
|
||||
for (i=0; i<=MAX_QUEUE_IDX; i++) {
|
||||
for (victim = TOR_TAILQ_FIRST(&ol_list[i]); victim; victim = next) {
|
||||
next = TOR_TAILQ_NEXT(victim,next);
|
||||
onion_queue_entry_remove(victim);
|
||||
|
@ -2053,21 +2053,38 @@ rep_hist_note_desc_served(const char * desc)
|
||||
*
|
||||
* They are reset at every heartbeat.
|
||||
* @{ */
|
||||
STATIC int onion_handshakes_requested[MAX_ONION_HANDSHAKE_TYPE+1] = {0};
|
||||
STATIC int onion_handshakes_assigned[MAX_ONION_HANDSHAKE_TYPE+1] = {0};
|
||||
STATIC int onion_handshakes_requested[MAX_ONION_STAT_TYPE+1] = {0};
|
||||
STATIC int onion_handshakes_assigned[MAX_ONION_STAT_TYPE+1] = {0};
|
||||
/**@}*/
|
||||
|
||||
/** Counters keeping the same stats as above but for the entire duration of the
|
||||
* process (not reset). */
|
||||
static uint64_t stats_n_onionskin_assigned[MAX_ONION_HANDSHAKE_TYPE+1] = {0};
|
||||
static uint64_t stats_n_onionskin_dropped[MAX_ONION_HANDSHAKE_TYPE+1] = {0};
|
||||
static uint64_t stats_n_onionskin_assigned[MAX_ONION_STAT_TYPE+1] = {0};
|
||||
static uint64_t stats_n_onionskin_dropped[MAX_ONION_STAT_TYPE+1] = {0};
|
||||
|
||||
/**
|
||||
* We combine ntorv3 and ntor into the same stat, so we must
|
||||
* use this function to covert the cell type to a stat index.
|
||||
*/
|
||||
static inline uint16_t
|
||||
onionskin_type_to_stat(uint16_t type)
|
||||
{
|
||||
if (type == ONION_HANDSHAKE_TYPE_NTOR_V3) {
|
||||
return ONION_HANDSHAKE_TYPE_NTOR;
|
||||
}
|
||||
|
||||
if (BUG(type > MAX_ONION_STAT_TYPE)) {
|
||||
return MAX_ONION_STAT_TYPE; // use ntor if out of range
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/** A new onionskin (using the <b>type</b> handshake) has arrived. */
|
||||
void
|
||||
rep_hist_note_circuit_handshake_requested(uint16_t type)
|
||||
{
|
||||
if (type <= MAX_ONION_HANDSHAKE_TYPE)
|
||||
onion_handshakes_requested[type]++;
|
||||
onion_handshakes_requested[onionskin_type_to_stat(type)]++;
|
||||
}
|
||||
|
||||
/** We've sent an onionskin (using the <b>type</b> handshake) to a
|
||||
@ -2075,10 +2092,8 @@ rep_hist_note_circuit_handshake_requested(uint16_t type)
|
||||
void
|
||||
rep_hist_note_circuit_handshake_assigned(uint16_t type)
|
||||
{
|
||||
if (type <= MAX_ONION_HANDSHAKE_TYPE) {
|
||||
onion_handshakes_assigned[type]++;
|
||||
stats_n_onionskin_assigned[type]++;
|
||||
}
|
||||
onion_handshakes_assigned[onionskin_type_to_stat(type)]++;
|
||||
stats_n_onionskin_assigned[onionskin_type_to_stat(type)]++;
|
||||
}
|
||||
|
||||
/** We've just drop an onionskin (using the <b>type</b> handshake) due to being
|
||||
@ -2086,49 +2101,35 @@ rep_hist_note_circuit_handshake_assigned(uint16_t type)
|
||||
void
|
||||
rep_hist_note_circuit_handshake_dropped(uint16_t type)
|
||||
{
|
||||
if (type <= MAX_ONION_HANDSHAKE_TYPE) {
|
||||
stats_n_onionskin_dropped[type]++;
|
||||
}
|
||||
stats_n_onionskin_dropped[onionskin_type_to_stat(type)]++;
|
||||
}
|
||||
|
||||
/** Get the circuit handshake value that is requested. */
|
||||
MOCK_IMPL(int,
|
||||
rep_hist_get_circuit_handshake_requested, (uint16_t type))
|
||||
{
|
||||
if (BUG(type > MAX_ONION_HANDSHAKE_TYPE)) {
|
||||
return 0;
|
||||
}
|
||||
return onion_handshakes_requested[type];
|
||||
return onion_handshakes_requested[onionskin_type_to_stat(type)];
|
||||
}
|
||||
|
||||
/** Get the circuit handshake value that is assigned. */
|
||||
MOCK_IMPL(int,
|
||||
rep_hist_get_circuit_handshake_assigned, (uint16_t type))
|
||||
{
|
||||
if (BUG(type > MAX_ONION_HANDSHAKE_TYPE)) {
|
||||
return 0;
|
||||
}
|
||||
return onion_handshakes_assigned[type];
|
||||
return onion_handshakes_assigned[onionskin_type_to_stat(type)];
|
||||
}
|
||||
|
||||
/** Get the total number of circuit handshake value that is assigned. */
|
||||
MOCK_IMPL(uint64_t,
|
||||
rep_hist_get_circuit_n_handshake_assigned, (uint16_t type))
|
||||
{
|
||||
if (BUG(type > MAX_ONION_HANDSHAKE_TYPE)) {
|
||||
return 0;
|
||||
}
|
||||
return stats_n_onionskin_assigned[type];
|
||||
return stats_n_onionskin_assigned[onionskin_type_to_stat(type)];
|
||||
}
|
||||
|
||||
/** Get the total number of circuit handshake value that is dropped. */
|
||||
MOCK_IMPL(uint64_t,
|
||||
rep_hist_get_circuit_n_handshake_dropped, (uint16_t type))
|
||||
{
|
||||
if (BUG(type > MAX_ONION_HANDSHAKE_TYPE)) {
|
||||
return 0;
|
||||
}
|
||||
return stats_n_onionskin_dropped[type];
|
||||
return stats_n_onionskin_dropped[onionskin_type_to_stat(type)];
|
||||
}
|
||||
|
||||
/** Log our onionskin statistics since the last time we were called. */
|
||||
|
@ -89,11 +89,15 @@ uint64_t rep_hist_get_n_dns_request(int type);
|
||||
void rep_hist_note_dns_request(int type);
|
||||
void rep_hist_note_dns_error(int type, uint8_t error);
|
||||
|
||||
/** We combine ntor and ntorv3 stats, so we have 3 stat types:
|
||||
* tap, fast, and ntor. The max type is ntor (2) */
|
||||
#define MAX_ONION_STAT_TYPE ONION_HANDSHAKE_TYPE_NTOR
|
||||
|
||||
extern uint64_t rephist_total_alloc;
|
||||
extern uint32_t rephist_total_num;
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern int onion_handshakes_requested[MAX_ONION_HANDSHAKE_TYPE+1];
|
||||
extern int onion_handshakes_assigned[MAX_ONION_HANDSHAKE_TYPE+1];
|
||||
extern int onion_handshakes_requested[MAX_ONION_STAT_TYPE+1];
|
||||
extern int onion_handshakes_assigned[MAX_ONION_STAT_TYPE+1];
|
||||
#endif
|
||||
|
||||
#ifdef REPHIST_PRIVATE
|
||||
|
Loading…
Reference in New Issue
Block a user