mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Split directory.c code into several modules
Parts of this C file naturally belong in dircache, dirclient, and dircommon: so, move them there.
This commit is contained in:
parent
0e4c42a912
commit
194acfb51d
3
changes/ticket26744
Normal file
3
changes/ticket26744
Normal file
@ -0,0 +1,3 @@
|
||||
o Code simplification and refactoring:
|
||||
- Split directory.c into separate pieces for client, server, and
|
||||
common functionality. Closes ticket 26744.
|
@ -62,9 +62,12 @@ LIBTOR_APP_A_SOURCES = \
|
||||
src/feature/dirauth/keypin.c \
|
||||
src/feature/dircache/conscache.c \
|
||||
src/feature/dircache/consdiffmgr.c \
|
||||
src/feature/dircache/directory.c \
|
||||
src/feature/dircache/dircache.c \
|
||||
src/feature/dircache/dirserv.c \
|
||||
src/feature/dirclient/dirclient.c \
|
||||
src/feature/dirclient/dlstatus.c \
|
||||
src/feature/dircommon/consdiff.c \
|
||||
src/feature/dircommon/directory.c \
|
||||
src/feature/dircommon/fp_pair.c \
|
||||
src/feature/dircommon/voting_schedule.c \
|
||||
src/feature/hibernate/hibernate.c \
|
||||
@ -257,12 +260,15 @@ noinst_HEADERS += \
|
||||
src/feature/dircache/cached_dir_st.h \
|
||||
src/feature/dircache/conscache.h \
|
||||
src/feature/dircache/consdiffmgr.h \
|
||||
src/feature/dircache/directory.h \
|
||||
src/feature/dircache/dircache.h \
|
||||
src/feature/dircache/dirserv.h \
|
||||
src/feature/dirclient/dir_server_st.h \
|
||||
src/feature/dirclient/dirclient.h \
|
||||
src/feature/dirclient/dlstatus.h \
|
||||
src/feature/dirclient/download_status_st.h \
|
||||
src/feature/dircommon/consdiff.h \
|
||||
src/feature/dircommon/dir_connection_st.h \
|
||||
src/feature/dircommon/directory.h \
|
||||
src/feature/dircommon/fp_pair.h \
|
||||
src/feature/dircommon/vote_timing_st.h \
|
||||
src/feature/dircommon/voting_schedule.h \
|
||||
|
@ -77,7 +77,7 @@
|
||||
#include "core/or/connection_or.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/relay/dns.h"
|
||||
#include "feature/client/dnsserv.h"
|
||||
|
@ -68,7 +68,7 @@
|
||||
#include "feature/control/control.h"
|
||||
#include "core/mainloop/cpuworker.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirauth/reachability.h"
|
||||
#include "feature/relay/dns.h"
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "core/or/connection_or.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "core/crypto/hs_ntor.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
|
@ -69,7 +69,7 @@
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "lib/crypt_ops/crypto_dh.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "feature/hs/hs_circuit.h"
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "core/or/connection_edge.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/hs/hs_common.h"
|
||||
#include "feature/hs/hs_client.h"
|
||||
|
@ -73,7 +73,7 @@
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/relay/dns.h"
|
||||
#include "feature/client/dnsserv.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/hibernate/hibernate.h"
|
||||
#include "feature/hs/hs_common.h"
|
||||
|
@ -63,7 +63,7 @@
|
||||
#include "feature/control/control.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/relay/dns.h"
|
||||
#include "feature/stats/geoip.h"
|
||||
#include "feature/hs/hs_cache.h"
|
||||
|
@ -18,7 +18,9 @@
|
||||
#include "core/or/circuitbuild.h"
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "core/or/policies.h"
|
||||
|
@ -125,7 +125,7 @@
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "feature/nodelist/microdesc.h"
|
||||
|
@ -56,7 +56,9 @@
|
||||
#include "feature/control/fmt_serverstatus.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/client/dnsserv.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include "feature/dirauth/dircollate.h"
|
||||
#include "feature/dirauth/recommend_pkg.h"
|
||||
#include "feature/dirauth/voteflags.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirauth/bwauth.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirauth/guardfraction.h"
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "core/or/policies.h"
|
||||
#include "feature/dirauth/keypin.h"
|
||||
#include "feature/dirauth/reachability.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "feature/nodelist/routerlist.h"
|
||||
|
1739
src/feature/dircache/dircache.c
Normal file
1739
src/feature/dircache/dircache.c
Normal file
File diff suppressed because it is too large
Load Diff
43
src/feature/dircache/dircache.h
Normal file
43
src/feature/dircache/dircache.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file dircache.h
|
||||
* \brief Header file for dircache.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_DIRCACHE_H
|
||||
#define TOR_DIRCACHE_H
|
||||
|
||||
int directory_handle_command(dir_connection_t *conn);
|
||||
|
||||
#ifdef DIRCACHE_PRIVATE
|
||||
MOCK_DECL(STATIC int, directory_handle_command_get,(dir_connection_t *conn,
|
||||
const char *headers,
|
||||
const char *req_body,
|
||||
size_t req_body_len));
|
||||
MOCK_DECL(STATIC int, directory_handle_command_post,(dir_connection_t *conn,
|
||||
const char *headers,
|
||||
const char *body,
|
||||
size_t body_len));
|
||||
|
||||
STATIC int handle_post_hs_descriptor(const char *url, const char *body);
|
||||
enum compression_level_t;
|
||||
STATIC enum compression_level_t choose_compression_level(ssize_t n_bytes);
|
||||
|
||||
struct get_handler_args_t;
|
||||
STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn,
|
||||
const struct get_handler_args_t *args);
|
||||
|
||||
STATIC int parse_http_url(const char *headers, char **url);
|
||||
|
||||
STATIC int parse_hs_version_from_post(const char *url, const char *prefix,
|
||||
const char **end_pos);
|
||||
|
||||
STATIC unsigned parse_accept_encoding_header(const char *h);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_DIRCACHE_H) */
|
@ -1,347 +0,0 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file directory.h
|
||||
* \brief Header file for directory.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_DIRECTORY_H
|
||||
#define TOR_DIRECTORY_H
|
||||
|
||||
#include "feature/hs/hs_ident.h"
|
||||
enum compress_method_t;
|
||||
|
||||
dir_connection_t *TO_DIR_CONN(connection_t *c);
|
||||
|
||||
#define DIR_CONN_STATE_MIN_ 1
|
||||
/** State for connection to directory server: waiting for connect(). */
|
||||
#define DIR_CONN_STATE_CONNECTING 1
|
||||
/** State for connection to directory server: sending HTTP request. */
|
||||
#define DIR_CONN_STATE_CLIENT_SENDING 2
|
||||
/** State for connection to directory server: reading HTTP response. */
|
||||
#define DIR_CONN_STATE_CLIENT_READING 3
|
||||
/** State for connection to directory server: happy and finished. */
|
||||
#define DIR_CONN_STATE_CLIENT_FINISHED 4
|
||||
/** State for connection at directory server: waiting for HTTP request. */
|
||||
#define DIR_CONN_STATE_SERVER_COMMAND_WAIT 5
|
||||
/** State for connection at directory server: sending HTTP response. */
|
||||
#define DIR_CONN_STATE_SERVER_WRITING 6
|
||||
#define DIR_CONN_STATE_MAX_ 6
|
||||
|
||||
#define DIR_PURPOSE_MIN_ 4
|
||||
/** A connection to a directory server: set after a v2 rendezvous
|
||||
* descriptor is downloaded. */
|
||||
#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
|
||||
/** A connection to a directory server: download one or more server
|
||||
* descriptors. */
|
||||
#define DIR_PURPOSE_FETCH_SERVERDESC 6
|
||||
/** A connection to a directory server: download one or more extra-info
|
||||
* documents. */
|
||||
#define DIR_PURPOSE_FETCH_EXTRAINFO 7
|
||||
/** A connection to a directory server: upload a server descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_DIR 8
|
||||
/** A connection to a directory server: upload a v3 networkstatus vote. */
|
||||
#define DIR_PURPOSE_UPLOAD_VOTE 10
|
||||
/** A connection to a directory server: upload a v3 consensus signature */
|
||||
#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
|
||||
/** A connection to a directory server: download one or more v3 networkstatus
|
||||
* votes. */
|
||||
#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
|
||||
/** A connection to a directory server: download a v3 detached signatures
|
||||
* object for a consensus. */
|
||||
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
|
||||
/** A connection to a directory server: download a v3 networkstatus
|
||||
* consensus. */
|
||||
#define DIR_PURPOSE_FETCH_CONSENSUS 14
|
||||
/** A connection to a directory server: download one or more directory
|
||||
* authority certificates. */
|
||||
#define DIR_PURPOSE_FETCH_CERTIFICATE 15
|
||||
|
||||
/** Purpose for connection at a directory server. */
|
||||
#define DIR_PURPOSE_SERVER 16
|
||||
/** A connection to a hidden service directory server: upload a v2 rendezvous
|
||||
* descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_RENDDESC_V2 17
|
||||
/** A connection to a hidden service directory server: download a v2 rendezvous
|
||||
* descriptor. */
|
||||
#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
|
||||
/** A connection to a directory server: download a microdescriptor. */
|
||||
#define DIR_PURPOSE_FETCH_MICRODESC 19
|
||||
/** A connection to a hidden service directory: upload a v3 descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_HSDESC 20
|
||||
/** A connection to a hidden service directory: fetch a v3 descriptor. */
|
||||
#define DIR_PURPOSE_FETCH_HSDESC 21
|
||||
/** A connection to a directory server: set after a hidden service descriptor
|
||||
* is downloaded. */
|
||||
#define DIR_PURPOSE_HAS_FETCHED_HSDESC 22
|
||||
#define DIR_PURPOSE_MAX_ 22
|
||||
|
||||
/** True iff <b>p</b> is a purpose corresponding to uploading
|
||||
* data to a directory server. */
|
||||
#define DIR_PURPOSE_IS_UPLOAD(p) \
|
||||
((p)==DIR_PURPOSE_UPLOAD_DIR || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_VOTE || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_SIGNATURES || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_RENDDESC_V2 || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_HSDESC)
|
||||
|
||||
int directories_have_accepted_server_descriptor(void);
|
||||
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
dirinfo_type_t type, const char *payload,
|
||||
size_t payload_len, size_t extrainfo_len);
|
||||
MOCK_DECL(void, directory_get_from_dirserver, (
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
const char *resource,
|
||||
int pds_flags,
|
||||
download_want_authority_t want_authority));
|
||||
void directory_get_from_all_authorities(uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
const char *resource);
|
||||
|
||||
/** Enumeration of ways to connect to a directory server */
|
||||
typedef enum {
|
||||
/** Default: connect over a one-hop Tor circuit. Relays fall back to direct
|
||||
* DirPort connections, clients, onion services, and bridges do not */
|
||||
DIRIND_ONEHOP=0,
|
||||
/** Connect over a multi-hop anonymizing Tor circuit */
|
||||
DIRIND_ANONYMOUS=1,
|
||||
/** Connect to the DirPort directly */
|
||||
DIRIND_DIRECT_CONN,
|
||||
/** Connect over a multi-hop anonymizing Tor circuit to our dirport */
|
||||
DIRIND_ANON_DIRPORT,
|
||||
} dir_indirection_t;
|
||||
|
||||
int directory_must_use_begindir(const or_options_t *options);
|
||||
|
||||
/**
|
||||
* A directory_request_t describes the information about a directory request
|
||||
* at the client side. It describes what we're going to ask for, which
|
||||
* directory we're going to ask for it, how we're going to contact that
|
||||
* directory, and (in some cases) what to do with it when we're done.
|
||||
*/
|
||||
typedef struct directory_request_t directory_request_t;
|
||||
directory_request_t *directory_request_new(uint8_t dir_purpose);
|
||||
void directory_request_free_(directory_request_t *req);
|
||||
#define directory_request_free(req) \
|
||||
FREE_AND_NULL(directory_request_t, directory_request_free_, (req))
|
||||
void directory_request_set_or_addr_port(directory_request_t *req,
|
||||
const tor_addr_port_t *p);
|
||||
void directory_request_set_dir_addr_port(directory_request_t *req,
|
||||
const tor_addr_port_t *p);
|
||||
void directory_request_set_directory_id_digest(directory_request_t *req,
|
||||
const char *digest);
|
||||
struct circuit_guard_state_t;
|
||||
void directory_request_set_guard_state(directory_request_t *req,
|
||||
struct circuit_guard_state_t *state);
|
||||
void directory_request_set_router_purpose(directory_request_t *req,
|
||||
uint8_t router_purpose);
|
||||
void directory_request_set_indirection(directory_request_t *req,
|
||||
dir_indirection_t indirection);
|
||||
void directory_request_set_resource(directory_request_t *req,
|
||||
const char *resource);
|
||||
void directory_request_set_payload(directory_request_t *req,
|
||||
const char *payload,
|
||||
size_t payload_len);
|
||||
void directory_request_set_if_modified_since(directory_request_t *req,
|
||||
time_t if_modified_since);
|
||||
void directory_request_set_rend_query(directory_request_t *req,
|
||||
const rend_data_t *query);
|
||||
void directory_request_upload_set_hs_ident(directory_request_t *req,
|
||||
const hs_ident_dir_conn_t *ident);
|
||||
void directory_request_fetch_set_hs_ident(directory_request_t *req,
|
||||
const hs_ident_dir_conn_t *ident);
|
||||
|
||||
void directory_request_set_routerstatus(directory_request_t *req,
|
||||
const routerstatus_t *rs);
|
||||
void directory_request_add_header(directory_request_t *req,
|
||||
const char *key,
|
||||
const char *val);
|
||||
MOCK_DECL(void, directory_initiate_request, (directory_request_t *request));
|
||||
|
||||
int parse_http_response(const char *headers, int *code, time_t *date,
|
||||
enum compress_method_t *compression, char **response);
|
||||
int parse_http_command(const char *headers,
|
||||
char **command_out, char **url_out);
|
||||
char *http_get_header(const char *headers, const char *which);
|
||||
|
||||
int connection_dir_is_encrypted(const dir_connection_t *conn);
|
||||
int connection_dir_reached_eof(dir_connection_t *conn);
|
||||
int connection_dir_process_inbuf(dir_connection_t *conn);
|
||||
int connection_dir_finished_flushing(dir_connection_t *conn);
|
||||
int connection_dir_finished_connecting(dir_connection_t *conn);
|
||||
void connection_dir_about_to_close(dir_connection_t *dir_conn);
|
||||
|
||||
#define DSR_HEX (1<<0)
|
||||
#define DSR_BASE64 (1<<1)
|
||||
#define DSR_DIGEST256 (1<<2)
|
||||
#define DSR_SORT_UNIQ (1<<3)
|
||||
int dir_split_resource_into_fingerprints(const char *resource,
|
||||
smartlist_t *fp_out, int *compressed_out,
|
||||
int flags);
|
||||
enum dir_spool_source_t;
|
||||
int dir_split_resource_into_spoolable(const char *resource,
|
||||
enum dir_spool_source_t source,
|
||||
smartlist_t *spool_out,
|
||||
int *compressed_out,
|
||||
int flags);
|
||||
int dir_split_resource_into_fingerprint_pairs(const char *res,
|
||||
smartlist_t *pairs_out);
|
||||
char *directory_dump_request_log(void);
|
||||
void note_request(const char *key, size_t bytes);
|
||||
int router_supports_extrainfo(const char *identity_digest, int is_authority);
|
||||
|
||||
time_t download_status_increment_failure(download_status_t *dls,
|
||||
int status_code, const char *item,
|
||||
int server, time_t now);
|
||||
time_t download_status_increment_attempt(download_status_t *dls,
|
||||
const char *item, time_t now);
|
||||
/** Increment the failure count of the download_status_t <b>dls</b>, with
|
||||
* the optional status code <b>sc</b>. */
|
||||
#define download_status_failed(dls, sc) \
|
||||
download_status_increment_failure((dls), (sc), NULL, \
|
||||
dir_server_mode(get_options()), \
|
||||
time(NULL))
|
||||
|
||||
void download_status_reset(download_status_t *dls);
|
||||
int download_status_is_ready(download_status_t *dls, time_t now);
|
||||
time_t download_status_get_next_attempt_at(const download_status_t *dls);
|
||||
void download_status_mark_impossible(download_status_t *dl);
|
||||
|
||||
int download_status_get_n_failures(const download_status_t *dls);
|
||||
int download_status_get_n_attempts(const download_status_t *dls);
|
||||
|
||||
int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
const char *resource);
|
||||
|
||||
#ifdef DIRECTORY_PRIVATE
|
||||
|
||||
/** A structure to hold arguments passed into each directory response
|
||||
* handler */
|
||||
typedef struct response_handler_args_t {
|
||||
int status_code;
|
||||
const char *reason;
|
||||
const char *body;
|
||||
size_t body_len;
|
||||
const char *headers;
|
||||
} response_handler_args_t;
|
||||
|
||||
struct directory_request_t {
|
||||
/**
|
||||
* These fields specify which directory we're contacting. Routerstatus,
|
||||
* if present, overrides the other fields.
|
||||
*
|
||||
* @{ */
|
||||
tor_addr_port_t or_addr_port;
|
||||
tor_addr_port_t dir_addr_port;
|
||||
char digest[DIGEST_LEN];
|
||||
|
||||
const routerstatus_t *routerstatus;
|
||||
/** @} */
|
||||
/** One of DIR_PURPOSE_* other than DIR_PURPOSE_SERVER. Describes what
|
||||
* kind of operation we'll be doing (upload/download), and of what kind
|
||||
* of document. */
|
||||
uint8_t dir_purpose;
|
||||
/** One of ROUTER_PURPOSE_*; used for uploads and downloads of routerinfo
|
||||
* and extrainfo docs. */
|
||||
uint8_t router_purpose;
|
||||
/** Enum: determines whether to anonymize, and whether to use dirport or
|
||||
* orport. */
|
||||
dir_indirection_t indirection;
|
||||
/** Alias to the variable part of the URL for this request */
|
||||
const char *resource;
|
||||
/** Alias to the payload to upload (if any) */
|
||||
const char *payload;
|
||||
/** Number of bytes to upload from payload</b> */
|
||||
size_t payload_len;
|
||||
/** Value to send in an if-modified-since header, or 0 for none. */
|
||||
time_t if_modified_since;
|
||||
/** Hidden-service-specific information v2. */
|
||||
const rend_data_t *rend_query;
|
||||
/** Extra headers to append to the request */
|
||||
struct config_line_t *additional_headers;
|
||||
/** Hidden-service-specific information for v3+. */
|
||||
const hs_ident_dir_conn_t *hs_ident;
|
||||
/** Used internally to directory.c: gets informed when the attempt to
|
||||
* connect to the directory succeeds or fails, if that attempt bears on the
|
||||
* directory's usability as a directory guard. */
|
||||
struct circuit_guard_state_t *guard_state;
|
||||
};
|
||||
|
||||
struct get_handler_args_t;
|
||||
STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn,
|
||||
const struct get_handler_args_t *args);
|
||||
STATIC int directory_handle_command(dir_connection_t *conn);
|
||||
STATIC char *accept_encoding_header(void);
|
||||
STATIC int allowed_anonymous_connection_compression_method(
|
||||
enum compress_method_t);
|
||||
STATIC void warn_disallowed_anonymous_compression_method(
|
||||
enum compress_method_t);
|
||||
|
||||
STATIC int handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
|
||||
const response_handler_args_t *args);
|
||||
STATIC int handle_response_fetch_microdesc(dir_connection_t *conn,
|
||||
const response_handler_args_t *args);
|
||||
|
||||
STATIC int handle_response_fetch_consensus(dir_connection_t *conn,
|
||||
const response_handler_args_t *args);
|
||||
|
||||
#endif /* defined(DIRECTORY_PRIVATE) */
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
/* Used only by test_dir.c and test_hs_cache.c */
|
||||
|
||||
STATIC int parse_http_url(const char *headers, char **url);
|
||||
STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose,
|
||||
const char *resource);
|
||||
MOCK_DECL(STATIC int, directory_handle_command_get,(dir_connection_t *conn,
|
||||
const char *headers,
|
||||
const char *req_body,
|
||||
size_t req_body_len));
|
||||
MOCK_DECL(STATIC int, directory_handle_command_post,(dir_connection_t *conn,
|
||||
const char *headers,
|
||||
const char *body,
|
||||
size_t body_len));
|
||||
STATIC int download_status_schedule_get_delay(download_status_t *dls,
|
||||
int min_delay,
|
||||
time_t now);
|
||||
|
||||
STATIC int handle_post_hs_descriptor(const char *url, const char *body);
|
||||
|
||||
STATIC char* authdir_type_to_string(dirinfo_type_t auth);
|
||||
STATIC const char * dir_conn_purpose_to_string(int purpose);
|
||||
STATIC int should_use_directory_guards(const or_options_t *options);
|
||||
enum compression_level_t;
|
||||
STATIC enum compression_level_t choose_compression_level(ssize_t n_bytes);
|
||||
STATIC int find_dl_min_delay(const download_status_t *dls,
|
||||
const or_options_t *options);
|
||||
|
||||
STATIC int next_random_exponential_delay(int delay,
|
||||
int base_delay);
|
||||
|
||||
STATIC void next_random_exponential_delay_range(int *low_bound_out,
|
||||
int *high_bound_out,
|
||||
int delay,
|
||||
int base_delay);
|
||||
|
||||
STATIC int parse_hs_version_from_post(const char *url, const char *prefix,
|
||||
const char **end_pos);
|
||||
|
||||
STATIC unsigned parse_accept_encoding_header(const char *h);
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#if defined(TOR_UNIT_TESTS) || defined(DIRECTORY_PRIVATE)
|
||||
/* Used only by directory.c and test_dir.c */
|
||||
|
||||
/* no more than quadruple the previous delay (multiplier + 1) */
|
||||
#define DIR_DEFAULT_RANDOM_MULTIPLIER (3)
|
||||
/* no more than triple the previous delay */
|
||||
#define DIR_TEST_NET_RANDOM_MULTIPLIER (2)
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) || defined(DIRECTORY_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_DIRECTORY_H) */
|
@ -10,7 +10,7 @@
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/dircache/conscache.h"
|
||||
#include "feature/dircache/consdiffmgr.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/nodelist/microdesc.h"
|
||||
#include "feature/nodelist/routerlist.h"
|
||||
|
File diff suppressed because it is too large
Load Diff
172
src/feature/dirclient/dirclient.h
Normal file
172
src/feature/dirclient/dirclient.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file dirclient.h
|
||||
* \brief Header file for dirclient.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_DIRCLIENT_H
|
||||
#define TOR_DIRCLIENT_H
|
||||
|
||||
#include "feature/hs/hs_ident.h"
|
||||
|
||||
int directories_have_accepted_server_descriptor(void);
|
||||
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
dirinfo_type_t type, const char *payload,
|
||||
size_t payload_len, size_t extrainfo_len);
|
||||
MOCK_DECL(void, directory_get_from_dirserver, (
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
const char *resource,
|
||||
int pds_flags,
|
||||
download_want_authority_t want_authority));
|
||||
void directory_get_from_all_authorities(uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
const char *resource);
|
||||
|
||||
/** Enumeration of ways to connect to a directory server */
|
||||
typedef enum {
|
||||
/** Default: connect over a one-hop Tor circuit. Relays fall back to direct
|
||||
* DirPort connections, clients, onion services, and bridges do not */
|
||||
DIRIND_ONEHOP=0,
|
||||
/** Connect over a multi-hop anonymizing Tor circuit */
|
||||
DIRIND_ANONYMOUS=1,
|
||||
/** Connect to the DirPort directly */
|
||||
DIRIND_DIRECT_CONN,
|
||||
/** Connect over a multi-hop anonymizing Tor circuit to our dirport */
|
||||
DIRIND_ANON_DIRPORT,
|
||||
} dir_indirection_t;
|
||||
|
||||
int directory_must_use_begindir(const or_options_t *options);
|
||||
|
||||
/**
|
||||
* A directory_request_t describes the information about a directory request
|
||||
* at the client side. It describes what we're going to ask for, which
|
||||
* directory we're going to ask for it, how we're going to contact that
|
||||
* directory, and (in some cases) what to do with it when we're done.
|
||||
*/
|
||||
typedef struct directory_request_t directory_request_t;
|
||||
directory_request_t *directory_request_new(uint8_t dir_purpose);
|
||||
void directory_request_free_(directory_request_t *req);
|
||||
#define directory_request_free(req) \
|
||||
FREE_AND_NULL(directory_request_t, directory_request_free_, (req))
|
||||
void directory_request_set_or_addr_port(directory_request_t *req,
|
||||
const tor_addr_port_t *p);
|
||||
void directory_request_set_dir_addr_port(directory_request_t *req,
|
||||
const tor_addr_port_t *p);
|
||||
void directory_request_set_directory_id_digest(directory_request_t *req,
|
||||
const char *digest);
|
||||
struct circuit_guard_state_t;
|
||||
void directory_request_set_guard_state(directory_request_t *req,
|
||||
struct circuit_guard_state_t *state);
|
||||
void directory_request_set_router_purpose(directory_request_t *req,
|
||||
uint8_t router_purpose);
|
||||
void directory_request_set_indirection(directory_request_t *req,
|
||||
dir_indirection_t indirection);
|
||||
void directory_request_set_resource(directory_request_t *req,
|
||||
const char *resource);
|
||||
void directory_request_set_payload(directory_request_t *req,
|
||||
const char *payload,
|
||||
size_t payload_len);
|
||||
void directory_request_set_if_modified_since(directory_request_t *req,
|
||||
time_t if_modified_since);
|
||||
void directory_request_set_rend_query(directory_request_t *req,
|
||||
const rend_data_t *query);
|
||||
void directory_request_upload_set_hs_ident(directory_request_t *req,
|
||||
const hs_ident_dir_conn_t *ident);
|
||||
void directory_request_fetch_set_hs_ident(directory_request_t *req,
|
||||
const hs_ident_dir_conn_t *ident);
|
||||
|
||||
void directory_request_set_routerstatus(directory_request_t *req,
|
||||
const routerstatus_t *rs);
|
||||
void directory_request_add_header(directory_request_t *req,
|
||||
const char *key,
|
||||
const char *val);
|
||||
MOCK_DECL(void, directory_initiate_request, (directory_request_t *request));
|
||||
|
||||
int router_supports_extrainfo(const char *identity_digest, int is_authority);
|
||||
|
||||
void connection_dir_client_request_failed(dir_connection_t *conn);
|
||||
void connection_dir_client_refetch_hsdesc_if_needed(
|
||||
dir_connection_t *dir_conn);
|
||||
|
||||
#ifdef DIRCLIENT_PRIVATE
|
||||
struct directory_request_t {
|
||||
/**
|
||||
* These fields specify which directory we're contacting. Routerstatus,
|
||||
* if present, overrides the other fields.
|
||||
*
|
||||
* @{ */
|
||||
tor_addr_port_t or_addr_port;
|
||||
tor_addr_port_t dir_addr_port;
|
||||
char digest[DIGEST_LEN];
|
||||
|
||||
const routerstatus_t *routerstatus;
|
||||
/** @} */
|
||||
/** One of DIR_PURPOSE_* other than DIR_PURPOSE_SERVER. Describes what
|
||||
* kind of operation we'll be doing (upload/download), and of what kind
|
||||
* of document. */
|
||||
uint8_t dir_purpose;
|
||||
/** One of ROUTER_PURPOSE_*; used for uploads and downloads of routerinfo
|
||||
* and extrainfo docs. */
|
||||
uint8_t router_purpose;
|
||||
/** Enum: determines whether to anonymize, and whether to use dirport or
|
||||
* orport. */
|
||||
dir_indirection_t indirection;
|
||||
/** Alias to the variable part of the URL for this request */
|
||||
const char *resource;
|
||||
/** Alias to the payload to upload (if any) */
|
||||
const char *payload;
|
||||
/** Number of bytes to upload from payload</b> */
|
||||
size_t payload_len;
|
||||
/** Value to send in an if-modified-since header, or 0 for none. */
|
||||
time_t if_modified_since;
|
||||
/** Hidden-service-specific information v2. */
|
||||
const rend_data_t *rend_query;
|
||||
/** Extra headers to append to the request */
|
||||
struct config_line_t *additional_headers;
|
||||
/** Hidden-service-specific information for v3+. */
|
||||
const hs_ident_dir_conn_t *hs_ident;
|
||||
/** Used internally to directory.c: gets informed when the attempt to
|
||||
* connect to the directory succeeds or fails, if that attempt bears on the
|
||||
* directory's usability as a directory guard. */
|
||||
struct circuit_guard_state_t *guard_state;
|
||||
};
|
||||
|
||||
/** A structure to hold arguments passed into each directory response
|
||||
* handler */
|
||||
typedef struct response_handler_args_t {
|
||||
int status_code;
|
||||
const char *reason;
|
||||
const char *body;
|
||||
size_t body_len;
|
||||
const char *headers;
|
||||
} response_handler_args_t;
|
||||
|
||||
enum compress_method_t;
|
||||
STATIC int allowed_anonymous_connection_compression_method(
|
||||
enum compress_method_t);
|
||||
STATIC void warn_disallowed_anonymous_compression_method(
|
||||
enum compress_method_t);
|
||||
|
||||
STATIC int should_use_directory_guards(const or_options_t *options);
|
||||
STATIC char *accept_encoding_header(void);
|
||||
STATIC const char *dir_conn_purpose_to_string(int purpose);
|
||||
|
||||
STATIC int handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
|
||||
const response_handler_args_t *args);
|
||||
STATIC int handle_response_fetch_microdesc(dir_connection_t *conn,
|
||||
const response_handler_args_t *args);
|
||||
|
||||
STATIC int handle_response_fetch_consensus(dir_connection_t *conn,
|
||||
const response_handler_args_t *args);
|
||||
|
||||
STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose,
|
||||
const char *resource);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_DIRCLIENT_H) */
|
422
src/feature/dirclient/dlstatus.c
Normal file
422
src/feature/dirclient/dlstatus.c
Normal file
@ -0,0 +1,422 @@
|
||||
/* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#define DLSTATUS_PRIVATE
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "app/config/config.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/relay/router.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
|
||||
#include "feature/dirclient/download_status_st.h"
|
||||
|
||||
/** Decide which download schedule we want to use based on descriptor type
|
||||
* in <b>dls</b> and <b>options</b>.
|
||||
*
|
||||
* Then, return the initial delay for that download schedule, in seconds.
|
||||
*
|
||||
* Helper function for download_status_increment_failure(),
|
||||
* download_status_reset(), and download_status_increment_attempt(). */
|
||||
STATIC int
|
||||
find_dl_min_delay(const download_status_t *dls, const or_options_t *options)
|
||||
{
|
||||
tor_assert(dls);
|
||||
tor_assert(options);
|
||||
|
||||
switch (dls->schedule) {
|
||||
case DL_SCHED_GENERIC:
|
||||
/* Any other directory document */
|
||||
if (dir_server_mode(options)) {
|
||||
/* A directory authority or directory mirror */
|
||||
return options->TestingServerDownloadInitialDelay;
|
||||
} else {
|
||||
return options->TestingClientDownloadInitialDelay;
|
||||
}
|
||||
case DL_SCHED_CONSENSUS:
|
||||
if (!networkstatus_consensus_can_use_multiple_directories(options)) {
|
||||
/* A public relay */
|
||||
return options->TestingServerConsensusDownloadInitialDelay;
|
||||
} else {
|
||||
/* A client or bridge */
|
||||
if (networkstatus_consensus_is_bootstrapping(time(NULL))) {
|
||||
/* During bootstrapping */
|
||||
if (!networkstatus_consensus_can_use_extra_fallbacks(options)) {
|
||||
/* A bootstrapping client without extra fallback directories */
|
||||
return options->
|
||||
ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay;
|
||||
} else if (dls->want_authority) {
|
||||
/* A bootstrapping client with extra fallback directories, but
|
||||
* connecting to an authority */
|
||||
return
|
||||
options->ClientBootstrapConsensusAuthorityDownloadInitialDelay;
|
||||
} else {
|
||||
/* A bootstrapping client connecting to extra fallback directories
|
||||
*/
|
||||
return
|
||||
options->ClientBootstrapConsensusFallbackDownloadInitialDelay;
|
||||
}
|
||||
} else {
|
||||
/* A client with a reasonably live consensus, with or without
|
||||
* certificates */
|
||||
return options->TestingClientConsensusDownloadInitialDelay;
|
||||
}
|
||||
}
|
||||
case DL_SCHED_BRIDGE:
|
||||
if (options->UseBridges && num_bridges_usable(0) > 0) {
|
||||
/* A bridge client that is sure that one or more of its bridges are
|
||||
* running can afford to wait longer to update bridge descriptors. */
|
||||
return options->TestingBridgeDownloadInitialDelay;
|
||||
} else {
|
||||
/* A bridge client which might have no running bridges, must try to
|
||||
* get bridge descriptors straight away. */
|
||||
return options->TestingBridgeBootstrapDownloadInitialDelay;
|
||||
}
|
||||
default:
|
||||
tor_assert(0);
|
||||
}
|
||||
|
||||
/* Impossible, but gcc will fail with -Werror without a `return`. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** As next_random_exponential_delay() below, but does not compute a random
|
||||
* value. Instead, compute the range of values that
|
||||
* next_random_exponential_delay() should use when computing its random value.
|
||||
* Store the low bound into *<b>low_bound_out</b>, and the high bound into
|
||||
* *<b>high_bound_out</b>. Guarantees that the low bound is strictly less
|
||||
* than the high bound. */
|
||||
STATIC void
|
||||
next_random_exponential_delay_range(int *low_bound_out,
|
||||
int *high_bound_out,
|
||||
int delay,
|
||||
int base_delay)
|
||||
{
|
||||
// This is the "decorrelated jitter" approach, from
|
||||
// https://www.awsarchitectureblog.com/2015/03/backoff.html
|
||||
// The formula is
|
||||
// sleep = min(cap, random_between(base, sleep * 3))
|
||||
|
||||
const int delay_times_3 = delay < INT_MAX/3 ? delay * 3 : INT_MAX;
|
||||
*low_bound_out = base_delay;
|
||||
if (delay_times_3 > base_delay) {
|
||||
*high_bound_out = delay_times_3;
|
||||
} else {
|
||||
*high_bound_out = base_delay+1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Advance one delay step. The algorithm will generate a random delay,
|
||||
* such that each failure is possibly (random) longer than the ones before.
|
||||
*
|
||||
* We then clamp that value to be no larger than max_delay, and return it.
|
||||
*
|
||||
* The <b>base_delay</b> parameter is lowest possible delay time (can't be
|
||||
* zero); the <b>backoff_position</b> parameter is the number of times we've
|
||||
* generated a delay; and the <b>delay</b> argument is the most recently used
|
||||
* delay.
|
||||
*/
|
||||
STATIC int
|
||||
next_random_exponential_delay(int delay,
|
||||
int base_delay)
|
||||
{
|
||||
/* Check preconditions */
|
||||
if (BUG(delay < 0))
|
||||
delay = 0;
|
||||
|
||||
if (base_delay < 1)
|
||||
base_delay = 1;
|
||||
|
||||
int low_bound=0, high_bound=INT_MAX;
|
||||
|
||||
next_random_exponential_delay_range(&low_bound, &high_bound,
|
||||
delay, base_delay);
|
||||
|
||||
return crypto_rand_int_range(low_bound, high_bound);
|
||||
}
|
||||
|
||||
/** Find the current delay for dls based on min_delay.
|
||||
*
|
||||
* This function sets dls->next_attempt_at based on now, and returns the delay.
|
||||
* Helper for download_status_increment_failure and
|
||||
* download_status_increment_attempt. */
|
||||
STATIC int
|
||||
download_status_schedule_get_delay(download_status_t *dls,
|
||||
int min_delay,
|
||||
time_t now)
|
||||
{
|
||||
tor_assert(dls);
|
||||
/* If we're using random exponential backoff, we do need min/max delay */
|
||||
tor_assert(min_delay >= 0);
|
||||
|
||||
int delay = INT_MAX;
|
||||
uint8_t dls_schedule_position = (dls->increment_on
|
||||
== DL_SCHED_INCREMENT_ATTEMPT
|
||||
? dls->n_download_attempts
|
||||
: dls->n_download_failures);
|
||||
|
||||
/* Check if we missed a reset somehow */
|
||||
IF_BUG_ONCE(dls->last_backoff_position > dls_schedule_position) {
|
||||
dls->last_backoff_position = 0;
|
||||
dls->last_delay_used = 0;
|
||||
}
|
||||
|
||||
if (dls_schedule_position > 0) {
|
||||
delay = dls->last_delay_used;
|
||||
|
||||
while (dls->last_backoff_position < dls_schedule_position) {
|
||||
/* Do one increment step */
|
||||
delay = next_random_exponential_delay(delay, min_delay);
|
||||
/* Update our position */
|
||||
++(dls->last_backoff_position);
|
||||
}
|
||||
} else {
|
||||
/* If we're just starting out, use the minimum delay */
|
||||
delay = min_delay;
|
||||
}
|
||||
|
||||
/* Clamp it within min/max if we have them */
|
||||
if (min_delay >= 0 && delay < min_delay) delay = min_delay;
|
||||
|
||||
/* Store it for next time */
|
||||
dls->last_backoff_position = dls_schedule_position;
|
||||
dls->last_delay_used = delay;
|
||||
|
||||
/* A negative delay makes no sense. Knowing that delay is
|
||||
* non-negative allows us to safely do the wrapping check below. */
|
||||
tor_assert(delay >= 0);
|
||||
|
||||
/* Avoid now+delay overflowing TIME_MAX, by comparing with a subtraction
|
||||
* that won't overflow (since delay is non-negative). */
|
||||
if (delay < INT_MAX && now <= TIME_MAX - delay) {
|
||||
dls->next_attempt_at = now+delay;
|
||||
} else {
|
||||
dls->next_attempt_at = TIME_MAX;
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
/* Log a debug message about item, which increments on increment_action, has
|
||||
* incremented dls_n_download_increments times. The message varies based on
|
||||
* was_schedule_incremented (if not, not_incremented_response is logged), and
|
||||
* the values of increment, dls_next_attempt_at, and now.
|
||||
* Helper for download_status_increment_failure and
|
||||
* download_status_increment_attempt. */
|
||||
static void
|
||||
download_status_log_helper(const char *item, int was_schedule_incremented,
|
||||
const char *increment_action,
|
||||
const char *not_incremented_response,
|
||||
uint8_t dls_n_download_increments, int increment,
|
||||
time_t dls_next_attempt_at, time_t now)
|
||||
{
|
||||
if (item) {
|
||||
if (!was_schedule_incremented)
|
||||
log_debug(LD_DIR, "%s %s %d time(s); I'll try again %s.",
|
||||
item, increment_action, (int)dls_n_download_increments,
|
||||
not_incremented_response);
|
||||
else if (increment == 0)
|
||||
log_debug(LD_DIR, "%s %s %d time(s); I'll try again immediately.",
|
||||
item, increment_action, (int)dls_n_download_increments);
|
||||
else if (dls_next_attempt_at < TIME_MAX)
|
||||
log_debug(LD_DIR, "%s %s %d time(s); I'll try again in %d seconds.",
|
||||
item, increment_action, (int)dls_n_download_increments,
|
||||
(int)(dls_next_attempt_at-now));
|
||||
else
|
||||
log_debug(LD_DIR, "%s %s %d time(s); Giving up for a while.",
|
||||
item, increment_action, (int)dls_n_download_increments);
|
||||
}
|
||||
}
|
||||
|
||||
/** Determine when a failed download attempt should be retried.
|
||||
* Called when an attempt to download <b>dls</b> has failed with HTTP status
|
||||
* <b>status_code</b>. Increment the failure count (if the code indicates a
|
||||
* real failure, or if we're a server) and set <b>dls</b>-\>next_attempt_at to
|
||||
* an appropriate time in the future and return it.
|
||||
* If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_ATTEMPT, increment the
|
||||
* failure count, and return a time in the far future for the next attempt (to
|
||||
* avoid an immediate retry). */
|
||||
time_t
|
||||
download_status_increment_failure(download_status_t *dls, int status_code,
|
||||
const char *item, int server, time_t now)
|
||||
{
|
||||
(void) status_code; // XXXX no longer used.
|
||||
(void) server; // XXXX no longer used.
|
||||
int increment = -1;
|
||||
int min_delay = 0;
|
||||
|
||||
tor_assert(dls);
|
||||
|
||||
/* dls wasn't reset before it was used */
|
||||
if (dls->next_attempt_at == 0) {
|
||||
download_status_reset(dls);
|
||||
}
|
||||
|
||||
/* count the failure */
|
||||
if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1) {
|
||||
++dls->n_download_failures;
|
||||
}
|
||||
|
||||
if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
|
||||
/* We don't find out that a failure-based schedule has attempted a
|
||||
* connection until that connection fails.
|
||||
* We'll never find out about successful connections, but this doesn't
|
||||
* matter, because schedules are reset after a successful download.
|
||||
*/
|
||||
if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
|
||||
++dls->n_download_attempts;
|
||||
|
||||
/* only return a failure retry time if this schedule increments on failures
|
||||
*/
|
||||
min_delay = find_dl_min_delay(dls, get_options());
|
||||
increment = download_status_schedule_get_delay(dls, min_delay, now);
|
||||
}
|
||||
|
||||
download_status_log_helper(item, !dls->increment_on, "failed",
|
||||
"concurrently", dls->n_download_failures,
|
||||
increment,
|
||||
download_status_get_next_attempt_at(dls),
|
||||
now);
|
||||
|
||||
if (dls->increment_on == DL_SCHED_INCREMENT_ATTEMPT) {
|
||||
/* stop this schedule retrying on failure, it will launch concurrent
|
||||
* connections instead */
|
||||
return TIME_MAX;
|
||||
} else {
|
||||
return download_status_get_next_attempt_at(dls);
|
||||
}
|
||||
}
|
||||
|
||||
/** Determine when the next download attempt should be made when using an
|
||||
* attempt-based (potentially concurrent) download schedule.
|
||||
* Called when an attempt to download <b>dls</b> is being initiated.
|
||||
* Increment the attempt count and set <b>dls</b>-\>next_attempt_at to an
|
||||
* appropriate time in the future and return it.
|
||||
* If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_FAILURE, don't increment
|
||||
* the attempts, and return a time in the far future (to avoid launching a
|
||||
* concurrent attempt). */
|
||||
time_t
|
||||
download_status_increment_attempt(download_status_t *dls, const char *item,
|
||||
time_t now)
|
||||
{
|
||||
int delay = -1;
|
||||
int min_delay = 0;
|
||||
|
||||
tor_assert(dls);
|
||||
|
||||
/* dls wasn't reset before it was used */
|
||||
if (dls->next_attempt_at == 0) {
|
||||
download_status_reset(dls);
|
||||
}
|
||||
|
||||
if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
|
||||
/* this schedule should retry on failure, and not launch any concurrent
|
||||
attempts */
|
||||
log_warn(LD_BUG, "Tried to launch an attempt-based connection on a "
|
||||
"failure-based schedule.");
|
||||
return TIME_MAX;
|
||||
}
|
||||
|
||||
if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
|
||||
++dls->n_download_attempts;
|
||||
|
||||
min_delay = find_dl_min_delay(dls, get_options());
|
||||
delay = download_status_schedule_get_delay(dls, min_delay, now);
|
||||
|
||||
download_status_log_helper(item, dls->increment_on, "attempted",
|
||||
"on failure", dls->n_download_attempts,
|
||||
delay, download_status_get_next_attempt_at(dls),
|
||||
now);
|
||||
|
||||
return download_status_get_next_attempt_at(dls);
|
||||
}
|
||||
|
||||
static time_t
|
||||
download_status_get_initial_delay_from_now(const download_status_t *dls)
|
||||
{
|
||||
/* We use constant initial delays, even in exponential backoff
|
||||
* schedules. */
|
||||
return time(NULL) + find_dl_min_delay(dls, get_options());
|
||||
}
|
||||
|
||||
/** Reset <b>dls</b> so that it will be considered downloadable
|
||||
* immediately, and/or to show that we don't need it anymore.
|
||||
*
|
||||
* Must be called to initialise a download schedule, otherwise the zeroth item
|
||||
* in the schedule will never be used.
|
||||
*
|
||||
* (We find the zeroth element of the download schedule, and set
|
||||
* next_attempt_at to be the appropriate offset from 'now'. In most
|
||||
* cases this means setting it to 'now', so the item will be immediately
|
||||
* downloadable; when using authorities with fallbacks, there is a few seconds'
|
||||
* delay.) */
|
||||
void
|
||||
download_status_reset(download_status_t *dls)
|
||||
{
|
||||
if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD
|
||||
|| dls->n_download_attempts == IMPOSSIBLE_TO_DOWNLOAD)
|
||||
return; /* Don't reset this. */
|
||||
|
||||
dls->n_download_failures = 0;
|
||||
dls->n_download_attempts = 0;
|
||||
dls->next_attempt_at = download_status_get_initial_delay_from_now(dls);
|
||||
dls->last_backoff_position = 0;
|
||||
dls->last_delay_used = 0;
|
||||
/* Don't reset dls->want_authority or dls->increment_on */
|
||||
}
|
||||
|
||||
/** Return true iff, as of <b>now</b>, the resource tracked by <b>dls</b> is
|
||||
* ready to get its download reattempted. */
|
||||
int
|
||||
download_status_is_ready(download_status_t *dls, time_t now)
|
||||
{
|
||||
/* dls wasn't reset before it was used */
|
||||
if (dls->next_attempt_at == 0) {
|
||||
download_status_reset(dls);
|
||||
}
|
||||
|
||||
return download_status_get_next_attempt_at(dls) <= now;
|
||||
}
|
||||
|
||||
/** Mark <b>dl</b> as never downloadable. */
|
||||
void
|
||||
download_status_mark_impossible(download_status_t *dl)
|
||||
{
|
||||
dl->n_download_failures = IMPOSSIBLE_TO_DOWNLOAD;
|
||||
dl->n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD;
|
||||
}
|
||||
|
||||
/** Return the number of failures on <b>dls</b> since the last success (if
|
||||
* any). */
|
||||
int
|
||||
download_status_get_n_failures(const download_status_t *dls)
|
||||
{
|
||||
return dls->n_download_failures;
|
||||
}
|
||||
|
||||
/** Return the number of attempts to download <b>dls</b> since the last success
|
||||
* (if any). This can differ from download_status_get_n_failures() due to
|
||||
* outstanding concurrent attempts. */
|
||||
int
|
||||
download_status_get_n_attempts(const download_status_t *dls)
|
||||
{
|
||||
return dls->n_download_attempts;
|
||||
}
|
||||
|
||||
/** Return the next time to attempt to download <b>dls</b>. */
|
||||
time_t
|
||||
download_status_get_next_attempt_at(const download_status_t *dls)
|
||||
{
|
||||
/* dls wasn't reset before it was used */
|
||||
if (dls->next_attempt_at == 0) {
|
||||
/* so give the answer we would have given if it had been */
|
||||
return download_status_get_initial_delay_from_now(dls);
|
||||
}
|
||||
|
||||
return dls->next_attempt_at;
|
||||
}
|
58
src/feature/dirclient/dlstatus.h
Normal file
58
src/feature/dirclient/dlstatus.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file dlstatus.h
|
||||
* \brief Header file for dlstatus.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_DLSTATUS_H
|
||||
#define TOR_DLSTATUS_H
|
||||
|
||||
time_t download_status_increment_failure(download_status_t *dls,
|
||||
int status_code, const char *item,
|
||||
int server, time_t now);
|
||||
time_t download_status_increment_attempt(download_status_t *dls,
|
||||
const char *item, time_t now);
|
||||
/** Increment the failure count of the download_status_t <b>dls</b>, with
|
||||
* the optional status code <b>sc</b>. */
|
||||
#define download_status_failed(dls, sc) \
|
||||
download_status_increment_failure((dls), (sc), NULL, \
|
||||
dir_server_mode(get_options()), \
|
||||
time(NULL))
|
||||
|
||||
void download_status_reset(download_status_t *dls);
|
||||
int download_status_is_ready(download_status_t *dls, time_t now);
|
||||
time_t download_status_get_next_attempt_at(const download_status_t *dls);
|
||||
void download_status_mark_impossible(download_status_t *dl);
|
||||
|
||||
int download_status_get_n_failures(const download_status_t *dls);
|
||||
int download_status_get_n_attempts(const download_status_t *dls);
|
||||
|
||||
#ifdef DLSTATUS_PRIVATE
|
||||
STATIC int download_status_schedule_get_delay(download_status_t *dls,
|
||||
int min_delay,
|
||||
time_t now);
|
||||
|
||||
STATIC int find_dl_min_delay(const download_status_t *dls,
|
||||
const or_options_t *options);
|
||||
|
||||
STATIC int next_random_exponential_delay(int delay,
|
||||
int base_delay);
|
||||
|
||||
STATIC void next_random_exponential_delay_range(int *low_bound_out,
|
||||
int *high_bound_out,
|
||||
int delay,
|
||||
int base_delay);
|
||||
|
||||
/* no more than quadruple the previous delay (multiplier + 1) */
|
||||
#define DIR_DEFAULT_RANDOM_MULTIPLIER (3)
|
||||
/* no more than triple the previous delay */
|
||||
#define DIR_TEST_NET_RANDOM_MULTIPLIER (2)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_DLSTATUS_H) */
|
651
src/feature/dircommon/directory.c
Normal file
651
src/feature/dircommon/directory.c
Normal file
@ -0,0 +1,651 @@
|
||||
/* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/dircache/dircache.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircommon/fp_pair.h"
|
||||
#include "feature/stats/geoip.h"
|
||||
#include "lib/compress/compress.h"
|
||||
|
||||
#include "feature/dircommon/dir_connection_st.h"
|
||||
#include "feature/nodelist/routerinfo_st.h"
|
||||
|
||||
/**
|
||||
* \file directory.c
|
||||
* \brief Code to send and fetch information from directory authorities and
|
||||
* caches via HTTP.
|
||||
*
|
||||
* Directory caches and authorities use dirserv.c to generate the results of a
|
||||
* query and stream them to the connection; clients use routerparse.c to parse
|
||||
* them.
|
||||
*
|
||||
* Every directory request has a dir_connection_t on the client side and on
|
||||
* the server side. In most cases, the dir_connection_t object is a linked
|
||||
* connection, tunneled through an edge_connection_t so that it can be a
|
||||
* stream on the Tor network. The only non-tunneled connections are those
|
||||
* that are used to upload material (descriptors and votes) to authorities.
|
||||
* Among tunneled connections, some use one-hop circuits, and others use
|
||||
* multi-hop circuits for anonymity.
|
||||
*
|
||||
* Directory requests are launched by calling
|
||||
* directory_initiate_request(). This
|
||||
* launch the connection, will construct an HTTP request with
|
||||
* directory_send_command(), send the and wait for a response. The client
|
||||
* later handles the response with connection_dir_client_reached_eof(),
|
||||
* which passes the information received to another part of Tor.
|
||||
*
|
||||
* On the server side, requests are read in directory_handle_command(),
|
||||
* which dispatches first on the request type (GET or POST), and then on
|
||||
* the URL requested. GET requests are processed with a table-based
|
||||
* dispatcher in url_table[]. The process of handling larger GET requests
|
||||
* is complicated because we need to avoid allocating a copy of all the
|
||||
* data to be sent to the client in one huge buffer. Instead, we spool the
|
||||
* data into the buffer using logic in connection_dirserv_flushed_some() in
|
||||
* dirserv.c. (TODO: If we extended buf.c to have a zero-copy
|
||||
* reference-based buffer type, we could remove most of that code, at the
|
||||
* cost of a bit more reference counting.)
|
||||
**/
|
||||
|
||||
/* In-points to directory.c:
|
||||
*
|
||||
* - directory_post_to_dirservers(), called from
|
||||
* router_upload_dir_desc_to_dirservers() in router.c
|
||||
* upload_service_descriptor() in rendservice.c
|
||||
* - directory_get_from_dirserver(), called from
|
||||
* rend_client_refetch_renddesc() in rendclient.c
|
||||
* run_scheduled_events() in main.c
|
||||
* do_hup() in main.c
|
||||
* - connection_dir_process_inbuf(), called from
|
||||
* connection_process_inbuf() in connection.c
|
||||
* - connection_dir_finished_flushing(), called from
|
||||
* connection_finished_flushing() in connection.c
|
||||
* - connection_dir_finished_connecting(), called from
|
||||
* connection_finished_connecting() in connection.c
|
||||
*/
|
||||
|
||||
/** Convert a connection_t* to a dir_connection_t*; assert if the cast is
|
||||
* invalid. */
|
||||
dir_connection_t *
|
||||
TO_DIR_CONN(connection_t *c)
|
||||
{
|
||||
tor_assert(c->magic == DIR_CONNECTION_MAGIC);
|
||||
return DOWNCAST(dir_connection_t, c);
|
||||
}
|
||||
|
||||
/** Return false if the directory purpose <b>dir_purpose</b>
|
||||
* does not require an anonymous (three-hop) connection.
|
||||
*
|
||||
* Return true 1) by default, 2) if all directory actions have
|
||||
* specifically been configured to be over an anonymous connection,
|
||||
* or 3) if the router is a bridge */
|
||||
int
|
||||
purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
const char *resource)
|
||||
{
|
||||
if (get_options()->AllDirActionsPrivate)
|
||||
return 1;
|
||||
|
||||
if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
|
||||
if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
|
||||
&& resource && !strcmp(resource, "authority.z")) {
|
||||
/* We are asking a bridge for its own descriptor. That doesn't need
|
||||
anonymity. */
|
||||
return 0;
|
||||
}
|
||||
/* Assume all other bridge stuff needs anonymity. */
|
||||
return 1; /* if no circuits yet, this might break bootstrapping, but it's
|
||||
* needed to be safe. */
|
||||
}
|
||||
|
||||
switch (dir_purpose)
|
||||
{
|
||||
case DIR_PURPOSE_UPLOAD_DIR:
|
||||
case DIR_PURPOSE_UPLOAD_VOTE:
|
||||
case DIR_PURPOSE_UPLOAD_SIGNATURES:
|
||||
case DIR_PURPOSE_FETCH_STATUS_VOTE:
|
||||
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
|
||||
case DIR_PURPOSE_FETCH_CONSENSUS:
|
||||
case DIR_PURPOSE_FETCH_CERTIFICATE:
|
||||
case DIR_PURPOSE_FETCH_SERVERDESC:
|
||||
case DIR_PURPOSE_FETCH_EXTRAINFO:
|
||||
case DIR_PURPOSE_FETCH_MICRODESC:
|
||||
return 0;
|
||||
case DIR_PURPOSE_HAS_FETCHED_HSDESC:
|
||||
case DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2:
|
||||
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
|
||||
case DIR_PURPOSE_FETCH_RENDDESC_V2:
|
||||
case DIR_PURPOSE_FETCH_HSDESC:
|
||||
case DIR_PURPOSE_UPLOAD_HSDESC:
|
||||
return 1;
|
||||
case DIR_PURPOSE_SERVER:
|
||||
default:
|
||||
log_warn(LD_BUG, "Called with dir_purpose=%d, router_purpose=%d",
|
||||
dir_purpose, router_purpose);
|
||||
tor_assert_nonfatal_unreached();
|
||||
return 1; /* Assume it needs anonymity; better safe than sorry. */
|
||||
}
|
||||
}
|
||||
|
||||
/** Return a newly allocated string describing <b>auth</b>. Only describes
|
||||
* authority features. */
|
||||
char *
|
||||
authdir_type_to_string(dirinfo_type_t auth)
|
||||
{
|
||||
char *result;
|
||||
smartlist_t *lst = smartlist_new();
|
||||
if (auth & V3_DIRINFO)
|
||||
smartlist_add(lst, (void*)"V3");
|
||||
if (auth & BRIDGE_DIRINFO)
|
||||
smartlist_add(lst, (void*)"Bridge");
|
||||
if (smartlist_len(lst)) {
|
||||
result = smartlist_join_strings(lst, ", ", 0, NULL);
|
||||
} else {
|
||||
result = tor_strdup("[Not an authority]");
|
||||
}
|
||||
smartlist_free(lst);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Return true iff anything we say on <b>conn</b> is being encrypted before
|
||||
* we send it to the client/server. */
|
||||
int
|
||||
connection_dir_is_encrypted(const dir_connection_t *conn)
|
||||
{
|
||||
/* Right now it's sufficient to see if conn is or has been linked, since
|
||||
* the only thing it could be linked to is an edge connection on a
|
||||
* circuit, and the only way it could have been unlinked is at the edge
|
||||
* connection getting closed.
|
||||
*/
|
||||
return TO_CONN(conn)->linked;
|
||||
}
|
||||
|
||||
/** Parse an HTTP request line at the start of a headers string. On failure,
|
||||
* return -1. On success, set *<b>command_out</b> to a copy of the HTTP
|
||||
* command ("get", "post", etc), set *<b>url_out</b> to a copy of the URL, and
|
||||
* return 0. */
|
||||
int
|
||||
parse_http_command(const char *headers, char **command_out, char **url_out)
|
||||
{
|
||||
const char *command, *end_of_command;
|
||||
char *s, *start, *tmp;
|
||||
|
||||
s = (char *)eat_whitespace_no_nl(headers);
|
||||
if (!*s) return -1;
|
||||
command = s;
|
||||
s = (char *)find_whitespace(s); /* get past GET/POST */
|
||||
if (!*s) return -1;
|
||||
end_of_command = s;
|
||||
s = (char *)eat_whitespace_no_nl(s);
|
||||
if (!*s) return -1;
|
||||
start = s; /* this is the URL, assuming it's valid */
|
||||
s = (char *)find_whitespace(start);
|
||||
if (!*s) return -1;
|
||||
|
||||
/* tolerate the http[s] proxy style of putting the hostname in the url */
|
||||
if (s-start >= 4 && !strcmpstart(start,"http")) {
|
||||
tmp = start + 4;
|
||||
if (*tmp == 's')
|
||||
tmp++;
|
||||
if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
|
||||
tmp = strchr(tmp+3, '/');
|
||||
if (tmp && tmp < s) {
|
||||
log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
|
||||
start = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the header is well formed (next sequence
|
||||
* should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
|
||||
{
|
||||
unsigned minor_ver;
|
||||
char ch;
|
||||
char *e = (char *)eat_whitespace_no_nl(s);
|
||||
if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
|
||||
return -1;
|
||||
}
|
||||
if (ch != '\r')
|
||||
return -1;
|
||||
}
|
||||
|
||||
*url_out = tor_memdup_nulterm(start, s-start);
|
||||
*command_out = tor_memdup_nulterm(command, end_of_command - command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return a copy of the first HTTP header in <b>headers</b> whose key is
|
||||
* <b>which</b>. The key should be given with a terminating colon and space;
|
||||
* this function copies everything after, up to but not including the
|
||||
* following \\r\\n. */
|
||||
char *
|
||||
http_get_header(const char *headers, const char *which)
|
||||
{
|
||||
const char *cp = headers;
|
||||
while (cp) {
|
||||
if (!strcasecmpstart(cp, which)) {
|
||||
char *eos;
|
||||
cp += strlen(which);
|
||||
if ((eos = strchr(cp,'\r')))
|
||||
return tor_strndup(cp, eos-cp);
|
||||
else
|
||||
return tor_strdup(cp);
|
||||
}
|
||||
cp = strchr(cp, '\n');
|
||||
if (cp)
|
||||
++cp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/** Parse an HTTP response string <b>headers</b> of the form
|
||||
* \verbatim
|
||||
* "HTTP/1.\%d \%d\%s\r\n...".
|
||||
* \endverbatim
|
||||
*
|
||||
* If it's well-formed, assign the status code to *<b>code</b> and
|
||||
* return 0. Otherwise, return -1.
|
||||
*
|
||||
* On success: If <b>date</b> is provided, set *date to the Date
|
||||
* header in the http headers, or 0 if no such header is found. If
|
||||
* <b>compression</b> is provided, set *<b>compression</b> to the
|
||||
* compression method given in the Content-Encoding header, or 0 if no
|
||||
* such header is found, or -1 if the value of the header is not
|
||||
* recognized. If <b>reason</b> is provided, strdup the reason string
|
||||
* into it.
|
||||
*/
|
||||
int
|
||||
parse_http_response(const char *headers, int *code, time_t *date,
|
||||
compress_method_t *compression, char **reason)
|
||||
{
|
||||
unsigned n1, n2;
|
||||
char datestr[RFC1123_TIME_LEN+1];
|
||||
smartlist_t *parsed_headers;
|
||||
tor_assert(headers);
|
||||
tor_assert(code);
|
||||
|
||||
while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
|
||||
|
||||
if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
|
||||
(n1 != 0 && n1 != 1) ||
|
||||
(n2 < 100 || n2 >= 600)) {
|
||||
log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
|
||||
return -1;
|
||||
}
|
||||
*code = n2;
|
||||
|
||||
parsed_headers = smartlist_new();
|
||||
smartlist_split_string(parsed_headers, headers, "\n",
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
|
||||
if (reason) {
|
||||
smartlist_t *status_line_elements = smartlist_new();
|
||||
tor_assert(smartlist_len(parsed_headers));
|
||||
smartlist_split_string(status_line_elements,
|
||||
smartlist_get(parsed_headers, 0),
|
||||
" ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
|
||||
tor_assert(smartlist_len(status_line_elements) <= 3);
|
||||
if (smartlist_len(status_line_elements) == 3) {
|
||||
*reason = smartlist_get(status_line_elements, 2);
|
||||
smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
|
||||
}
|
||||
SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
|
||||
smartlist_free(status_line_elements);
|
||||
}
|
||||
if (date) {
|
||||
*date = 0;
|
||||
SMARTLIST_FOREACH(parsed_headers, const char *, s,
|
||||
if (!strcmpstart(s, "Date: ")) {
|
||||
strlcpy(datestr, s+6, sizeof(datestr));
|
||||
/* This will do nothing on failure, so we don't need to check
|
||||
the result. We shouldn't warn, since there are many other valid
|
||||
date formats besides the one we use. */
|
||||
parse_rfc1123_time(datestr, date);
|
||||
break;
|
||||
});
|
||||
}
|
||||
if (compression) {
|
||||
const char *enc = NULL;
|
||||
SMARTLIST_FOREACH(parsed_headers, const char *, s,
|
||||
if (!strcmpstart(s, "Content-Encoding: ")) {
|
||||
enc = s+18; break;
|
||||
});
|
||||
|
||||
if (enc == NULL)
|
||||
*compression = NO_METHOD;
|
||||
else {
|
||||
*compression = compression_method_get_by_name(enc);
|
||||
|
||||
if (*compression == UNKNOWN_METHOD)
|
||||
log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
|
||||
escaped(enc));
|
||||
}
|
||||
}
|
||||
SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
|
||||
smartlist_free(parsed_headers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** If any directory object is arriving, and it's over 10MB large, we're
|
||||
* getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
|
||||
* ask for more than 96 router descriptors at a time.)
|
||||
*/
|
||||
#define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
|
||||
|
||||
#define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
|
||||
|
||||
/** Read handler for directory connections. (That's connections <em>to</em>
|
||||
* directory servers and connections <em>at</em> directory servers.)
|
||||
*/
|
||||
int
|
||||
connection_dir_process_inbuf(dir_connection_t *conn)
|
||||
{
|
||||
size_t max_size;
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->base_.type == CONN_TYPE_DIR);
|
||||
|
||||
/* Directory clients write, then read data until they receive EOF;
|
||||
* directory servers read data until they get an HTTP command, then
|
||||
* write their response (when it's finished flushing, they mark for
|
||||
* close).
|
||||
*/
|
||||
|
||||
/* If we're on the dirserver side, look for a command. */
|
||||
if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
|
||||
if (directory_handle_command(conn) < 0) {
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_size =
|
||||
(TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
|
||||
MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
|
||||
|
||||
if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
|
||||
log_warn(LD_HTTP,
|
||||
"Too much data received from directory connection (%s): "
|
||||
"denial of service attempt, or you need to upgrade?",
|
||||
conn->base_.address);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!conn->base_.inbuf_reached_eof)
|
||||
log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Called when we're about to finally unlink and free a directory connection:
|
||||
* perform necessary accounting and cleanup */
|
||||
void
|
||||
connection_dir_about_to_close(dir_connection_t *dir_conn)
|
||||
{
|
||||
connection_t *conn = TO_CONN(dir_conn);
|
||||
|
||||
if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
|
||||
/* It's a directory connection and connecting or fetching
|
||||
* failed: forget about this router, and maybe try again. */
|
||||
connection_dir_client_request_failed(dir_conn);
|
||||
}
|
||||
|
||||
connection_dir_client_refetch_hsdesc_if_needed(dir_conn);
|
||||
}
|
||||
|
||||
/** Write handler for directory connections; called when all data has
|
||||
* been flushed. Close the connection or wait for a response as
|
||||
* appropriate.
|
||||
*/
|
||||
int
|
||||
connection_dir_finished_flushing(dir_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->base_.type == CONN_TYPE_DIR);
|
||||
|
||||
if (conn->base_.marked_for_close)
|
||||
return 0;
|
||||
|
||||
/* Note that we have finished writing the directory response. For direct
|
||||
* connections this means we're done; for tunneled connections it's only
|
||||
* an intermediate step. */
|
||||
if (conn->dirreq_id)
|
||||
geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
|
||||
DIRREQ_FLUSHING_DIR_CONN_FINISHED);
|
||||
else
|
||||
geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
|
||||
DIRREQ_DIRECT,
|
||||
DIRREQ_FLUSHING_DIR_CONN_FINISHED);
|
||||
switch (conn->base_.state) {
|
||||
case DIR_CONN_STATE_CONNECTING:
|
||||
case DIR_CONN_STATE_CLIENT_SENDING:
|
||||
log_debug(LD_DIR,"client finished sending command.");
|
||||
conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
|
||||
return 0;
|
||||
case DIR_CONN_STATE_SERVER_WRITING:
|
||||
if (conn->spool) {
|
||||
log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
} else {
|
||||
log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
log_warn(LD_BUG,"called in unexpected state %d.",
|
||||
conn->base_.state);
|
||||
tor_fragile_assert();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Connected handler for directory connections: begin sending data to the
|
||||
* server, and return 0.
|
||||
* Only used when connections don't immediately connect. */
|
||||
int
|
||||
connection_dir_finished_connecting(dir_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->base_.type == CONN_TYPE_DIR);
|
||||
tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
|
||||
|
||||
log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
|
||||
conn->base_.address,conn->base_.port);
|
||||
|
||||
/* start flushing conn */
|
||||
conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Helper. Compare two fp_pair_t objects, and return negative, 0, or
|
||||
* positive as appropriate. */
|
||||
static int
|
||||
compare_pairs_(const void **a, const void **b)
|
||||
{
|
||||
const fp_pair_t *fp1 = *a, *fp2 = *b;
|
||||
int r;
|
||||
if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
|
||||
return r;
|
||||
else
|
||||
return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
|
||||
}
|
||||
|
||||
/** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
|
||||
* FP is a hex-encoded fingerprint, into a sequence of distinct sorted
|
||||
* fp_pair_t. Skip malformed pairs. On success, return 0 and add those
|
||||
* fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
|
||||
int
|
||||
dir_split_resource_into_fingerprint_pairs(const char *res,
|
||||
smartlist_t *pairs_out)
|
||||
{
|
||||
smartlist_t *pairs_tmp = smartlist_new();
|
||||
smartlist_t *pairs_result = smartlist_new();
|
||||
|
||||
smartlist_split_string(pairs_tmp, res, "+", 0, 0);
|
||||
if (smartlist_len(pairs_tmp)) {
|
||||
char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
|
||||
size_t last_len = strlen(last);
|
||||
if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
|
||||
last[last_len-2] = '\0';
|
||||
}
|
||||
}
|
||||
SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
|
||||
if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
|
||||
log_info(LD_DIR,
|
||||
"Skipping digest pair %s with non-standard length.", escaped(cp));
|
||||
} else if (cp[HEX_DIGEST_LEN] != '-') {
|
||||
log_info(LD_DIR,
|
||||
"Skipping digest pair %s with missing dash.", escaped(cp));
|
||||
} else {
|
||||
fp_pair_t pair;
|
||||
if (base16_decode(pair.first, DIGEST_LEN,
|
||||
cp, HEX_DIGEST_LEN) != DIGEST_LEN ||
|
||||
base16_decode(pair.second,DIGEST_LEN,
|
||||
cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN) != DIGEST_LEN) {
|
||||
log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
|
||||
} else {
|
||||
smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
|
||||
}
|
||||
}
|
||||
tor_free(cp);
|
||||
} SMARTLIST_FOREACH_END(cp);
|
||||
smartlist_free(pairs_tmp);
|
||||
|
||||
/* Uniq-and-sort */
|
||||
smartlist_sort(pairs_result, compare_pairs_);
|
||||
smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
|
||||
|
||||
smartlist_add_all(pairs_out, pairs_result);
|
||||
smartlist_free(pairs_result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Given a directory <b>resource</b> request, containing zero
|
||||
* or more strings separated by plus signs, followed optionally by ".z", store
|
||||
* the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
|
||||
* non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
|
||||
*
|
||||
* If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
|
||||
* decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
|
||||
* a separator, delete all the elements that aren't base64-encoded digests,
|
||||
* and decode the rest. If (flags & DSR_DIGEST256), these digests should be
|
||||
* 256 bits long; else they should be 160.
|
||||
*
|
||||
* If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
|
||||
*/
|
||||
int
|
||||
dir_split_resource_into_fingerprints(const char *resource,
|
||||
smartlist_t *fp_out, int *compressed_out,
|
||||
int flags)
|
||||
{
|
||||
const int decode_hex = flags & DSR_HEX;
|
||||
const int decode_base64 = flags & DSR_BASE64;
|
||||
const int digests_are_256 = flags & DSR_DIGEST256;
|
||||
const int sort_uniq = flags & DSR_SORT_UNIQ;
|
||||
|
||||
const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
|
||||
const int hex_digest_len = digests_are_256 ?
|
||||
HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
|
||||
const int base64_digest_len = digests_are_256 ?
|
||||
BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
|
||||
smartlist_t *fp_tmp = smartlist_new();
|
||||
|
||||
tor_assert(!(decode_hex && decode_base64));
|
||||
tor_assert(fp_out);
|
||||
|
||||
smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
|
||||
if (compressed_out)
|
||||
*compressed_out = 0;
|
||||
if (smartlist_len(fp_tmp)) {
|
||||
char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
|
||||
size_t last_len = strlen(last);
|
||||
if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
|
||||
last[last_len-2] = '\0';
|
||||
if (compressed_out)
|
||||
*compressed_out = 1;
|
||||
}
|
||||
}
|
||||
if (decode_hex || decode_base64) {
|
||||
const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
|
||||
int i;
|
||||
char *cp, *d = NULL;
|
||||
for (i = 0; i < smartlist_len(fp_tmp); ++i) {
|
||||
cp = smartlist_get(fp_tmp, i);
|
||||
if (strlen(cp) != encoded_len) {
|
||||
log_info(LD_DIR,
|
||||
"Skipping digest %s with non-standard length.", escaped(cp));
|
||||
smartlist_del_keeporder(fp_tmp, i--);
|
||||
goto again;
|
||||
}
|
||||
d = tor_malloc_zero(digest_len);
|
||||
if (decode_hex ?
|
||||
(base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) :
|
||||
(base64_decode(d, digest_len, cp, base64_digest_len)
|
||||
!= digest_len)) {
|
||||
log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
|
||||
smartlist_del_keeporder(fp_tmp, i--);
|
||||
goto again;
|
||||
}
|
||||
smartlist_set(fp_tmp, i, d);
|
||||
d = NULL;
|
||||
again:
|
||||
tor_free(cp);
|
||||
tor_free(d);
|
||||
}
|
||||
}
|
||||
if (sort_uniq) {
|
||||
if (decode_hex || decode_base64) {
|
||||
if (digests_are_256) {
|
||||
smartlist_sort_digests256(fp_tmp);
|
||||
smartlist_uniq_digests256(fp_tmp);
|
||||
} else {
|
||||
smartlist_sort_digests(fp_tmp);
|
||||
smartlist_uniq_digests(fp_tmp);
|
||||
}
|
||||
} else {
|
||||
smartlist_sort_strings(fp_tmp);
|
||||
smartlist_uniq_strings(fp_tmp);
|
||||
}
|
||||
}
|
||||
smartlist_add_all(fp_out, fp_tmp);
|
||||
smartlist_free(fp_tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** As dir_split_resource_into_fingerprints, but instead fills
|
||||
* <b>spool_out</b> with a list of spoolable_resource_t for the resource
|
||||
* identified through <b>source</b>. */
|
||||
int
|
||||
dir_split_resource_into_spoolable(const char *resource,
|
||||
dir_spool_source_t source,
|
||||
smartlist_t *spool_out,
|
||||
int *compressed_out,
|
||||
int flags)
|
||||
{
|
||||
smartlist_t *fingerprints = smartlist_new();
|
||||
|
||||
tor_assert(flags & (DSR_HEX|DSR_BASE64));
|
||||
const size_t digest_len =
|
||||
(flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
|
||||
|
||||
int r = dir_split_resource_into_fingerprints(resource, fingerprints,
|
||||
compressed_out, flags);
|
||||
/* This is not a very efficient implementation XXXX */
|
||||
SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
|
||||
spooled_resource_t *spooled =
|
||||
spooled_resource_new(source, digest, digest_len);
|
||||
if (spooled)
|
||||
smartlist_add(spool_out, spooled);
|
||||
tor_free(digest);
|
||||
} SMARTLIST_FOREACH_END(digest);
|
||||
|
||||
smartlist_free(fingerprints);
|
||||
return r;
|
||||
}
|
129
src/feature/dircommon/directory.h
Normal file
129
src/feature/dircommon/directory.h
Normal file
@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file directory.h
|
||||
* \brief Header file for directory.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_DIRECTORY_H
|
||||
#define TOR_DIRECTORY_H
|
||||
|
||||
dir_connection_t *TO_DIR_CONN(connection_t *c);
|
||||
|
||||
#define DIR_CONN_STATE_MIN_ 1
|
||||
/** State for connection to directory server: waiting for connect(). */
|
||||
#define DIR_CONN_STATE_CONNECTING 1
|
||||
/** State for connection to directory server: sending HTTP request. */
|
||||
#define DIR_CONN_STATE_CLIENT_SENDING 2
|
||||
/** State for connection to directory server: reading HTTP response. */
|
||||
#define DIR_CONN_STATE_CLIENT_READING 3
|
||||
/** State for connection to directory server: happy and finished. */
|
||||
#define DIR_CONN_STATE_CLIENT_FINISHED 4
|
||||
/** State for connection at directory server: waiting for HTTP request. */
|
||||
#define DIR_CONN_STATE_SERVER_COMMAND_WAIT 5
|
||||
/** State for connection at directory server: sending HTTP response. */
|
||||
#define DIR_CONN_STATE_SERVER_WRITING 6
|
||||
#define DIR_CONN_STATE_MAX_ 6
|
||||
|
||||
#define DIR_PURPOSE_MIN_ 4
|
||||
/** A connection to a directory server: set after a v2 rendezvous
|
||||
* descriptor is downloaded. */
|
||||
#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
|
||||
/** A connection to a directory server: download one or more server
|
||||
* descriptors. */
|
||||
#define DIR_PURPOSE_FETCH_SERVERDESC 6
|
||||
/** A connection to a directory server: download one or more extra-info
|
||||
* documents. */
|
||||
#define DIR_PURPOSE_FETCH_EXTRAINFO 7
|
||||
/** A connection to a directory server: upload a server descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_DIR 8
|
||||
/** A connection to a directory server: upload a v3 networkstatus vote. */
|
||||
#define DIR_PURPOSE_UPLOAD_VOTE 10
|
||||
/** A connection to a directory server: upload a v3 consensus signature */
|
||||
#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
|
||||
/** A connection to a directory server: download one or more v3 networkstatus
|
||||
* votes. */
|
||||
#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
|
||||
/** A connection to a directory server: download a v3 detached signatures
|
||||
* object for a consensus. */
|
||||
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
|
||||
/** A connection to a directory server: download a v3 networkstatus
|
||||
* consensus. */
|
||||
#define DIR_PURPOSE_FETCH_CONSENSUS 14
|
||||
/** A connection to a directory server: download one or more directory
|
||||
* authority certificates. */
|
||||
#define DIR_PURPOSE_FETCH_CERTIFICATE 15
|
||||
|
||||
/** Purpose for connection at a directory server. */
|
||||
#define DIR_PURPOSE_SERVER 16
|
||||
/** A connection to a hidden service directory server: upload a v2 rendezvous
|
||||
* descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_RENDDESC_V2 17
|
||||
/** A connection to a hidden service directory server: download a v2 rendezvous
|
||||
* descriptor. */
|
||||
#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
|
||||
/** A connection to a directory server: download a microdescriptor. */
|
||||
#define DIR_PURPOSE_FETCH_MICRODESC 19
|
||||
/** A connection to a hidden service directory: upload a v3 descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_HSDESC 20
|
||||
/** A connection to a hidden service directory: fetch a v3 descriptor. */
|
||||
#define DIR_PURPOSE_FETCH_HSDESC 21
|
||||
/** A connection to a directory server: set after a hidden service descriptor
|
||||
* is downloaded. */
|
||||
#define DIR_PURPOSE_HAS_FETCHED_HSDESC 22
|
||||
#define DIR_PURPOSE_MAX_ 22
|
||||
|
||||
/** True iff <b>p</b> is a purpose corresponding to uploading
|
||||
* data to a directory server. */
|
||||
#define DIR_PURPOSE_IS_UPLOAD(p) \
|
||||
((p)==DIR_PURPOSE_UPLOAD_DIR || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_VOTE || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_SIGNATURES || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_RENDDESC_V2 || \
|
||||
(p)==DIR_PURPOSE_UPLOAD_HSDESC)
|
||||
|
||||
enum compress_method_t;
|
||||
int parse_http_response(const char *headers, int *code, time_t *date,
|
||||
enum compress_method_t *compression, char **response);
|
||||
int parse_http_command(const char *headers,
|
||||
char **command_out, char **url_out);
|
||||
char *http_get_header(const char *headers, const char *which);
|
||||
|
||||
int connection_dir_is_encrypted(const dir_connection_t *conn);
|
||||
int connection_dir_reached_eof(dir_connection_t *conn);
|
||||
int connection_dir_process_inbuf(dir_connection_t *conn);
|
||||
int connection_dir_finished_flushing(dir_connection_t *conn);
|
||||
int connection_dir_finished_connecting(dir_connection_t *conn);
|
||||
void connection_dir_about_to_close(dir_connection_t *dir_conn);
|
||||
|
||||
#define DSR_HEX (1<<0)
|
||||
#define DSR_BASE64 (1<<1)
|
||||
#define DSR_DIGEST256 (1<<2)
|
||||
#define DSR_SORT_UNIQ (1<<3)
|
||||
int dir_split_resource_into_fingerprints(const char *resource,
|
||||
smartlist_t *fp_out, int *compressed_out,
|
||||
int flags);
|
||||
enum dir_spool_source_t;
|
||||
int dir_split_resource_into_spoolable(const char *resource,
|
||||
enum dir_spool_source_t source,
|
||||
smartlist_t *spool_out,
|
||||
int *compressed_out,
|
||||
int flags);
|
||||
int dir_split_resource_into_fingerprint_pairs(const char *res,
|
||||
smartlist_t *pairs_out);
|
||||
char *directory_dump_request_log(void);
|
||||
void note_request(const char *key, size_t bytes);
|
||||
|
||||
int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
const char *resource);
|
||||
|
||||
char *authdir_type_to_string(dirinfo_type_t auth);
|
||||
|
||||
#define X_ADDRESS_HEADER "X-Your-Address-Is: "
|
||||
#define X_OR_DIFF_FROM_CONSENSUS_HEADER "X-Or-Diff-From-Consensus: "
|
||||
|
||||
#endif /* !defined(TOR_DIRECTORY_H) */
|
@ -19,7 +19,8 @@
|
||||
#include "lib/crypt_ops/crypto_format.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/hs/hs_cache.h"
|
||||
#include "feature/hs/hs_cell.h"
|
||||
#include "feature/hs/hs_circuit.h"
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "lib/crypt_ops/crypto_ope.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
|
@ -23,7 +23,9 @@
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "core/or/policies.h"
|
||||
#include "feature/client/bridges.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/dircommon/fp_pair.h"
|
||||
#include "feature/nodelist/authcert.h"
|
||||
#include "feature/nodelist/dirlist.h"
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "app/config/config.h"
|
||||
#include "core/or/policies.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/nodelist/dirlist.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
|
@ -14,8 +14,9 @@
|
||||
|
||||
#include "core/or/circuitbuild.h"
|
||||
#include "app/config/config.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/nodelist/microdesc.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
|
@ -51,7 +51,9 @@
|
||||
#include "feature/control/control.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirauth/reachability.h"
|
||||
#include "core/or/dos.h"
|
||||
|
@ -18,7 +18,8 @@
|
||||
#include "core/or/policies.h"
|
||||
#include "core/or/reasons.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/nodelist/dirlist.h"
|
||||
#include "feature/nodelist/microdesc.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
|
@ -69,8 +69,10 @@
|
||||
#include "feature/client/bridges.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/dirauth/mode.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/dirauth/reachability.h"
|
||||
#include "feature/dirauth/process_descs.h"
|
||||
#include "feature/nodelist/authcert.h"
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirauth/process_descs.h"
|
||||
#include "feature/relay/dns.h"
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "lib/crypt_ops/crypto_dh.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/hs/hs_circuit.h"
|
||||
#include "feature/hs/hs_client.h"
|
||||
#include "feature/hs/hs_common.h"
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "lib/crypt_ops/crypto_dh.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/hs/hs_common.h"
|
||||
#include "feature/hs/hs_config.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
|
@ -4,14 +4,14 @@
|
||||
#include "orconfig.h"
|
||||
|
||||
#define BUFFERS_PRIVATE
|
||||
#define DIRECTORY_PRIVATE
|
||||
#define DIRCACHE_PRIVATE
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "lib/err/backtrace.h"
|
||||
#include "lib/container/buffers.h"
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircache/dircache.h"
|
||||
#include "lib/log/log.h"
|
||||
|
||||
#include "feature/dircommon/dir_connection_st.h"
|
||||
@ -132,4 +132,3 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/rend/rendcache.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "core/or/connection_or.h"
|
||||
#include "lib/net/resolve.h"
|
||||
|
||||
|
@ -9,8 +9,11 @@
|
||||
#define BWAUTH_PRIVATE
|
||||
#define CONFIG_PRIVATE
|
||||
#define CONTROL_PRIVATE
|
||||
#define DIRCACHE_PRIVATE
|
||||
#define DIRCLIENT_PRIVATE
|
||||
#define DIRSERV_PRIVATE
|
||||
#define DIRVOTE_PRIVATE
|
||||
#define DLSTATUS_PRIVATE
|
||||
#define HIBERNATE_PRIVATE
|
||||
#define NETWORKSTATUS_PRIVATE
|
||||
#define NODE_SELECT_PRIVATE
|
||||
@ -30,8 +33,11 @@
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
#include "lib/crypt_ops/crypto_format.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirclient/dlstatus.h"
|
||||
#include "feature/dirauth/bwauth.h"
|
||||
#include "feature/dircache/dircache.h"
|
||||
#include "feature/dircache/dirserv.h"
|
||||
#include "feature/dirauth/process_descs.h"
|
||||
#include "feature/dirauth/dirvote.h"
|
||||
|
@ -8,12 +8,14 @@
|
||||
#define CONNECTION_PRIVATE
|
||||
#define CONFIG_PRIVATE
|
||||
#define RENDCACHE_PRIVATE
|
||||
#define DIRCACHE_PRIVATE
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/dircache/consdiffmgr.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dircache/dircache.h"
|
||||
#include "test/test.h"
|
||||
#include "lib/compress/compress.h"
|
||||
#include "feature/rend/rendcommon.h"
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define STATEFILE_PRIVATE
|
||||
#define ENTRYNODES_PRIVATE
|
||||
#define ROUTERLIST_PRIVATE
|
||||
#define DIRECTORY_PRIVATE
|
||||
#define DIRCLIENT_PRIVATE
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "test/test.h"
|
||||
@ -19,7 +19,8 @@
|
||||
#include "app/config/config.h"
|
||||
#include "app/config/confparse.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
|
@ -7,13 +7,15 @@
|
||||
*/
|
||||
|
||||
#define CONNECTION_PRIVATE
|
||||
#define DIRECTORY_PRIVATE
|
||||
#define DIRCACHE_PRIVATE
|
||||
#define DIRCLIENT_PRIVATE
|
||||
#define HS_CACHE_PRIVATE
|
||||
|
||||
#include "trunnel/ed25519_cert.h"
|
||||
#include "feature/hs/hs_cache.h"
|
||||
#include "feature/rend/rendcache.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircache/dircache.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "core/proto/proto_http.h"
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "lib/crypt_ops/crypto_cipher.h"
|
||||
#include "lib/crypt_ops/crypto_dh.h"
|
||||
#include "core/or/channeltls.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "feature/nodelist/routerset.h"
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "feature/hs/hs_service.h"
|
||||
#include "app/config/config.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirauth/dirvote.h"
|
||||
#include "feature/nodelist/nodelist.h"
|
||||
#include "feature/nodelist/routerlist.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "core/or/connection_or.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "test/test.h"
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#define CONNECTION_PRIVATE
|
||||
#define DIRECTORY_PRIVATE
|
||||
#define DIRCLIENT_PRIVATE
|
||||
#define DIRVOTE_PRIVATE
|
||||
#define ENTRYNODES_PRIVATE
|
||||
#define HIBERNATE_PRIVATE
|
||||
@ -19,7 +19,8 @@
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "feature/dircache/directory.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "feature/dirclient/dirclient.h"
|
||||
#include "feature/dirauth/dirvote.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/hibernate/hibernate.h"
|
||||
|
Loading…
Reference in New Issue
Block a user