diff --git a/src/or/bridges.c b/src/or/bridges.c
index 699e030e6c..d5a9d05b49 100644
--- a/src/or/bridges.c
+++ b/src/or/bridges.c
@@ -27,6 +27,8 @@
#include "routerset.h"
#include "transports.h"
+#include "node_st.h"
+
/** Information about a configured bridge. Currently this just matches the
* ones in the torrc file, but one day we may be able to learn about new
* bridges on our own, and remember them in the state file. */
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 0df616a5ac..42ce1cfdaa 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -67,6 +67,7 @@
#include "cpath_build_state_st.h"
#include "entry_connection_st.h"
+#include "node_st.h"
#include "or_circuit_st.h"
#include "origin_circuit_st.h"
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index ce018e8742..e177b0ee2d 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -100,6 +100,7 @@
#include "cpath_build_state_st.h"
#include "dir_connection_st.h"
#include "entry_connection_st.h"
+#include "node_st.h"
#include "or_circuit_st.h"
#include "origin_circuit_st.h"
#include "socks_request_st.h"
diff --git a/src/or/control.c b/src/or/control.c
index 20da122596..ee79dfcd52 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -84,6 +84,7 @@
#include "control_connection_st.h"
#include "cpath_build_state_st.h"
#include "entry_connection_st.h"
+#include "node_st.h"
#include "or_connection_st.h"
#include "or_circuit_st.h"
#include "origin_circuit_st.h"
diff --git a/src/or/dirauth/dirvote.c b/src/or/dirauth/dirvote.c
index ae2de57a84..41acc21d67 100644
--- a/src/or/dirauth/dirvote.c
+++ b/src/or/dirauth/dirvote.c
@@ -29,6 +29,7 @@
#include "dirauth/shared_random_state.h"
#include "dir_server_st.h"
+#include "node_st.h"
#include "vote_timing_st.h"
/**
diff --git a/src/or/directory.c b/src/or/directory.c
index 00605c054a..8392dd81f2 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -57,6 +57,7 @@
#include "dir_connection_st.h"
#include "dir_server_st.h"
#include "entry_connection_st.h"
+#include "node_st.h"
#include "rend_service_descriptor_st.h"
/**
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 038b47e01a..3af057c6ce 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -37,6 +37,7 @@
#include "dirauth/dirvote.h"
#include "dir_connection_st.h"
+#include "node_st.h"
#include "tor_version_st.h"
/**
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 8aac07451c..62a65f2494 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -139,6 +139,7 @@
#include "transports.h"
#include "statefile.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
/** A list of existing guard selection contexts. */
diff --git a/src/or/hs_circuit.c b/src/or/hs_circuit.c
index b5ac7184a0..761edd6210 100644
--- a/src/or/hs_circuit.c
+++ b/src/or/hs_circuit.c
@@ -35,6 +35,7 @@
#include "cpath_build_state_st.h"
#include "crypt_path_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
/* A circuit is about to become an e2e rendezvous circuit. Check
diff --git a/src/or/hs_common.c b/src/or/hs_common.c
index afe80467aa..c5f59059e4 100644
--- a/src/or/hs_common.c
+++ b/src/or/hs_common.c
@@ -34,6 +34,7 @@
#include "dirauth/shared_random_state.h"
#include "edge_connection_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
/* Trunnel */
diff --git a/src/or/hs_control.c b/src/or/hs_control.c
index 6b9b95c6d8..4f3dd62c61 100644
--- a/src/or/hs_control.c
+++ b/src/or/hs_control.c
@@ -15,6 +15,8 @@
#include "hs_service.h"
#include "nodelist.h"
+#include "node_st.h"
+
/* Send on the control port the "HS_DESC REQUESTEDÂ [...]" event.
*
* The onion_pk is the onion service public key, base64_blinded_pk is the
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 6c2c167347..90e607225b 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -41,6 +41,7 @@
#include "dir_connection_st.h"
#include "edge_connection_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
/* Trunnel */
diff --git a/src/or/include.am b/src/or/include.am
index 4e0e1e9a4e..ee1ee562c6 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -248,6 +248,7 @@ ORHEADERS = \
src/or/microdesc.h \
src/or/networkstatus.h \
src/or/nodelist.h \
+ src/or/node_st.h \
src/or/ntmain.h \
src/or/onion.h \
src/or/onion_fast.h \
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index b4a934e095..f06c4bd2ae 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -22,6 +22,8 @@
#include "routerlist.h"
#include "routerparse.h"
+#include "node_st.h"
+
/** A data structure to hold a bunch of cached microdescriptors. There are
* two active files in the cache: a "cache file" that we mmap, and a "journal
* file" that we append to. Periodically, we rebuild the cache file to hold
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 3694da49dd..4ac2034cdf 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -76,6 +76,7 @@
#include "dir_connection_st.h"
#include "dir_server_st.h"
+#include "node_st.h"
/** Most recently received and validated v3 "ns"-flavored consensus network
* status. */
diff --git a/src/or/node_st.h b/src/or/node_st.h
new file mode 100644
index 0000000000..511e23ad17
--- /dev/null
+++ b/src/or/node_st.h
@@ -0,0 +1,100 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef NODE_ST_H
+#define NODE_ST_H
+
+/** A node_t represents a Tor router.
+ *
+ * Specifically, a node_t is a Tor router as we are using it: a router that
+ * we are considering for circuits, connections, and so on. A node_t is a
+ * thin wrapper around the routerstatus, routerinfo, and microdesc for a
+ * single router, and provides a consistent interface for all of them.
+ *
+ * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
+ * and a microdesc have[*] only the information read from a router
+ * descriptor, a consensus entry, and a microdescriptor (respectively)...
+ * a node_t has flags based on *our own current opinion* of the node.
+ *
+ * [*] Actually, there is some leftover information in each that is mutable.
+ * We should try to excise that.
+ */
+struct node_t {
+ /* Indexing information */
+
+ /** Used to look up the node_t by its identity digest. */
+ HT_ENTRY(node_t) ht_ent;
+ /** Used to look up the node_t by its ed25519 identity digest. */
+ HT_ENTRY(node_t) ed_ht_ent;
+ /** Position of the node within the list of nodes */
+ int nodelist_idx;
+
+ /** The identity digest of this node_t. No more than one node_t per
+ * identity may exist at a time. */
+ char identity[DIGEST_LEN];
+
+ /** The ed25519 identity of this node_t. This field is nonzero iff we
+ * currently have an ed25519 identity for this node in either md or ri,
+ * _and_ this node has been inserted to the ed25519-to-node map in the
+ * nodelist.
+ */
+ ed25519_public_key_t ed25519_id;
+
+ microdesc_t *md;
+ routerinfo_t *ri;
+ routerstatus_t *rs;
+
+ /* local info: copied from routerstatus, then possibly frobbed based
+ * on experience. Authorities set this stuff directly. Note that
+ * these reflect knowledge of the primary (IPv4) OR port only. */
+
+ unsigned int is_running:1; /**< As far as we know, is this OR currently
+ * running? */
+ unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
+ * (For Authdir: Have we validated this OR?) */
+ unsigned int is_fast:1; /** Do we think this is a fast OR? */
+ unsigned int is_stable:1; /** Do we think this is a stable OR? */
+ unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
+ unsigned int is_exit:1; /**< Do we think this is an OK exit? */
+ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
+ * or otherwise nasty? */
+ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
+ * directory according to the authorities. */
+
+ /* Local info: warning state. */
+
+ unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
+ * to this (unnamed) router by nickname?
+ */
+
+ /** Local info: we treat this node as if it rejects everything */
+ unsigned int rejects_all:1;
+
+ /* Local info: derived. */
+
+ /** True if the IPv6 OR port is preferred over the IPv4 OR port.
+ * XX/teor - can this become out of date if the torrc changes? */
+ unsigned int ipv6_preferred:1;
+
+ /** According to the geoip db what country is this router in? */
+ /* XXXprop186 what is this suppose to mean with multiple OR ports? */
+ country_t country;
+
+ /* The below items are used only by authdirservers for
+ * reachability testing. */
+
+ /** When was the last time we could reach this OR? */
+ time_t last_reachable; /* IPv4. */
+ time_t last_reachable6; /* IPv6. */
+
+ /* Hidden service directory index data. This is used by a service or client
+ * in order to know what's the hs directory index for this node at the time
+ * the consensus is set. */
+ struct hsdir_index_t hsdir_index;
+};
+
+#endif
+
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 4d67904c81..2c78c35ab5 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -69,6 +69,7 @@
#include "dirauth/mode.h"
#include "dir_server_st.h"
+#include "node_st.h"
static void nodelist_drop_node(node_t *node, int remove_from_ht);
#define node_free(val) \
@@ -634,6 +635,14 @@ nodelist_set_consensus(networkstatus_t *ns)
}
}
+/** Return 1 iff node has Exit flag and no BadExit flag.
+ * Otherwise, return 0.
+ */
+int node_is_good_exit(const node_t *node)
+{
+ return node->is_exit && ! node->is_bad_exit;
+}
+
/** Helper: return true iff a node has a usable amount of information*/
static inline int
node_is_usable(const node_t *node)
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 1ffba2e8df..fd91a26832 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -46,6 +46,7 @@ void node_get_verbose_nickname(const node_t *node,
void node_get_verbose_nickname_by_id(const char *id_digest,
char *verbose_name_out);
int node_is_dir(const node_t *node);
+int node_is_good_exit(const node_t *node);
int node_has_any_descriptor(const node_t *node);
int node_has_preferred_descriptor(const node_t *node,
int for_direct_connect);
diff --git a/src/or/or.h b/src/or/or.h
index 19d0bb2ab6..f2de729ece 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1857,94 +1857,7 @@ typedef struct microdesc_t {
} microdesc_t;
-/** A node_t represents a Tor router.
- *
- * Specifically, a node_t is a Tor router as we are using it: a router that
- * we are considering for circuits, connections, and so on. A node_t is a
- * thin wrapper around the routerstatus, routerinfo, and microdesc for a
- * single router, and provides a consistent interface for all of them.
- *
- * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
- * and a microdesc have[*] only the information read from a router
- * descriptor, a consensus entry, and a microdescriptor (respectively)...
- * a node_t has flags based on *our own current opinion* of the node.
- *
- * [*] Actually, there is some leftover information in each that is mutable.
- * We should try to excise that.
- */
-typedef struct node_t {
- /* Indexing information */
-
- /** Used to look up the node_t by its identity digest. */
- HT_ENTRY(node_t) ht_ent;
- /** Used to look up the node_t by its ed25519 identity digest. */
- HT_ENTRY(node_t) ed_ht_ent;
- /** Position of the node within the list of nodes */
- int nodelist_idx;
-
- /** The identity digest of this node_t. No more than one node_t per
- * identity may exist at a time. */
- char identity[DIGEST_LEN];
-
- /** The ed25519 identity of this node_t. This field is nonzero iff we
- * currently have an ed25519 identity for this node in either md or ri,
- * _and_ this node has been inserted to the ed25519-to-node map in the
- * nodelist.
- */
- ed25519_public_key_t ed25519_id;
-
- microdesc_t *md;
- routerinfo_t *ri;
- routerstatus_t *rs;
-
- /* local info: copied from routerstatus, then possibly frobbed based
- * on experience. Authorities set this stuff directly. Note that
- * these reflect knowledge of the primary (IPv4) OR port only. */
-
- unsigned int is_running:1; /**< As far as we know, is this OR currently
- * running? */
- unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
- * (For Authdir: Have we validated this OR?) */
- unsigned int is_fast:1; /** Do we think this is a fast OR? */
- unsigned int is_stable:1; /** Do we think this is a stable OR? */
- unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
- unsigned int is_exit:1; /**< Do we think this is an OK exit? */
- unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
- * or otherwise nasty? */
- unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
- * directory according to the authorities. */
-
- /* Local info: warning state. */
-
- unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
- * to this (unnamed) router by nickname?
- */
-
- /** Local info: we treat this node as if it rejects everything */
- unsigned int rejects_all:1;
-
- /* Local info: derived. */
-
- /** True if the IPv6 OR port is preferred over the IPv4 OR port.
- * XX/teor - can this become out of date if the torrc changes? */
- unsigned int ipv6_preferred:1;
-
- /** According to the geoip db what country is this router in? */
- /* XXXprop186 what is this suppose to mean with multiple OR ports? */
- country_t country;
-
- /* The below items are used only by authdirservers for
- * reachability testing. */
-
- /** When was the last time we could reach this OR? */
- time_t last_reachable; /* IPv4. */
- time_t last_reachable6; /* IPv6. */
-
- /* Hidden service directory index data. This is used by a service or client
- * in order to know what's the hs directory index for this node at the time
- * the consensus is set. */
- struct hsdir_index_t hsdir_index;
-} node_t;
+typedef struct node_t node_t;
/** Linked list of microdesc hash lines for a single router in a directory
* vote.
@@ -2385,14 +2298,6 @@ typedef enum {
/** Convert a circuit subtype to a circuit_t. */
#define TO_CIRCUIT(x) (&((x)->base_))
-/** Return 1 iff node has Exit flag and no BadExit flag.
- * Otherwise, return 0.
- */
-static inline int node_is_good_exit(const node_t *node)
-{
- return node->is_exit && ! node->is_bad_exit;
-}
-
/* limits for TCP send and recv buffer size used for constrained sockets */
#define MIN_CONSTRAINED_TCP_BUFFER 2048
#define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */
diff --git a/src/or/policies.c b/src/or/policies.c
index 51dc83827e..78cbcd5cd2 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -31,6 +31,7 @@
#include "ht.h"
#include "dir_server_st.h"
+#include "node_st.h"
#include "port_cfg_st.h"
/** Policy that addresses for incoming SOCKS connections must match. */
diff --git a/src/or/router.c b/src/or/router.c
index 2d03058893..6d8f61d716 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -42,6 +42,7 @@
#include "crypt_path_st.h"
#include "dir_connection_st.h"
#include "dir_server_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
#include "port_cfg_st.h"
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 970eac8d3f..313685784a 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -127,6 +127,7 @@
#include "dir_connection_st.h"
#include "dir_server_st.h"
+#include "node_st.h"
// #define DEBUG_ROUTERLIST
diff --git a/src/or/routerset.c b/src/or/routerset.c
index a2599b316c..8a6ff3b582 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -36,6 +36,8 @@
#include "routerparse.h"
#include "routerset.h"
+#include "node_st.h"
+
/** Return a new empty routerset. */
routerset_t *
routerset_new(void)
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index 93d5dc8469..6f9c2706c2 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -26,6 +26,7 @@
#include "dir_connection_st.h"
#include "entry_connection_st.h"
+#include "node_st.h"
#include "or_connection_st.h"
#include "socks_request_st.h"
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index bff6a40bd3..cf9da232ca 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -33,6 +33,7 @@
#include "cpath_build_state_st.h"
#include "crypt_path_st.h"
#include "dir_connection_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
#include "test_helpers.h"
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 91cc7d4d2e..78d10b261f 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -25,6 +25,7 @@
#include "routerlist.h"
#include "connection_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
#include "test.h"
diff --git a/src/test/test_hs.c b/src/test/test_hs.c
index 9343d131f2..c546af2fe9 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -22,6 +22,7 @@
#include "routerset.h"
#include "circuitbuild.h"
+#include "node_st.h"
#include "rend_encoded_v2_service_descriptor_st.h"
#include "rend_intro_point_st.h"
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index 8bcb2c7e46..21a109d2bc 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -33,6 +33,8 @@
#include "util.h"
#include "voting_schedule.h"
+#include "node_st.h"
+
/** Test the validation of HS v3 addresses */
static void
test_validate_address(void *arg)
diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c
index 308843e9b8..1fcea44f4b 100644
--- a/src/test/test_hs_control.c
+++ b/src/test/test_hs_control.c
@@ -7,10 +7,6 @@
**/
#define CONTROL_PRIVATE
-#define CIRCUITBUILD_PRIVATE
-#define RENDCOMMON_PRIVATE
-#define RENDSERVICE_PRIVATE
-#define HS_SERVICE_PRIVATE
#include "or.h"
#include "test.h"
@@ -19,10 +15,9 @@
#include "hs_common.h"
#include "hs_control.h"
#include "nodelist.h"
-//#include "rendcommon.h"
-//#include "rendservice.h"
-//#include "routerset.h"
-//#include "circuitbuild.h"
+
+#include "node_st.h"
+
#include "test_helpers.h"
/* mock ID digest and longname for node that's in nodelist */
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 3487785500..83a9d3cb59 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -55,6 +55,7 @@
#include "cpath_build_state_st.h"
#include "crypt_path_st.h"
+#include "node_st.h"
#include "origin_circuit_st.h"
/* Trunnel */
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index 9499fd0380..a3f2de29f0 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -11,6 +11,9 @@
#include "networkstatus.h"
#include "nodelist.h"
#include "torcert.h"
+
+#include "node_st.h"
+
#include "test.h"
/** Test the case when node_get_by_id() returns NULL,
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index e55452d3e4..673336eaeb 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -10,6 +10,7 @@
#include "policies.h"
#include "test.h"
+#include "node_st.h"
#include "port_cfg_st.h"
/* Helper: assert that short_policy parses and writes back out as itself,
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index d66f8933de..bf97499eee 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -35,6 +35,7 @@
#include "statefile.h"
#include "dir_connection_st.h"
+#include "node_st.h"
#include "test.h"
#include "test_dir_common.h"
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index c541324674..0e1ad3fdfa 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -9,6 +9,9 @@
#include "routerparse.h"
#include "policies.h"
#include "nodelist.h"
+
+#include "node_st.h"
+
#include "test.h"
#define NS_MODULE routerset