aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dircommon
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/dircommon')
-rw-r--r--src/feature/dircommon/.may_include1
-rw-r--r--src/feature/dircommon/consdiff.c50
-rw-r--r--src/feature/dircommon/consdiff.h22
-rw-r--r--src/feature/dircommon/dir_connection_st.h13
-rw-r--r--src/feature/dircommon/directory.c117
-rw-r--r--src/feature/dircommon/directory.h9
-rw-r--r--src/feature/dircommon/feature_dircommon.md7
-rw-r--r--src/feature/dircommon/fp_pair.c19
-rw-r--r--src/feature/dircommon/fp_pair.h6
-rw-r--r--src/feature/dircommon/include.am14
-rw-r--r--src/feature/dircommon/vote_timing_st.h10
-rw-r--r--src/feature/dircommon/voting_schedule.c194
-rw-r--r--src/feature/dircommon/voting_schedule.h65
13 files changed, 180 insertions, 347 deletions
diff --git a/src/feature/dircommon/.may_include b/src/feature/dircommon/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dircommon/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c
index d0f7594ce3..e42378c44c 100644
--- a/src/feature/dircommon/consdiff.c
+++ b/src/feature/dircommon/consdiff.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -101,11 +101,11 @@ smartlist_add_linecpy(smartlist_t *lst, memarea_t *area, const char *s)
/* This is a separate, mockable function so that we can override it when
* fuzzing. */
MOCK_IMPL(STATIC int,
-consensus_compute_digest,(const char *cons,
+consensus_compute_digest,(const char *cons, size_t len,
consensus_digest_t *digest_out))
{
int r = crypto_digest256((char*)digest_out->sha3_256,
- cons, strlen(cons), DIGEST_SHA3_256);
+ cons, len, DIGEST_SHA3_256);
return r;
}
@@ -114,11 +114,11 @@ consensus_compute_digest,(const char *cons,
/* This is a separate, mockable function so that we can override it when
* fuzzing. */
MOCK_IMPL(STATIC int,
-consensus_compute_digest_as_signed,(const char *cons,
+consensus_compute_digest_as_signed,(const char *cons, size_t len,
consensus_digest_t *digest_out))
{
return router_get_networkstatus_v3_sha3_as_signed(digest_out->sha3_256,
- cons);
+ cons, len);
}
/** Return true iff <b>d1</b> and <b>d2</b> contain the same digest */
@@ -530,10 +530,12 @@ typedef struct router_id_iterator_t {
cdline_t hash;
} router_id_iterator_t;
+#ifndef COCCI
/**
* Initializer for a router_id_iterator_t.
*/
#define ROUTER_ID_ITERATOR_INIT { { NULL, 0 }, { NULL, 0 } }
+#endif /* !defined(COCCI) */
/** Given an index *<b>idxp</b> into the consensus at <b>cons</b>, advance
* the index to the next router line ("r ...") in the consensus, or to
@@ -570,7 +572,7 @@ find_next_router_line(const smartlist_t *cons,
/** Pre-process a consensus in <b>cons</b> (represented as a list of cdline_t)
* to remove the signatures from it. If the footer is removed, return a
* cdline_t containing a delete command to delete the footer, allocated in
- * <b>area</>. If no footer is removed, return NULL.
+ * <b>area</b>. If no footer is removed, return NULL.
*
* We remove the signatures here because they are not themselves signed, and
* as such there might be different encodings for them.
@@ -1048,7 +1050,7 @@ consdiff_gen_diff(const smartlist_t *cons1,
if (smartlist_len(cons2) == smartlist_len(ed_cons2)) {
SMARTLIST_FOREACH_BEGIN(cons2, const cdline_t *, line1) {
const cdline_t *line2 = smartlist_get(ed_cons2, line1_sl_idx);
- if (! lines_eq(line1, line2) ) {
+ if (!lines_eq(line1, line2)) {
cons2_eq = 0;
break;
}
@@ -1229,7 +1231,8 @@ consdiff_apply_diff(const smartlist_t *cons1,
cons2_str = consensus_join_lines(cons2);
consensus_digest_t cons2_digests;
- if (consensus_compute_digest(cons2_str, &cons2_digests) < 0) {
+ if (consensus_compute_digest(cons2_str, strlen(cons2_str),
+ &cons2_digests) < 0) {
/* LCOV_EXCL_START -- digest can't fail */
log_warn(LD_CONSDIFF, "Could not compute digests of the consensus "
"resulting from applying a consensus diff.");
@@ -1283,12 +1286,13 @@ consdiff_apply_diff(const smartlist_t *cons1,
* generated cdlines will become invalid.
*/
STATIC int
-consensus_split_lines(smartlist_t *out, const char *s, memarea_t *area)
+consensus_split_lines(smartlist_t *out,
+ const char *s, size_t len,
+ memarea_t *area)
{
- const char *end_of_str = s + strlen(s);
- tor_assert(*end_of_str == '\0');
+ const char *end_of_str = s + len;
- while (*s) {
+ while (s < end_of_str) {
const char *eol = memchr(s, '\n', end_of_str - s);
if (!eol) {
/* File doesn't end with newline. */
@@ -1334,25 +1338,25 @@ consensus_join_lines(const smartlist_t *inp)
* success, retun a newly allocated string containing that diff. On failure,
* return NULL. */
char *
-consensus_diff_generate(const char *cons1,
- const char *cons2)
+consensus_diff_generate(const char *cons1, size_t cons1len,
+ const char *cons2, size_t cons2len)
{
consensus_digest_t d1, d2;
smartlist_t *lines1 = NULL, *lines2 = NULL, *result_lines = NULL;
int r1, r2;
char *result = NULL;
- r1 = consensus_compute_digest_as_signed(cons1, &d1);
- r2 = consensus_compute_digest(cons2, &d2);
+ r1 = consensus_compute_digest_as_signed(cons1, cons1len, &d1);
+ r2 = consensus_compute_digest(cons2, cons2len, &d2);
if (BUG(r1 < 0 || r2 < 0))
return NULL; // LCOV_EXCL_LINE
memarea_t *area = memarea_new();
lines1 = smartlist_new();
lines2 = smartlist_new();
- if (consensus_split_lines(lines1, cons1, area) < 0)
+ if (consensus_split_lines(lines1, cons1, cons1len, area) < 0)
goto done;
- if (consensus_split_lines(lines2, cons2, area) < 0)
+ if (consensus_split_lines(lines2, cons2, cons2len, area) < 0)
goto done;
result_lines = consdiff_gen_diff(lines1, lines2, &d1, &d2, area);
@@ -1375,7 +1379,9 @@ consensus_diff_generate(const char *cons1,
* consensus. On failure, return NULL. */
char *
consensus_diff_apply(const char *consensus,
- const char *diff)
+ size_t consensus_len,
+ const char *diff,
+ size_t diff_len)
{
consensus_digest_t d1;
smartlist_t *lines1 = NULL, *lines2 = NULL;
@@ -1383,15 +1389,15 @@ consensus_diff_apply(const char *consensus,
char *result = NULL;
memarea_t *area = memarea_new();
- r1 = consensus_compute_digest_as_signed(consensus, &d1);
+ r1 = consensus_compute_digest_as_signed(consensus, consensus_len, &d1);
if (BUG(r1 < 0))
goto done;
lines1 = smartlist_new();
lines2 = smartlist_new();
- if (consensus_split_lines(lines1, consensus, area) < 0)
+ if (consensus_split_lines(lines1, consensus, consensus_len, area) < 0)
goto done;
- if (consensus_split_lines(lines2, diff, area) < 0)
+ if (consensus_split_lines(lines2, diff, diff_len, area) < 0)
goto done;
result = consdiff_apply_diff(lines1, lines2, &d1);
diff --git a/src/feature/dircommon/consdiff.h b/src/feature/dircommon/consdiff.h
index 98217e6d46..c2dcb6da24 100644
--- a/src/feature/dircommon/consdiff.h
+++ b/src/feature/dircommon/consdiff.h
@@ -1,16 +1,21 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file consdiff.h
+ * @brief Header for consdiff.c
+ **/
+
#ifndef TOR_CONSDIFF_H
#define TOR_CONSDIFF_H
#include "core/or/or.h"
-char *consensus_diff_generate(const char *cons1,
- const char *cons2);
-char *consensus_diff_apply(const char *consensus,
- const char *diff);
+char *consensus_diff_generate(const char *cons1, size_t cons1len,
+ const char *cons2, size_t cons2len);
+char *consensus_diff_apply(const char *consensus, size_t consensus_len,
+ const char *diff, size_t diff_len);
int looks_like_a_consensus_diff(const char *document, size_t len);
@@ -78,7 +83,8 @@ STATIC int smartlist_slice_string_pos(const smartlist_slice_t *slice,
STATIC void set_changed(bitarray_t *changed1, bitarray_t *changed2,
const smartlist_slice_t *slice1,
const smartlist_slice_t *slice2);
-STATIC int consensus_split_lines(smartlist_t *out, const char *s,
+STATIC int consensus_split_lines(smartlist_t *out,
+ const char *s, size_t len,
struct memarea_t *area);
STATIC void smartlist_add_linecpy(smartlist_t *lst, struct memarea_t *area,
const char *s);
@@ -86,10 +92,10 @@ STATIC int lines_eq(const cdline_t *a, const cdline_t *b);
STATIC int line_str_eq(const cdline_t *a, const char *b);
MOCK_DECL(STATIC int,
- consensus_compute_digest,(const char *cons,
+ consensus_compute_digest,(const char *cons, size_t len,
consensus_digest_t *digest_out));
MOCK_DECL(STATIC int,
- consensus_compute_digest_as_signed,(const char *cons,
+ consensus_compute_digest_as_signed,(const char *cons, size_t len,
consensus_digest_t *digest_out));
MOCK_DECL(STATIC int,
consensus_digest_eq,(const uint8_t *d1,
diff --git a/src/feature/dircommon/dir_connection_st.h b/src/feature/dircommon/dir_connection_st.h
index 8c59cc7a46..12230e6741 100644
--- a/src/feature/dircommon/dir_connection_st.h
+++ b/src/feature/dircommon/dir_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dir_connection_st.h
+ * @brief Client/server directory connection structure.
+ **/
+
#ifndef DIR_CONNECTION_ST_H
#define DIR_CONNECTION_ST_H
@@ -23,7 +28,9 @@ struct dir_connection_t {
* fingerprints.
**/
char *requested_resource;
- unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
+ /** Is this dirconn direct, or via a multi-hop Tor circuit?
+ * Direct connections can use the DirPort, or BEGINDIR over the ORPort. */
+ unsigned int dirconn_direct:1;
/** If we're fetching descriptors, what router purpose shall we assign
* to them? */
@@ -64,4 +71,4 @@ struct dir_connection_t {
#endif /* defined(MEASUREMENTS_21206) */
};
-#endif
+#endif /* !defined(DIR_CONNECTION_ST_H) */
diff --git a/src/feature/dircommon/directory.c b/src/feature/dircommon/directory.c
index 9e6f72e9ac..b177fe5201 100644
--- a/src/feature/dircommon/directory.c
+++ b/src/feature/dircommon/directory.c
@@ -1,12 +1,16 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, 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 "core/or/circuitlist.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "core/or/channeltls.h"
#include "feature/dircache/dircache.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
@@ -15,6 +19,10 @@
#include "feature/stats/geoip_stats.h"
#include "lib/compress/compress.h"
+#include "core/or/circuit_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/edge_connection_st.h"
+#include "core/or/or_connection_st.h"
#include "feature/dircommon/dir_connection_st.h"
#include "feature/nodelist/routerinfo_st.h"
@@ -167,6 +175,82 @@ connection_dir_is_encrypted(const dir_connection_t *conn)
return TO_CONN(conn)->linked;
}
+/** Return true iff the given directory connection <b>dir_conn</b> is
+ * anonymous, that is, it is on a circuit via a public relay and not directly
+ * from a client or bridge.
+ *
+ * For client circuits via relays: true for 2-hop+ paths.
+ * For client circuits via bridges: true for 3-hop+ paths.
+ *
+ * This first test if the connection is encrypted since it is a strong
+ * requirement for anonymity. */
+bool
+connection_dir_is_anonymous(const dir_connection_t *dir_conn)
+{
+ const connection_t *conn, *linked_conn;
+ const edge_connection_t *edge_conn;
+ const circuit_t *circ;
+
+ tor_assert(dir_conn);
+
+ if (!connection_dir_is_encrypted(dir_conn)) {
+ return false;
+ }
+
+ /*
+ * Buckle up, we'll do a deep dive into the connection in order to get the
+ * final connection channel of that connection in order to figure out if
+ * this is a client or relay link.
+ *
+ * We go: dir_conn -> linked_conn -> edge_conn -> on_circuit -> p_chan.
+ */
+
+ conn = TO_CONN(dir_conn);
+ linked_conn = conn->linked_conn;
+
+ /* The dir connection should be connected to an edge connection. It can not
+ * be closed or marked for close. */
+ if (linked_conn == NULL || linked_conn->magic != EDGE_CONNECTION_MAGIC ||
+ conn->linked_conn_is_closed || conn->linked_conn->marked_for_close) {
+ log_debug(LD_DIR, "Directory connection is not anonymous: "
+ "not linked to edge");
+ return false;
+ }
+
+ edge_conn = TO_EDGE_CONN((connection_t *) linked_conn);
+ circ = edge_conn->on_circuit;
+
+ /* Can't be a circuit we initiated and without a circuit, no channel. */
+ if (circ == NULL || CIRCUIT_IS_ORIGIN(circ)) {
+ log_debug(LD_DIR, "Directory connection is not anonymous: "
+ "not on OR circuit");
+ return false;
+ }
+
+ /* It is possible that the circuit was closed because one of the channel was
+ * closed or a DESTROY cell was received. Either way, this connection can
+ * not continue so return that it is not anonymous since we can not know for
+ * sure if it is. */
+ if (circ->marked_for_close) {
+ log_debug(LD_DIR, "Directory connection is not anonymous: "
+ "circuit marked for close");
+ return false;
+ }
+
+ /* Get the previous channel to learn if it is a client or relay link. We
+ * BUG() because if the circuit is not mark for close, we ought to have a
+ * p_chan else we have a code flow issue. */
+ if (BUG(CONST_TO_OR_CIRCUIT(circ)->p_chan == NULL)) {
+ log_debug(LD_DIR, "Directory connection is not anonymous: "
+ "no p_chan on circuit");
+ return false;
+ }
+
+ /* Will be true if the channel is an unauthenticated peer which is only true
+ * for clients and bridges. */
+ return !channel_is_client(CONST_TO_OR_CIRCUIT(circ)->p_chan);
+}
+
/** 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
@@ -618,34 +702,3 @@ dir_split_resource_into_fingerprints(const char *resource,
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;
-}
diff --git a/src/feature/dircommon/directory.h b/src/feature/dircommon/directory.h
index ba3f8c1b0e..0f26cdeff9 100644
--- a/src/feature/dircommon/directory.h
+++ b/src/feature/dircommon/directory.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -94,6 +94,7 @@ int parse_http_command(const char *headers,
char *http_get_header(const char *headers, const char *which);
int connection_dir_is_encrypted(const dir_connection_t *conn);
+bool connection_dir_is_anonymous(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);
@@ -107,12 +108,6 @@ void connection_dir_about_to_close(dir_connection_t *dir_conn);
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);
diff --git a/src/feature/dircommon/feature_dircommon.md b/src/feature/dircommon/feature_dircommon.md
new file mode 100644
index 0000000000..359049ecd8
--- /dev/null
+++ b/src/feature/dircommon/feature_dircommon.md
@@ -0,0 +1,7 @@
+@dir /feature/dircommon
+@brief feature/dircommon: Directory client and server shared code
+
+This module has the code that directory clients (anybody who download
+information about relays) and directory servers (anybody who serves such
+information) share in common.
+
diff --git a/src/feature/dircommon/fp_pair.c b/src/feature/dircommon/fp_pair.c
index 284600df77..87e1c253bd 100644
--- a/src/feature/dircommon/fp_pair.c
+++ b/src/feature/dircommon/fp_pair.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,14 +22,14 @@
/* Define fp_pair_map_t structures */
-struct fp_pair_map_entry_s {
- HT_ENTRY(fp_pair_map_entry_s) node;
+struct fp_pair_map_entry_t {
+ HT_ENTRY(fp_pair_map_entry_t) node;
void *val;
fp_pair_t key;
};
-struct fp_pair_map_s {
- HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_s) head;
+struct fp_pair_map_t {
+ HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_t) head;
};
/*
@@ -56,11 +56,11 @@ fp_pair_map_entry_hash(const fp_pair_map_entry_t *a)
* Hash table functions for fp_pair_map_t
*/
-HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_s, node,
- fp_pair_map_entry_hash, fp_pair_map_entries_eq)
-HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_s, node,
+HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_t, node,
+ fp_pair_map_entry_hash, fp_pair_map_entries_eq);
+HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_t, node,
fp_pair_map_entry_hash, fp_pair_map_entries_eq,
- 0.6, tor_reallocarray_, tor_free_)
+ 0.6, tor_reallocarray_, tor_free_);
/** Constructor to create a new empty map from fp_pair_t to void *
*/
@@ -312,4 +312,3 @@ fp_pair_map_assert_ok(const fp_pair_map_t *map)
{
tor_assert(!fp_pair_map_impl_HT_REP_IS_BAD_(&(map->head)));
}
-
diff --git a/src/feature/dircommon/fp_pair.h b/src/feature/dircommon/fp_pair.h
index 5041583e88..ae71ea7b71 100644
--- a/src/feature/dircommon/fp_pair.h
+++ b/src/feature/dircommon/fp_pair.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,8 +19,8 @@ typedef struct {
* Declare fp_pair_map_t functions and structs
*/
-typedef struct fp_pair_map_entry_s fp_pair_map_entry_t;
-typedef struct fp_pair_map_s fp_pair_map_t;
+typedef struct fp_pair_map_entry_t fp_pair_map_entry_t;
+typedef struct fp_pair_map_t fp_pair_map_t;
typedef fp_pair_map_entry_t *fp_pair_map_iter_t;
fp_pair_map_t * fp_pair_map_new(void);
diff --git a/src/feature/dircommon/include.am b/src/feature/dircommon/include.am
new file mode 100644
index 0000000000..87850ce183
--- /dev/null
+++ b/src/feature/dircommon/include.am
@@ -0,0 +1,14 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dircommon/consdiff.c \
+ src/feature/dircommon/directory.c \
+ src/feature/dircommon/fp_pair.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ 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
diff --git a/src/feature/dircommon/vote_timing_st.h b/src/feature/dircommon/vote_timing_st.h
index 47b90ab009..103d950f86 100644
--- a/src/feature/dircommon/vote_timing_st.h
+++ b/src/feature/dircommon/vote_timing_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_timing_st.h
+ * @brief Directory voting schedule structure.
+ **/
+
#ifndef VOTE_TIMING_ST_H
#define VOTE_TIMING_ST_H
@@ -20,5 +25,4 @@ struct vote_timing_t {
int dist_delay;
};
-#endif
-
+#endif /* !defined(VOTE_TIMING_ST_H) */
diff --git a/src/feature/dircommon/voting_schedule.c b/src/feature/dircommon/voting_schedule.c
deleted file mode 100644
index 0a7476eda7..0000000000
--- a/src/feature/dircommon/voting_schedule.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file voting_schedule.c
- * \brief This file contains functions that are from the directory authority
- * subsystem related to voting specifically but used by many part of
- * tor. The full feature is built as part of the dirauth module.
- **/
-
-#define VOTING_SCHEDULE_PRIVATE
-#include "feature/dircommon/voting_schedule.h"
-
-#include "core/or/or.h"
-#include "app/config/config.h"
-#include "feature/nodelist/networkstatus.h"
-
-#include "feature/nodelist/networkstatus_st.h"
-
-/* =====
- * Vote scheduling
- * ===== */
-
-/** Return the start of the next interval of size <b>interval</b> (in
- * seconds) after <b>now</b>, plus <b>offset</b>. Midnight always
- * starts a fresh interval, and if the last interval of a day would be
- * truncated to less than half its size, it is rolled into the
- * previous interval. */
-time_t
-voting_schedule_get_start_of_next_interval(time_t now, int interval,
- int offset)
-{
- struct tm tm;
- time_t midnight_today=0;
- time_t midnight_tomorrow;
- time_t next;
-
- tor_gmtime_r(&now, &tm);
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
-
- if (tor_timegm(&tm, &midnight_today) < 0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG, "Ran into an invalid time when trying to find midnight.");
- // LCOV_EXCL_STOP
- }
- midnight_tomorrow = midnight_today + (24*60*60);
-
- next = midnight_today + ((now-midnight_today)/interval + 1)*interval;
-
- /* Intervals never cross midnight. */
- if (next > midnight_tomorrow)
- next = midnight_tomorrow;
-
- /* If the interval would only last half as long as it's supposed to, then
- * skip over to the next day. */
- if (next + interval/2 > midnight_tomorrow)
- next = midnight_tomorrow;
-
- next += offset;
- if (next - interval > now)
- next -= interval;
-
- return next;
-}
-
-/* Populate and return a new voting_schedule_t that can be used to schedule
- * voting. The object is allocated on the heap and it's the responsibility of
- * the caller to free it. Can't fail. */
-static voting_schedule_t *
-get_voting_schedule(const or_options_t *options, time_t now, int severity)
-{
- int interval, vote_delay, dist_delay;
- time_t start;
- time_t end;
- networkstatus_t *consensus;
- voting_schedule_t *new_voting_schedule;
-
- new_voting_schedule = tor_malloc_zero(sizeof(voting_schedule_t));
-
- consensus = networkstatus_get_live_consensus(now);
-
- if (consensus) {
- interval = (int)( consensus->fresh_until - consensus->valid_after );
- vote_delay = consensus->vote_seconds;
- dist_delay = consensus->dist_seconds;
-
- /* Note down the consensus valid after, so that we detect outdated voting
- * schedules in case of skewed clocks etc. */
- new_voting_schedule->live_consensus_valid_after = consensus->valid_after;
- } else {
- interval = options->TestingV3AuthInitialVotingInterval;
- vote_delay = options->TestingV3AuthInitialVoteDelay;
- dist_delay = options->TestingV3AuthInitialDistDelay;
- }
-
- tor_assert(interval > 0);
-
- if (vote_delay + dist_delay > interval/2)
- vote_delay = dist_delay = interval / 4;
-
- start = new_voting_schedule->interval_starts =
- voting_schedule_get_start_of_next_interval(now,interval,
- options->TestingV3AuthVotingStartOffset);
- end = voting_schedule_get_start_of_next_interval(start+1, interval,
- options->TestingV3AuthVotingStartOffset);
-
- tor_assert(end > start);
-
- new_voting_schedule->fetch_missing_signatures = start - (dist_delay/2);
- new_voting_schedule->voting_ends = start - dist_delay;
- new_voting_schedule->fetch_missing_votes =
- start - dist_delay - (vote_delay/2);
- new_voting_schedule->voting_starts = start - dist_delay - vote_delay;
-
- {
- char tbuf[ISO_TIME_LEN+1];
- format_iso_time(tbuf, new_voting_schedule->interval_starts);
- tor_log(severity, LD_DIR,"Choosing expected valid-after time as %s: "
- "consensus_set=%d, interval=%d",
- tbuf, consensus?1:0, interval);
- }
-
- return new_voting_schedule;
-}
-
-#define voting_schedule_free(s) \
- FREE_AND_NULL(voting_schedule_t, voting_schedule_free_, (s))
-
-/** Frees a voting_schedule_t. This should be used instead of the generic
- * tor_free. */
-static void
-voting_schedule_free_(voting_schedule_t *voting_schedule_to_free)
-{
- if (!voting_schedule_to_free)
- return;
- tor_free(voting_schedule_to_free);
-}
-
-voting_schedule_t voting_schedule;
-
-/* Using the time <b>now</b>, return the next voting valid-after time. */
-time_t
-voting_schedule_get_next_valid_after_time(void)
-{
- time_t now = approx_time();
- bool need_to_recalculate_voting_schedule = false;
-
- /* This is a safe guard in order to make sure that the voting schedule
- * static object is at least initialized. Using this function with a zeroed
- * voting schedule can lead to bugs. */
- if (tor_mem_is_zero((const char *) &voting_schedule,
- sizeof(voting_schedule))) {
- need_to_recalculate_voting_schedule = true;
- goto done; /* no need for next check if we have to recalculate anyway */
- }
-
- /* Also make sure we are not using an outdated voting schedule. If we have a
- * newer consensus, make sure we recalculate the voting schedule. */
- const networkstatus_t *ns = networkstatus_get_live_consensus(now);
- if (ns && ns->valid_after != voting_schedule.live_consensus_valid_after) {
- log_info(LD_DIR, "Voting schedule is outdated: recalculating (%d/%d)",
- (int) ns->valid_after,
- (int) voting_schedule.live_consensus_valid_after);
- need_to_recalculate_voting_schedule = true;
- }
-
- done:
- if (need_to_recalculate_voting_schedule) {
- voting_schedule_recalculate_timing(get_options(), approx_time());
- voting_schedule.created_on_demand = 1;
- }
-
- return voting_schedule.interval_starts;
-}
-
-/** Set voting_schedule to hold the timing for the next vote we should be
- * doing. All type of tor do that because HS subsystem needs the timing as
- * well to function properly. */
-void
-voting_schedule_recalculate_timing(const or_options_t *options, time_t now)
-{
- voting_schedule_t *new_voting_schedule;
-
- /* get the new voting schedule */
- new_voting_schedule = get_voting_schedule(options, now, LOG_INFO);
- tor_assert(new_voting_schedule);
-
- /* Fill in the global static struct now */
- memcpy(&voting_schedule, new_voting_schedule, sizeof(voting_schedule));
- voting_schedule_free(new_voting_schedule);
-}
-
diff --git a/src/feature/dircommon/voting_schedule.h b/src/feature/dircommon/voting_schedule.h
deleted file mode 100644
index bafd81184e..0000000000
--- a/src/feature/dircommon/voting_schedule.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file voting_schedule.h
- * \brief Header file for voting_schedule.c.
- **/
-
-#ifndef TOR_VOTING_SCHEDULE_H
-#define TOR_VOTING_SCHEDULE_H
-
-#include "core/or/or.h"
-
-/** Scheduling information for a voting interval. */
-typedef struct {
- /** When do we generate and distribute our vote for this interval? */
- time_t voting_starts;
- /** When do we send an HTTP request for any votes that we haven't
- * been posted yet?*/
- time_t fetch_missing_votes;
- /** When do we give up on getting more votes and generate a consensus? */
- time_t voting_ends;
- /** When do we send an HTTP request for any signatures we're expecting to
- * see on the consensus? */
- time_t fetch_missing_signatures;
- /** When do we publish the consensus? */
- time_t interval_starts;
-
- /* True iff we have generated and distributed our vote. */
- int have_voted;
- /* True iff we've requested missing votes. */
- int have_fetched_missing_votes;
- /* True iff we have built a consensus and sent the signatures around. */
- int have_built_consensus;
- /* True iff we've fetched missing signatures. */
- int have_fetched_missing_signatures;
- /* True iff we have published our consensus. */
- int have_published_consensus;
-
- /* True iff this voting schedule was set on demand meaning not through the
- * normal vote operation of a dirauth or when a consensus is set. This only
- * applies to a directory authority that needs to recalculate the voting
- * timings only for the first vote even though this object was initilized
- * prior to voting. */
- int created_on_demand;
-
- /** The valid-after time of the last live consensus that filled this voting
- * schedule. It's used to detect outdated voting schedules. */
- time_t live_consensus_valid_after;
-} voting_schedule_t;
-
-/* Public API. */
-
-extern voting_schedule_t voting_schedule;
-
-void voting_schedule_recalculate_timing(const or_options_t *options,
- time_t now);
-
-time_t voting_schedule_get_start_of_next_interval(time_t now,
- int interval,
- int offset);
-time_t voting_schedule_get_next_valid_after_time(void);
-
-#endif /* TOR_VOTING_SCHEDULE_H */
-