2010-07-22 12:09:49 +02:00
|
|
|
/* Copyright (c) 2001 Matej Pfajfar.
|
|
|
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2017-03-15 21:13:17 +01:00
|
|
|
* Copyright (c) 2007-2017, The Tor Project, Inc. */
|
2010-07-22 12:09:49 +02:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file dirserv.h
|
|
|
|
* \brief Header file for dirserv.c.
|
|
|
|
**/
|
|
|
|
|
2012-10-12 18:13:10 +02:00
|
|
|
#ifndef TOR_DIRSERV_H
|
|
|
|
#define TOR_DIRSERV_H
|
2010-07-22 12:09:49 +02:00
|
|
|
|
2013-06-06 23:58:28 +02:00
|
|
|
#include "testsupport.h"
|
|
|
|
|
2011-03-12 04:12:15 +01:00
|
|
|
/** What fraction (1 over this number) of the relay ID space do we
|
|
|
|
* (as a directory authority) launch connections to at each reachability
|
|
|
|
* test? */
|
|
|
|
#define REACHABILITY_MODULO_PER_TEST 128
|
|
|
|
|
2011-03-12 06:19:52 +01:00
|
|
|
/** How often (in seconds) do we launch reachability tests? */
|
|
|
|
#define REACHABILITY_TEST_INTERVAL 10
|
|
|
|
|
2011-03-12 04:12:15 +01:00
|
|
|
/** How many seconds apart are the reachability tests for a given relay? */
|
2011-03-12 06:19:52 +01:00
|
|
|
#define REACHABILITY_TEST_CYCLE_PERIOD \
|
|
|
|
(REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST)
|
2011-03-12 04:12:15 +01:00
|
|
|
|
2010-07-22 12:09:49 +02:00
|
|
|
/** Maximum length of an exit policy summary. */
|
|
|
|
#define MAX_EXITPOLICY_SUMMARY_LEN 1000
|
|
|
|
|
|
|
|
/** Maximum allowable length of a version line in a networkstatus. */
|
|
|
|
#define MAX_V_LINE_LEN 128
|
|
|
|
|
2017-03-13 20:38:20 +01:00
|
|
|
/** Ways to convert a spoolable_resource_t to a bunch of bytes. */
|
|
|
|
typedef enum dir_spool_source_t {
|
|
|
|
DIR_SPOOL_SERVER_BY_DIGEST=1, DIR_SPOOL_SERVER_BY_FP,
|
|
|
|
DIR_SPOOL_EXTRA_BY_DIGEST, DIR_SPOOL_EXTRA_BY_FP,
|
|
|
|
DIR_SPOOL_MICRODESC,
|
|
|
|
DIR_SPOOL_NETWORKSTATUS,
|
2017-04-16 23:47:28 +02:00
|
|
|
DIR_SPOOL_CONSENSUS_CACHE_ENTRY,
|
2017-03-13 20:38:20 +01:00
|
|
|
} dir_spool_source_t;
|
|
|
|
#define dir_spool_source_bitfield_t ENUM_BF(dir_spool_source_t)
|
|
|
|
|
|
|
|
/** Object to remember the identity of an object that we are spooling,
|
|
|
|
* or about to spool, in response to a directory request.
|
|
|
|
*
|
|
|
|
* (Why do we spool? Because some directory responses are very large,
|
|
|
|
* and we don't want to just shove the complete answer into the output
|
|
|
|
* buffer: that would take a ridiculous amount of RAM.)
|
|
|
|
*
|
|
|
|
* If the spooled resource is relatively small (like microdescriptors,
|
|
|
|
* descriptors, etc), we look them up by ID as needed, and add the whole
|
|
|
|
* thing onto the output buffer at once. If the spooled reseource is
|
|
|
|
* big (like networkstatus documents), we reference-count it, and add it
|
|
|
|
* a few K at a time.
|
|
|
|
*/
|
|
|
|
typedef struct spooled_resource_t {
|
|
|
|
/**
|
|
|
|
* If true, we add the entire object to the outbuf. If false,
|
|
|
|
* we spool the object a few K at a time.
|
|
|
|
*/
|
|
|
|
unsigned spool_eagerly : 1;
|
|
|
|
/**
|
|
|
|
* Tells us what kind of object to get, and how to look it up.
|
|
|
|
*/
|
|
|
|
dir_spool_source_bitfield_t spool_source : 7;
|
|
|
|
/**
|
|
|
|
* Tells us the specific object to spool.
|
|
|
|
*/
|
|
|
|
uint8_t digest[DIGEST256_LEN];
|
|
|
|
/**
|
|
|
|
* A large object that we're spooling. Holds a reference count. Only
|
|
|
|
* used when spool_eagerly is false.
|
|
|
|
*/
|
|
|
|
struct cached_dir_t *cached_dir_ref;
|
|
|
|
/**
|
2017-04-16 23:47:28 +02:00
|
|
|
* A different kind of large object that we might be spooling. Also
|
|
|
|
* reference-counted. Also only used when spool_eagerly is false.
|
|
|
|
*/
|
|
|
|
struct consensus_cache_entry_t *consensus_cache_entry;
|
|
|
|
const uint8_t *cce_body;
|
|
|
|
size_t cce_len;
|
|
|
|
/**
|
|
|
|
* The current offset into cached_dir or cce_body. Only used when
|
|
|
|
* spool_eagerly is false */
|
2017-03-13 20:38:20 +01:00
|
|
|
off_t cached_dir_offset;
|
|
|
|
} spooled_resource_t;
|
|
|
|
|
2010-07-22 12:09:49 +02:00
|
|
|
int connection_dirserv_flushed_some(dir_connection_t *conn);
|
|
|
|
|
2014-09-04 23:16:51 +02:00
|
|
|
int dirserv_add_own_fingerprint(crypto_pk_t *pk);
|
2010-07-22 12:09:49 +02:00
|
|
|
int dirserv_load_fingerprint_file(void);
|
|
|
|
void dirserv_free_fingerprint_list(void);
|
|
|
|
enum was_router_added_t dirserv_add_multiple_descriptors(
|
|
|
|
const char *desc, uint8_t purpose,
|
|
|
|
const char *source,
|
|
|
|
const char **msg);
|
|
|
|
enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri,
|
|
|
|
const char **msg,
|
|
|
|
const char *source);
|
|
|
|
void dirserv_set_router_is_running(routerinfo_t *router, time_t now);
|
|
|
|
int list_server_status_v1(smartlist_t *routers, char **router_status_out,
|
|
|
|
int for_controller);
|
2013-02-04 19:44:05 +01:00
|
|
|
char *dirserv_get_flag_thresholds_line(void);
|
2016-05-11 18:13:22 +02:00
|
|
|
void dirserv_compute_bridge_flag_thresholds(void);
|
2010-07-22 12:09:49 +02:00
|
|
|
|
2011-06-14 19:01:38 +02:00
|
|
|
int directory_fetches_from_authorities(const or_options_t *options);
|
|
|
|
int directory_fetches_dir_info_early(const or_options_t *options);
|
|
|
|
int directory_fetches_dir_info_later(const or_options_t *options);
|
2012-03-30 21:20:06 +02:00
|
|
|
int directory_caches_unknown_auth_certs(const or_options_t *options);
|
2011-06-14 19:01:38 +02:00
|
|
|
int directory_caches_dir_info(const or_options_t *options);
|
|
|
|
int directory_permits_begindir_requests(const or_options_t *options);
|
|
|
|
int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
|
|
|
|
time_t now);
|
2010-07-22 12:09:49 +02:00
|
|
|
|
|
|
|
cached_dir_t *dirserv_get_consensus(const char *flavor_name);
|
|
|
|
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
|
2016-02-10 21:35:46 +01:00
|
|
|
const char *flavor_name,
|
|
|
|
const common_digests_t *digests,
|
2017-05-03 16:17:37 +02:00
|
|
|
const uint8_t *sha3_as_signed,
|
2016-02-10 21:35:46 +01:00
|
|
|
time_t published);
|
2010-07-22 12:09:49 +02:00
|
|
|
void dirserv_clear_old_networkstatuses(time_t cutoff);
|
2017-03-13 20:38:20 +01:00
|
|
|
int dirserv_get_routerdesc_spool(smartlist_t *spools_out, const char *key,
|
|
|
|
dir_spool_source_t source,
|
2018-01-24 09:55:15 +01:00
|
|
|
int conn_is_encrypted,
|
2017-03-13 20:38:20 +01:00
|
|
|
const char **msg_out);
|
2010-07-22 12:09:49 +02:00
|
|
|
int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
|
|
|
|
const char **msg);
|
2012-05-09 17:58:01 +02:00
|
|
|
void dirserv_orconn_tls_done(const tor_addr_t *addr,
|
2010-07-22 12:09:49 +02:00
|
|
|
uint16_t or_port,
|
2016-09-24 20:25:48 +02:00
|
|
|
const char *digest_rcvd,
|
|
|
|
const ed25519_public_key_t *ed_id_rcvd);
|
2010-09-29 06:38:32 +02:00
|
|
|
int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
|
|
|
|
const routerinfo_t *ri_old);
|
2010-07-22 12:09:49 +02:00
|
|
|
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
|
|
|
|
void dirserv_test_reachability(time_t now);
|
|
|
|
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
int complain,
|
|
|
|
int *valid_out);
|
|
|
|
uint32_t dirserv_router_get_status(const routerinfo_t *router,
|
2015-07-31 16:47:39 +02:00
|
|
|
const char **msg,
|
|
|
|
int severity);
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
void dirserv_set_node_flags_from_authoritative_status(node_t *node,
|
|
|
|
uint32_t authstatus);
|
|
|
|
|
2010-09-29 07:35:08 +02:00
|
|
|
int dirserv_would_reject_router(const routerstatus_t *rs);
|
2013-02-20 06:55:34 +01:00
|
|
|
char *routerstatus_format_entry(
|
2016-08-25 20:55:41 +02:00
|
|
|
const routerstatus_t *rs,
|
|
|
|
const char *version,
|
|
|
|
const char *protocols,
|
Refactor storing of measured_bw versus Unmeasured=1.
This patch moves the measured_bw field and the has_measured_bw field
into vote_routerstatus_t, since only votes have 'Measured=XX' set on
their weight line.
I also added a new bw_is_unmeasured flag to routerstatus_t to
represent the Unmeasured=1 flag on a w line. Previously, I was using
has_measured_bw for this, which was quite incorrect: has_measured_bw
means that the measured_bw field is set, and it's probably a mistake
to have it serve double duty as meaning that 'baandwidth' represents a
measured value.
While making this change,I also found a harmless but stupid bug in
dirserv_read_measured_bandwidths: It assumes that it's getting a
smartlist of routerstatus_t, when really it's getting a smartlist of
vote_routerstatus_t. C's struct layout rules mean that we could never
actually get an error because of that, but it's still quite incorrect.
I fixed that, and in the process needed to add two more sorting and
searching helpers.
Finally, I made the Unmeasured=1 flag get parsed. We don't use it for
anything yet, but someday we might.
This isn't complete yet -- the new 2286 unit test doesn't build.
2013-02-19 16:39:27 +01:00
|
|
|
routerstatus_format_type_t format,
|
2017-10-15 18:09:52 +02:00
|
|
|
int consensus_method,
|
Refactor storing of measured_bw versus Unmeasured=1.
This patch moves the measured_bw field and the has_measured_bw field
into vote_routerstatus_t, since only votes have 'Measured=XX' set on
their weight line.
I also added a new bw_is_unmeasured flag to routerstatus_t to
represent the Unmeasured=1 flag on a w line. Previously, I was using
has_measured_bw for this, which was quite incorrect: has_measured_bw
means that the measured_bw field is set, and it's probably a mistake
to have it serve double duty as meaning that 'baandwidth' represents a
measured value.
While making this change,I also found a harmless but stupid bug in
dirserv_read_measured_bandwidths: It assumes that it's getting a
smartlist of routerstatus_t, when really it's getting a smartlist of
vote_routerstatus_t. C's struct layout rules mean that we could never
actually get an error because of that, but it's still quite incorrect.
I fixed that, and in the process needed to add two more sorting and
searching helpers.
Finally, I made the Unmeasured=1 flag get parsed. We don't use it for
anything yet, but someday we might.
This isn't complete yet -- the new 2286 unit test doesn't build.
2013-02-19 16:39:27 +01:00
|
|
|
const vote_routerstatus_t *vrs);
|
2010-07-22 12:09:49 +02:00
|
|
|
void dirserv_free_all(void);
|
|
|
|
void cached_dir_decref(cached_dir_t *d);
|
|
|
|
cached_dir_t *new_cached_dir(char *s, time_t published);
|
|
|
|
|
2015-01-09 17:36:47 +01:00
|
|
|
int validate_recommended_package_line(const char *line);
|
2018-04-25 17:20:59 +02:00
|
|
|
int dirserv_query_measured_bw_cache_kb(const char *node_id,
|
|
|
|
long *bw_out,
|
|
|
|
time_t *as_of_out);
|
|
|
|
void dirserv_clear_measured_bw_cache(void);
|
|
|
|
int dirserv_has_measured_bw(const char *node_id);
|
|
|
|
int dirserv_get_measured_bw_cache_size(void);
|
|
|
|
void dirserv_count_measured_bws(const smartlist_t *routers);
|
|
|
|
int running_long_enough_to_decide_unreachable(void);
|
|
|
|
void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil);
|
2015-01-09 17:36:47 +01:00
|
|
|
|
2010-07-22 12:09:49 +02:00
|
|
|
#ifdef DIRSERV_PRIVATE
|
2013-03-08 00:41:22 +01:00
|
|
|
|
2015-08-14 04:09:00 +02:00
|
|
|
STATIC void dirserv_set_routerstatus_testing(routerstatus_t *rs);
|
|
|
|
|
2013-03-08 00:41:22 +01:00
|
|
|
/* Put the MAX_MEASUREMENT_AGE #define here so unit tests can see it */
|
|
|
|
#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
|
|
|
|
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC int measured_bw_line_parse(measured_bw_line_t *out, const char *line);
|
2010-07-22 12:09:49 +02:00
|
|
|
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC int measured_bw_line_apply(measured_bw_line_t *parsed_line,
|
2010-07-22 12:09:49 +02:00
|
|
|
smartlist_t *routerstatuses);
|
2013-03-08 00:41:22 +01:00
|
|
|
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC void dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
|
2013-03-08 00:41:22 +01:00
|
|
|
time_t as_of);
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC void dirserv_expire_measured_bw_cache(time_t now);
|
2015-01-29 15:54:47 +01:00
|
|
|
|
|
|
|
STATIC int
|
|
|
|
dirserv_read_guardfraction_file_from_str(const char *guardfraction_file_str,
|
|
|
|
smartlist_t *vote_routerstatuses);
|
2017-09-15 22:24:44 +02:00
|
|
|
#endif /* defined(DIRSERV_PRIVATE) */
|
2010-07-22 12:09:49 +02:00
|
|
|
|
|
|
|
int dirserv_read_measured_bandwidths(const char *from_file,
|
|
|
|
smartlist_t *routerstatuses);
|
|
|
|
|
2015-01-29 15:54:47 +01:00
|
|
|
int dirserv_read_guardfraction_file(const char *fname,
|
|
|
|
smartlist_t *vote_routerstatuses);
|
|
|
|
|
2017-03-13 20:38:20 +01:00
|
|
|
spooled_resource_t *spooled_resource_new(dir_spool_source_t source,
|
|
|
|
const uint8_t *digest,
|
|
|
|
size_t digestlen);
|
2017-04-16 23:47:28 +02:00
|
|
|
spooled_resource_t *spooled_resource_new_from_cache_entry(
|
|
|
|
struct consensus_cache_entry_t *entry);
|
2017-11-21 15:37:47 +01:00
|
|
|
void spooled_resource_free_(spooled_resource_t *spooled);
|
2017-12-07 16:52:55 +01:00
|
|
|
#define spooled_resource_free(sp) \
|
|
|
|
FREE_AND_NULL(spooled_resource_t, spooled_resource_free_, (sp))
|
2017-03-13 20:38:20 +01:00
|
|
|
void dirserv_spool_remove_missing_and_guess_size(dir_connection_t *conn,
|
|
|
|
time_t cutoff,
|
|
|
|
int compression,
|
2017-03-28 21:41:59 +02:00
|
|
|
size_t *size_out,
|
2017-03-13 20:38:20 +01:00
|
|
|
int *n_expired_out);
|
|
|
|
void dirserv_spool_sort(dir_connection_t *conn);
|
|
|
|
void dir_conn_clear_spool(dir_connection_t *conn);
|
|
|
|
|
2017-09-15 22:24:44 +02:00
|
|
|
#endif /* !defined(TOR_DIRSERV_H) */
|
2010-07-22 12:09:49 +02:00
|
|
|
|