aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/or/circuitbuild.c437
-rw-r--r--src/or/circuitbuild.h5
-rw-r--r--src/or/circuitlist.c9
-rw-r--r--src/or/circuituse.c66
-rw-r--r--src/or/circuituse.h3
-rw-r--r--src/or/command.c7
-rw-r--r--src/or/connection_edge.c36
-rw-r--r--src/or/connection_edge.h2
-rw-r--r--src/or/connection_or.c15
-rw-r--r--src/or/control.c46
-rw-r--r--src/or/directory.c33
-rw-r--r--src/or/dirserv.c199
-rw-r--r--src/or/dirserv.h10
-rw-r--r--src/or/dirvote.h1
-rw-r--r--src/or/microdesc.c1
-rw-r--r--src/or/networkstatus.c126
-rw-r--r--src/or/networkstatus.h5
-rw-r--r--src/or/nodelist.c418
-rw-r--r--src/or/nodelist.h39
-rw-r--r--src/or/or.h100
-rw-r--r--src/or/policies.c52
-rw-r--r--src/or/policies.h9
-rw-r--r--src/or/relay.c11
-rw-r--r--src/or/rendclient.c8
-rw-r--r--src/or/rendservice.c41
-rw-r--r--src/or/rephist.c33
-rw-r--r--src/or/router.c39
-rw-r--r--src/or/routerlist.c651
-rw-r--r--src/or/routerlist.h53
-rw-r--r--src/or/routerparse.c3
30 files changed, 1502 insertions, 956 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 02f361ce3..58d4e60fa 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -23,6 +23,7 @@
#include "directory.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "policies.h"
#include "relay.h"
@@ -54,8 +55,8 @@ extern circuit_t *global_circuitlist;
/** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just
- * use a routerinfo_t, since we want to remember these even when we
- * don't have a directory. */
+ * use a node_t, since we want to remember these even when we
+ * don't have any directory info. */
typedef struct {
char nickname[MAX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
@@ -94,7 +95,7 @@ static int circuit_deliver_create_cell(circuit_t *circ,
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
-static int count_acceptable_routers(smartlist_t *routers);
+static int count_acceptable_nodes(smartlist_t *routers);
static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static void entry_guards_changed(void);
@@ -1401,10 +1402,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
hop = circ->cpath;
do {
- const routerinfo_t *ri;
- const routerstatus_t *rs;
char *elt;
const char *id;
+ const node_t *node;
if (!hop)
break;
if (!verbose && hop->state != CPATH_STATE_OPEN)
@@ -1414,10 +1414,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
id = hop->extend_info->identity_digest;
if (verbose_names) {
elt = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1);
- if ((ri = router_get_by_digest(id))) {
- router_get_verbose_nickname(elt, ri);
- } else if ((rs = router_get_consensus_status_by_id(id))) {
- routerstatus_get_verbose_nickname(elt, rs);
+ if ((node = node_get_by_id(id))) {
+ node_get_verbose_nickname(node, elt);
} else if (is_legal_nickname(hop->extend_info->nickname)) {
elt[0] = '$';
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
@@ -1429,9 +1427,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
}
} else { /* ! verbose_names */
- if ((ri = router_get_by_digest(id)) &&
- ri->is_named) {
- elt = tor_strdup(hop->extend_info->nickname);
+ node = node_get_by_id(id);
+ if (node && node_is_named(node)) {
+ elt = tor_strdup(node_get_nickname(node));
} else {
elt = tor_malloc(HEX_DIGEST_LEN+2);
elt[0] = '$';
@@ -1501,7 +1499,6 @@ circuit_rep_hist_note_result(origin_circuit_t *circ)
{
crypt_path_t *hop;
const char *prev_digest = NULL;
- const routerinfo_t *router;
hop = circ->cpath;
if (!hop) /* circuit hasn't started building yet. */
return;
@@ -1512,19 +1509,17 @@ circuit_rep_hist_note_result(origin_circuit_t *circ)
prev_digest = me->cache_info.identity_digest;
}
do {
- router = router_get_by_digest(hop->extend_info->identity_digest);
- if (router) {
+ const node_t *node = node_get_by_id(hop->extend_info->identity_digest);
+ if (node) { /* Why do we check this? We know the identity. -NM XXXX */
if (prev_digest) {
if (hop->state == CPATH_STATE_OPEN)
- rep_hist_note_extend_succeeded(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_succeeded(prev_digest, node->identity);
else {
- rep_hist_note_extend_failed(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_failed(prev_digest, node->identity);
break;
}
}
- prev_digest = router->cache_info.identity_digest;
+ prev_digest = node->identity;
} else {
prev_digest = NULL;
}
@@ -1866,7 +1861,7 @@ int
circuit_send_next_onion_skin(origin_circuit_t *circ)
{
crypt_path_t *hop;
- const routerinfo_t *router;
+ const node_t *node;
char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
char *onionskin;
size_t payload_len;
@@ -1882,7 +1877,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
else
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
- router = router_get_by_digest(circ->_base.n_conn->identity_digest);
+ node = node_get_by_id(circ->_base.n_conn->identity_digest);
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We are an OR and we know the right onion key: we should
@@ -1916,7 +1911,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
fast ? "CREATE_FAST" : "CREATE",
- router ? router->nickname : "<unnamed>");
+ node ? node_get_nickname(node) : "<unnamed>");
} else {
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
@@ -2390,12 +2385,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
*/
static int
new_route_len(uint8_t purpose, extend_info_t *exit,
- smartlist_t *routers)
+ smartlist_t *nodes)
{
int num_acceptable_routers;
int routelen;
- tor_assert(routers);
+ tor_assert(nodes);
routelen = DEFAULT_ROUTE_LEN;
if (exit &&
@@ -2403,10 +2398,10 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
routelen++;
- num_acceptable_routers = count_acceptable_routers(routers);
+ num_acceptable_routers = count_acceptable_nodes(nodes);
log_debug(LD_CIRC,"Chosen route length %d (%d/%d routers suitable).",
- routelen, num_acceptable_routers, smartlist_len(routers));
+ routelen, num_acceptable_routers, smartlist_len(nodes));
if (num_acceptable_routers < 2) {
log_info(LD_CIRC,
@@ -2475,12 +2470,12 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
return enough;
}
-/** Return 1 if <b>router</b> can handle one or more of the ports in
+/** Return 1 if <b>node</b> can handle one or more of the ports in
* <b>needed_ports</b>, else return 0.
*/
static int
-router_handles_some_port(const routerinfo_t *router, smartlist_t *needed_ports)
-{
+node_handles_some_port(const node_t *node, smartlist_t *needed_ports)
+{ /* XXXX MOVE */
int i;
uint16_t port;
@@ -2490,7 +2485,10 @@ router_handles_some_port(const routerinfo_t *router, smartlist_t *needed_ports)
needed_ports is explicitly a smartlist of uint16_t's */
port = *(uint16_t *)smartlist_get(needed_ports, i);
tor_assert(port);
- r = compare_addr_to_addr_policy(0, port, router->exit_policy);
+ if (node)
+ r = compare_addr_to_node_policy(0, port, node);
+ else
+ continue;
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 1;
}
@@ -2523,18 +2521,17 @@ ap_stream_wants_exit_attention(connection_t *conn)
*
* Return NULL if we can't find any suitable routers.
*/
-static const routerinfo_t *
-choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
- int need_capacity)
+static const node_t *
+choose_good_exit_server_general(int need_uptime, int need_capacity)
{
int *n_supported;
- int i;
int n_pending_connections = 0;
smartlist_t *connections;
int best_support = -1;
int n_best_support=0;
- const routerinfo_t *router;
or_options_t *options = get_options();
+ const smartlist_t *the_nodes;
+ const node_t *node=NULL;
connections = get_connection_array();
@@ -2555,10 +2552,11 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*
* -1 means "Don't use this router at all."
*/
- n_supported = tor_malloc(sizeof(int)*smartlist_len(dir->routers));
- for (i = 0; i < smartlist_len(dir->routers); ++i) {/* iterate over routers */
- router = smartlist_get(dir->routers, i);
- if (router_is_me(router)) {
+ the_nodes = nodelist_get_list();
+ n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes));
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ const int i = node_sl_idx;
+ if (router_digest_is_me(node->identity)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s -- it's me.", router->nickname);
/* XXX there's probably a reverse predecessor attack here, but
@@ -2566,13 +2564,15 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*/
continue;
}
- if (!router->is_running || router->is_bad_exit) {
+ if (!node->ri && !(node->rs && node->md))
+ continue;
+ if (!node->is_running || node->is_bad_exit) {
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
- if (router_is_unreliable(router, need_uptime, need_capacity, 0) &&
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0) &&
(!options->ExitNodes ||
- !routerset_contains_router(options->ExitNodes, router))) {
+ !routerset_contains_node(options->ExitNodes, node))) {
/* FFFF Someday, differentiate between a routerset that names
* routers, and a routerset that names countries, and only do this
* check if they've asked for specific exit relays. Or if the country
@@ -2581,18 +2581,19 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
continue; /* skip routers that are not suitable, unless we have
* ExitNodes set, in which case we asked for it */
}
- if (!(router->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
+ if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
/* if it's invalid and we don't want it */
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.",
// router->nickname, i);
continue; /* skip invalid routers */
}
- if (options->ExcludeSingleHopRelays && router->allow_single_hop_exits) {
+ if (options->ExcludeSingleHopRelays &&
+ node_allows_single_hop_exits(node)) {
n_supported[i] = -1;
continue;
}
- if (router_exit_policy_rejects_all(router)) {
+ if (node_exit_policy_rejects_all(node)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
// router->nickname, i);
@@ -2603,7 +2604,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) {
if (!ap_stream_wants_exit_attention(conn))
continue; /* Skip everything but APs in CIRCUIT_WAIT */
- if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router, 1)) {
+ if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), node, 1)) {
++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]);
@@ -2628,7 +2629,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* count of equally good routers.*/
++n_best_support;
}
- }
+ } SMARTLIST_FOREACH_END(node);
log_info(LD_CIRC,
"Found %d servers that might support %d/%d pending connections.",
n_best_support, best_support >= 0 ? best_support : 0,
@@ -2639,18 +2640,19 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
if (best_support > 0) {
smartlist_t *supporting = smartlist_create(), *use = smartlist_create();
- for (i = 0; i < smartlist_len(dir->routers); i++)
- if (n_supported[i] == best_support)
- smartlist_add(supporting, smartlist_get(dir->routers, i));
+ SMARTLIST_FOREACH(the_nodes, const node_t *, node, {
+ if (n_supported[node_sl_idx] == best_support)
+ smartlist_add(supporting, (void*)node);
+ });
- routersets_get_disjunction(use, supporting, options->ExitNodes,
+ routersets_get_node_disjunction(use, supporting, options->ExitNodes,
options->_ExcludeExitNodesUnion, 1);
if (smartlist_len(use) == 0 && options->ExitNodes &&
!options->StrictNodes) { /* give up on exitnodes and try again */
- routersets_get_disjunction(use, supporting, NULL,
+ routersets_get_node_disjunction(use, supporting, NULL,
options->_ExcludeExitNodesUnion, 1);
}
- router = routerlist_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
+ node = node_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
smartlist_free(use);
smartlist_free(supporting);
} else {
@@ -2669,7 +2671,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
need_capacity?", fast":"",
need_uptime?", stable":"");
tor_free(n_supported);
- return choose_good_exit_server_general(dir, 0, 0);
+ return choose_good_exit_server_general(0, 0);
}
log_notice(LD_CIRC, "All routers are down or won't exit%s -- "
"choosing a doomed exit at random.",
@@ -2681,28 +2683,27 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
for (attempt = 0; attempt < 2; attempt++) {
/* try once to pick only from routers that satisfy a needed port,
* then if there are none, pick from any that support exiting. */
- for (i = 0; i < smartlist_len(dir->routers); i++) {
- router = smartlist_get(dir->routers, i);
- if (n_supported[i] != -1 &&
- (attempt || router_handles_some_port(router, needed_ports))) {
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ if (n_supported[node_sl_idx] != -1 &&
+ (attempt || node_handles_some_port(node, needed_ports))) {
// log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.",
// try, router->nickname);
- smartlist_add(supporting, (void*)router);
+ smartlist_add(supporting, (void*)node);
}
- }
+ } SMARTLIST_FOREACH_END(node);
- routersets_get_disjunction(use, supporting, options->ExitNodes,
+ routersets_get_node_disjunction(use, supporting, options->ExitNodes,
options->_ExcludeExitNodesUnion, 1);
if (smartlist_len(use) == 0 && options->ExitNodes &&
!options->StrictNodes) { /* give up on exitnodes and try again */
- routersets_get_disjunction(use, supporting, NULL,
+ routersets_get_node_disjunction(use, supporting, NULL,
options->_ExcludeExitNodesUnion, 1);
}
/* FFF sometimes the above results in null, when the requested
* exit node is considered down by the consensus. we should pick
* it anyway, since the user asked for it. */
- router = routerlist_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
- if (router)
+ node = node_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
+ if (node)
break;
smartlist_clear(supporting);
smartlist_clear(use);
@@ -2714,9 +2715,9 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
tor_free(n_supported);
- if (router) {
- log_info(LD_CIRC, "Chose exit server '%s'", router->nickname);
- return router;
+ if (node) {
+ log_info(LD_CIRC, "Chose exit server '%s'", node_get_nickname(node));
+ return node;
}
if (options->ExitNodes && options->StrictNodes) {
log_warn(LD_CIRC,
@@ -2736,12 +2737,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* For client-side rendezvous circuits, choose a random node, weighted
* toward the preferences in 'options'.
*/
-static const routerinfo_t *
-choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
+static const node_t *
+choose_good_exit_server(uint8_t purpose,
int need_uptime, int need_capacity, int is_internal)
{
or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ router_crn_flags_t flags = CRN_NEED_DESC;
if (need_uptime)
flags |= CRN_NEED_UPTIME;
if (need_capacity)
@@ -2754,7 +2755,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
if (is_internal) /* pick it like a middle hop */
return router_choose_random_node(NULL, options->ExcludeNodes, flags);
else
- return choose_good_exit_server_general(dir,need_uptime,need_capacity);
+ return choose_good_exit_server_general(need_uptime,need_capacity);
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS)
flags |= CRN_ALLOW_INVALID;
@@ -2835,13 +2836,12 @@ static int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
{
cpath_build_state_t *state = circ->build_state;
- routerlist_t *rl = router_get_routerlist();
if (state->onehop_tunnel) {
log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel.");
state->desired_path_len = 1;
} else {
- int r = new_route_len(circ->_base.purpose, exit, rl->routers);
+ int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list());
if (r < 1) /* must be at least 1 */
return -1;
state->desired_path_len = r;
@@ -2852,14 +2852,14 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
log_info(LD_CIRC,"Using requested exit node '%s'", exit->nickname);
exit = extend_info_dup(exit);
} else { /* we have to decide one */
- const routerinfo_t *router =
- choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
+ const node_t *node =
+ choose_good_exit_server(circ->_base.purpose, state->need_uptime,
state->need_capacity, state->is_internal);
- if (!router) {
+ if (!node) {
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
}
- exit = extend_info_from_router(router);
+ exit = extend_info_from_node(node);
}
state->chosen_exit = exit;
return 0;
@@ -2910,35 +2910,30 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit)
* and available for building circuits through.
*/
static int
-count_acceptable_routers(smartlist_t *routers)
+count_acceptable_nodes(smartlist_t *nodes)
{
- int i, n;
int num=0;
- routerinfo_t *r;
- n = smartlist_len(routers);
- for (i=0;i<n;i++) {
- r = smartlist_get(routers, i);
-// log_debug(LD_CIRC,
+ SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
+ // log_debug(LD_CIRC,
// "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname);
- if (r->is_running == 0) {
+ if (! node->is_running)
// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
- goto next_i_loop;
- }
- if (r->is_valid == 0) {
+ continue;
+ if (! node->is_valid)
// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
- goto next_i_loop;
+ continue;
+ if (! node_has_descriptor(node))
+ continue;
/* XXX This clause makes us count incorrectly: if AllowInvalidRouters
* allows this node in some places, then we're getting an inaccurate
* count. For now, be conservative and don't count it. But later we
* should try to be smarter. */
- }
- num++;
+ ++num;
+ } SMARTLIST_FOREACH_END(node);
+
// log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num);
- next_i_loop:
- ; /* C requires an explicit statement after the label */
- }
return num;
}
@@ -2966,31 +2961,31 @@ onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
* circuit. In particular, make sure we don't pick the exit node or its
* family, and make sure we don't duplicate any previous nodes or their
* families. */
-static const routerinfo_t *
+static const node_t *
choose_good_middle_server(uint8_t purpose,
cpath_build_state_t *state,
crypt_path_t *head,
int cur_len)
{
int i;
- const routerinfo_t *r, *choice;
+ const node_t *r, *choice;
crypt_path_t *cpath;
smartlist_t *excluded;
or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ router_crn_flags_t flags = CRN_NEED_DESC;
tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose &&
purpose <= _CIRCUIT_PURPOSE_MAX);
log_debug(LD_CIRC, "Contemplating intermediate hop: random choice.");
excluded = smartlist_create();
- if ((r = build_state_get_exit_router(state))) {
+ if ((r = build_state_get_exit_node(state))) {
smartlist_add(excluded, (void*) r);
- routerlist_add_family(excluded, r);
+ nodelist_add_node_family(excluded, r);
}
for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) {
- if ((r = router_get_by_digest(cpath->extend_info->identity_digest))) {
+ if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
smartlist_add(excluded, (void*)r);
- routerlist_add_family(excluded, r);
+ nodelist_add_node_family(excluded, r);
}
}
@@ -3013,13 +3008,14 @@ choose_good_middle_server(uint8_t purpose,
* If <b>state</b> is NULL, we're choosing a router to serve as an entry
* guard, not for any particular circuit.
*/
-static const routerinfo_t *
+static const node_t *
choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
{
- const routerinfo_t *r, *choice;
+ const node_t *choice;
smartlist_t *excluded;
or_options_t *options = get_options();
- router_crn_flags_t flags = CRN_NEED_GUARD;
+ router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC;
+ const node_t *node;
if (state && options->UseEntryGuards &&
(purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) {
@@ -3028,29 +3024,26 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
excluded = smartlist_create();
- if (state && (r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, (void*)r);
- routerlist_add_family(excluded, r);
+ if (state && (node = build_state_get_exit_node(state))) {
+ smartlist_add(excluded, (void*)node);
+ nodelist_add_node_family(excluded, node);
}
if (firewall_is_fascist_or()) {
/*XXXX This could slow things down a lot; use a smarter implementation */
/* exclude all ORs that listen on the wrong port, if anybody notices. */
- routerlist_t *rl = router_get_routerlist();
- int i;
-
- for (i=0; i < smartlist_len(rl->routers); i++) {
- r = smartlist_get(rl->routers, i);
- if (!fascist_firewall_allows_or(r))
- smartlist_add(excluded, (void*)r);
- }
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *,node, {
+ if (!fascist_firewall_allows_node(node))
+ smartlist_add(excluded, (void*)node);
+ });
}
/* and exclude current entry guards, if applicable */
if (options->UseEntryGuards && entry_guards) {
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
{
- if ((r = router_get_by_digest(entry->identity))) {
- smartlist_add(excluded, (void*)r);
- routerlist_add_family(excluded, r);
+ if ((node = node_get_by_id(entry->identity))) {
+ smartlist_add(excluded, (void*)node);
+ nodelist_add_node_family(excluded, node);
}
});
}
@@ -3106,14 +3099,14 @@ onion_extend_cpath(origin_circuit_t *circ)
if (cur_len == state->desired_path_len - 1) { /* Picking last node */
info = extend_info_dup(state->chosen_exit);
} else if (cur_len == 0) { /* picking first node */
- const routerinfo_t *r = choose_good_entry_server(purpose, state);
+ const node_t *r = choose_good_entry_server(purpose, state);
if (r)
- info = extend_info_from_router(r);
+ info = extend_info_from_node(r);
} else {
- const routerinfo_t *r =
+ const node_t *r =
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
if (r)
- info = extend_info_from_router(r);
+ info = extend_info_from_node(r);
}
if (!info) {
@@ -3181,6 +3174,29 @@ extend_info_from_router(const routerinfo_t *r)
r->onion_pkey, &addr, r->or_port);
}
+/** Allocate and return a new extend_info that can be used to build a ircuit
+ * to or through the node <b>node</b>. May return NULL if there is not
+ * enough info about <b>node</b> to extend to it--for example, if there
+ * is no routerinfo_t or microdesc_t.
+ **/
+extend_info_t *
+extend_info_from_node(const node_t *node)
+{
+ if (node->ri) {
+ return extend_info_from_router(node->ri);
+ } else if (node->rs && node->md) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return extend_info_alloc(node->rs->nickname,
+ node->identity,
+ node->md->onion_pkey,
+ &addr,
+ node->rs->or_port);
+ } else {
+ return NULL;
+ }
+}
+
/** Release storage held by an extend_info_t struct. */
void
extend_info_free(extend_info_t *info)
@@ -3211,12 +3227,12 @@ extend_info_dup(extend_info_t *info)
* If there is no chosen exit, or if we don't know the routerinfo_t for
* the chosen exit, return NULL.
*/
-const routerinfo_t *
-build_state_get_exit_router(cpath_build_state_t *state)
+const node_t *
+build_state_get_exit_node(cpath_build_state_t *state)
{
if (!state || !state->chosen_exit)
return NULL;
- return router_get_by_digest(state->chosen_exit->identity_digest);
+ return node_get_by_id(state->chosen_exit->identity_digest);
}
/** Return the nickname for the chosen exit router in <b>state</b>. If
@@ -3238,9 +3254,8 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
*
* If it's not usable, set *<b>reason</b> to a static string explaining why.
*/
-/*XXXX take a routerstatus, not a routerinfo. */
static int
-entry_guard_set_status(entry_guard_t *e, const routerinfo_t *ri,
+entry_guard_set_status(entry_guard_t *e, const node_t *node,
time_t now, or_options_t *options, const char **reason)
{
char buf[HEX_DIGEST_LEN+1];
@@ -3249,16 +3264,17 @@ entry_guard_set_status(entry_guard_t *e, const routerinfo_t *ri,
*reason = NULL;
/* Do we want to mark this guard as bad? */
- if (!ri)
+ if (!node)
*reason = "unlisted";
- else if (!ri->is_running)
+ else if (!node->is_running)
*reason = "down";
- else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE)
+ else if (options->UseBridges && (!node->ri ||
+ node->ri->purpose != ROUTER_PURPOSE_BRIDGE))
*reason = "not a bridge";
- else if (!options->UseBridges && !ri->is_possible_guard &&
- !routerset_contains_router(options->EntryNodes,ri))
+ else if (!options->UseBridges && !node->is_possible_guard &&
+ !routerset_contains_node(options->EntryNodes,node))
*reason = "not recommended as a guard";
- else if (routerset_contains_router(options->ExcludeNodes, ri))
+ else if (routerset_contains_node(options->ExcludeNodes, node))
*reason = "excluded";
if (*reason && ! e->bad_since) {
@@ -3302,7 +3318,7 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
return now > (e->last_attempted + 36*60*60);
}
-/** Return the router corresponding to <b>e</b>, if <b>e</b> is
+/** Return the node corresponding to <b>e</b>, if <b>e</b> is
* working well enough that we are willing to use it as an entry
* right now. (Else return NULL.) In particular, it must be
* - Listed as either up or never yet contacted;
@@ -3316,11 +3332,11 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
*
* If the answer is no, set *<b>msg</b> to an explanation of why.
*/
-static INLINE const routerinfo_t *
+static INLINE const node_t *
entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
int assume_reachable, const char **msg)
{
- const routerinfo_t *r;
+ const node_t *node;
or_options_t *options = get_options();
tor_assert(msg);
@@ -3334,33 +3350,36 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
*msg = "unreachable";
return NULL;
}
- r = router_get_by_digest(e->identity);
- if (!r) {
+ node = node_get_by_id(e->identity);
+ if (!node && !node_has_descriptor(node)) {
*msg = "no descriptor";
return NULL;
}
- if (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) {
- *msg = "not a bridge";
- return NULL;
- }
- if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) {
- *msg = "not general-purpose";
- return NULL;
+ if (get_options()->UseBridges) {
+ if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) {
+ *msg = "not a bridge";
+ return NULL;
+ }
+ } else { /* !get_options()->UseBridges */
+ if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) {
+ *msg = "not general-purpose";
+ return NULL;
+ }
}
if (options->EntryNodes &&
- routerset_contains_router(options->EntryNodes, r)) {
+ routerset_contains_node(options->EntryNodes, node)) {
/* they asked for it, they get it */
need_uptime = need_capacity = 0;
}
- if (router_is_unreliable(r, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
*msg = "not fast/stable";
return NULL;
}
- if (!fascist_firewall_allows_or(r)) {
+ if (!fascist_firewall_allows_node(node)) {
*msg = "unreachable by config";
return NULL;
}
- return r;
+ return node;
}
/** Return the number of entry guards that we think are usable. */
@@ -3458,15 +3477,15 @@ control_event_guard_deferred(void)
* If <b>chosen</b> is defined, use that one, and if it's not
* already in our entry_guards list, put it at the *beginning*.
* Else, put the one we pick at the end of the list. */
-static const routerinfo_t *
-add_an_entry_guard(routerinfo_t *chosen, int reset_status)
+static const node_t *
+add_an_entry_guard(const node_t *chosen, int reset_status)
{
- const routerinfo_t *router;
+ const node_t *node;
entry_guard_t *entry;
if (chosen) {
- router = chosen;
- entry = is_an_entry_guard(router->cache_info.identity_digest);
+ node = chosen;
+ entry = is_an_entry_guard(node->identity);
if (entry) {
if (reset_status) {
entry->bad_since = 0;
@@ -3475,14 +3494,15 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
return NULL;
}
} else {
- router = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
- if (!router)
+ node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
+ if (!node)
return NULL;
}
entry = tor_malloc_zero(sizeof(entry_guard_t));
- log_info(LD_CIRC, "Chose '%s' as new entry guard.", router->nickname);
- strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname));
- memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN);
+ log_info(LD_CIRC, "Chose '%s' as new entry guard.",
+ node_get_nickname(node));
+ strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname));
+ memcpy(entry->identity, node->identity, DIGEST_LEN);
/* Choose expiry time smudged over the past month. The goal here
* is to a) spread out when Tor clients rotate their guards, so they
* don't all select them on the same day, and b) avoid leaving a
@@ -3497,7 +3517,7 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
log_entry_guards(LOG_INFO);
- return router;
+ return node;
}
/** If the use of entry guards is configured, choose more entry guards
@@ -3651,7 +3671,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
reasons = digestmap_new();
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry)
{
- const routerinfo_t *r = router_get_by_digest(entry->identity);
+ const node_t *r = node_get_by_id(entry->identity);
const char *reason = NULL;
if (entry_guard_set_status(entry, r, now, options, &reason))
changed = 1;
@@ -3672,7 +3692,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *reason = digestmap_get(reasons, entry->identity);
const char *live_msg = "";
- const routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
+ const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s%s%s, and %s%s.",
entry->nickname,
entry->unreachable_since ? "unreachable" : "reachable",
@@ -3789,7 +3809,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
break;
if (e->made_contact) {
const char *msg;
- const routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg);
+ const node_t *r = entry_is_live(e, 0, 1, 1, &msg);
if (r && e->unreachable_since) {
refuse_conn = 1;
e->can_retry = 1;
@@ -3830,7 +3850,7 @@ entry_nodes_should_be_added(void)
static void
entry_guards_prepend_from_config(or_options_t *options)
{
- smartlist_t *entry_routers, *entry_fps;
+ smartlist_t *entry_nodes, *entry_fps;
smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
tor_assert(entry_guards);
@@ -3850,7 +3870,7 @@ entry_guards_prepend_from_config(or_options_t *options)
tor_free(string);
}
- entry_routers = smartlist_create();
+ entry_nodes = smartlist_create();
entry_fps = smartlist_create();
old_entry_guards_on_list = smartlist_create();
old_entry_guards_not_on_list = smartlist_create();
@@ -3863,9 +3883,9 @@ entry_guards_prepend_from_config(or_options_t *options)
* Perhaps we should do this calculation once whenever the list of routers
* changes or the entrynodes setting changes.
*/
- routerset_get_all_routers(entry_routers, options->EntryNodes, 0);
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri,
- smartlist_add(entry_fps,ri->cache_info.identity_digest));
+ routerset_get_all_nodes(entry_nodes, options->EntryNodes, 0);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
+ smartlist_add(entry_fps, (void*)node->identity));
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, {
if (smartlist_digest_isin(entry_fps, e->identity))
smartlist_add(old_entry_guards_on_list, e);
@@ -3874,9 +3894,9 @@ entry_guards_prepend_from_config(or_options_t *options)
});
/* Remove all currently configured entry guards from entry_routers. */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- if (is_an_entry_guard(ri->cache_info.identity_digest)) {
- SMARTLIST_DEL_CURRENT(entry_routers, ri);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
+ if (is_an_entry_guard(node->identity)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
}
});
@@ -3885,8 +3905,8 @@ entry_guards_prepend_from_config(or_options_t *options)
/* First, the previously configured guards that are in EntryNodes. */
smartlist_add_all(entry_guards, old_entry_guards_on_list);
/* Next, the rest of EntryNodes */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- add_an_entry_guard(ri, 0);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
+ add_an_entry_guard(node, 0);
});
/* Finally, the remaining previously configured guards that are not in
* EntryNodes, unless we're strict in which case we drop them */
@@ -3897,7 +3917,7 @@ entry_guards_prepend_from_config(or_options_t *options)
smartlist_add_all(entry_guards, old_entry_guards_not_on_list);
}
- smartlist_free(entry_routers);
+ smartlist_free(entry_nodes);
smartlist_free(entry_fps);
smartlist_free(old_entry_guards_on_list);
smartlist_free(old_entry_guards_not_on_list);
@@ -3935,22 +3955,22 @@ entry_list_is_totally_static(or_options_t *options)
* make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random
* guard (likely a bridge). */
-const routerinfo_t *
+const node_t *
choose_random_entry(cpath_build_state_t *state)
{
or_options_t *options = get_options();
smartlist_t *live_entry_guards = smartlist_create();
smartlist_t *exit_family = smartlist_create();
- const routerinfo_t *chosen_exit =
- state?build_state_get_exit_router(state) : NULL;
- const routerinfo_t *r = NULL;
+ const node_t *chosen_exit =
+ state?build_state_get_exit_node(state) : NULL;
+ const node_t *node = NULL;
int need_uptime = state ? state->need_uptime : 0;
int need_capacity = state ? state->need_capacity : 0;
int preferred_min, consider_exit_family = 0;
if (chosen_exit) {
smartlist_add(exit_family, (void*) chosen_exit);
- routerlist_add_family(exit_family, chosen_exit);
+ nodelist_add_node_family(exit_family, chosen_exit);
consider_exit_family = 1;
}
@@ -3968,13 +3988,13 @@ choose_random_entry(cpath_build_state_t *state)
smartlist_clear(live_entry_guards);
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *msg;
- r = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
- if (!r)
+ node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
+ if (!node)
continue; /* down, no point */
- if (consider_exit_family && smartlist_isin(exit_family, r))
+ if (consider_exit_family && smartlist_isin(exit_family, node))
continue; /* avoid relays that are family members of our exit */
if (options->EntryNodes &&
- !routerset_contains_router(options->EntryNodes, r)) {
+ !routerset_contains_node(options->EntryNodes, node)) {
/* We've come to the end of our preferred entry nodes. */
if (smartlist_len(live_entry_guards))
goto choose_and_finish; /* only choose from the ones we like */
@@ -3987,7 +4007,7 @@ choose_random_entry(cpath_build_state_t *state)
"No relays from EntryNodes available. Using others.");
}
}
- smartlist_add(live_entry_guards, (void*)r);
+ smartlist_add(live_entry_guards, (void*)node);
if (!entry->made_contact) {
/* Always start with the first not-yet-contacted entry
* guard. Otherwise we might add several new ones, pick
@@ -4017,8 +4037,8 @@ choose_random_entry(cpath_build_state_t *state)
/* XXX if guard doesn't imply fast and stable, then we need
* to tell add_an_entry_guard below what we want, or it might
* be a long time til we get it. -RD */
- r = add_an_entry_guard(NULL, 0);
- if (r) {
+ node = add_an_entry_guard(NULL, 0);
+ if (node) {
entry_guards_changed();
/* XXX we start over here in case the new node we added shares
* a family with our exit node. There's a chance that we'll just
@@ -4028,16 +4048,16 @@ choose_random_entry(cpath_build_state_t *state)
goto retry;
}
}
- if (!r && need_uptime) {
+ if (!node && need_uptime) {
need_uptime = 0; /* try without that requirement */
goto retry;
}
- if (!r && need_capacity) {
+ if (!node && need_capacity) {
/* still no? last attempt, try without requiring capacity */
need_capacity = 0;
goto retry;
}
- if (!r && entry_list_is_constrained(options) && consider_exit_family) {
+ if (!node && entry_list_is_constrained(options) && consider_exit_family) {
/* still no? if we're using bridges or have strictentrynodes
* set, and our chosen exit is in the same family as all our
* bridges/entry guards, then be flexible about families. */
@@ -4051,16 +4071,16 @@ choose_random_entry(cpath_build_state_t *state)
if (entry_list_is_constrained(options)) {
/* We need to weight by bandwidth, because our bridges or entryguards
* were not already selected proportional to their bandwidth. */
- r = routerlist_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
+ node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
} else {
/* We choose uniformly at random here, because choose_good_entry_server()
* already weights its choices by bandwidth, so we don't want to
* *double*-weight our guard selection. */
- r = smartlist_choose(live_entry_guards);
+ node = smartlist_choose(live_entry_guards);
}
smartlist_free(live_entry_guards);
smartlist_free(exit_family);
- return r;
+ return node;
}
/** Parse <b>state</b> and learn about the entry guards it describes.
@@ -4307,7 +4327,7 @@ getinfo_helper_entry_guards(control_connection_t *conn,
char *c = tor_malloc(len);
const char *status = NULL;
time_t when = 0;
- const routerinfo_t *ri;
+ const node_t *node;
if (!e->made_contact) {
status = "never-connected";
@@ -4318,9 +4338,9 @@ getinfo_helper_entry_guards(control_connection_t *conn,
status = "up";
}
- ri = router_get_by_digest(e->identity);
- if (ri) {
- router_get_verbose_nickname(nbuf, ri);
+ node = node_get_by_id(e->identity);
+ if (node) {
+ node_get_verbose_nickname(node, nbuf);
} else {
nbuf[0] = '$';
base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN);
@@ -4566,14 +4586,17 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
int first = !any_bridge_descriptors_known();
bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
time_t now = time(NULL);
- ri->is_running = 1;
+ router_set_status(ri->cache_info.identity_digest, 1);
if (bridge) { /* if we actually want to use this one */
+ const node_t *node;
/* it's here; schedule its re-fetch for a long time from now. */
if (!from_cache)
download_status_reset(&bridge->fetch_status);
- add_an_entry_guard(ri, 1);
+ node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
+ add_an_entry_guard(node, 1);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
from_cache ? "cached" : "fresh");
/* set entry->made_contact so if it goes down we don't drop it from
@@ -4627,18 +4650,18 @@ any_pending_bridge_descriptor_fetches(void)
static int
entries_retry_helper(or_options_t *options, int act)
{
- routerinfo_t *ri;
+ const node_t *node;
int any_known = 0;
int any_running = 0;
- int purpose = options->UseBridges ?
- ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
+ int need_bridges = options->UseBridges != 0;
if (!entry_guards)
entry_guards = smartlist_create();
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
- ri = router_get_mutable_by_digest(e->identity);
- if (ri && ri->purpose == purpose) {
+ node = node_get_by_id(e->identity);
+ if (node && node_has_descriptor(node) &&
+ node_is_bridge(node) == need_bridges) {
any_known = 1;
- if (ri->is_running)
+ if (node->is_running)
any_running = 1; /* some entry is both known and running */
else if (act) {
/* Mark all current connections to this OR as unhealthy, since
@@ -4647,10 +4670,10 @@ entries_retry_helper(or_options_t *options, int act)
* the node down and undermine the retry attempt. We mark even
* the established conns, since if the network just came back
* we'll want to attach circuits to fresh conns. */
- connection_or_set_bad_connections(ri->cache_info.identity_digest, 1);
+ connection_or_set_bad_connections(node->identity, 1);
/* mark this entry node for retry */
- router_set_status(ri->cache_info.identity_digest, 1);
+ router_set_status(node->identity, 1);
e->can_retry = 1;
e->bad_since = 0;
}
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 59e818d5f..7c125e96b 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -45,9 +45,10 @@ extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
crypto_pk_env_t *onion_key,
const tor_addr_t *addr, uint16_t port);
extend_info_t *extend_info_from_router(const routerinfo_t *r);
+extend_info_t *extend_info_from_node(const node_t *node);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
-const routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
+const node_t *build_state_get_exit_node(cpath_build_state_t *state);
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
void entry_guards_compute_status(or_options_t *options, time_t now);
@@ -55,7 +56,7 @@ int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);
void entry_nodes_should_be_added(void);
int entry_list_is_constrained(or_options_t *options);
-const routerinfo_t *choose_random_entry(cpath_build_state_t *state);
+const node_t *choose_random_entry(cpath_build_state_t *state);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 96a06c05f..da6d32961 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -19,6 +19,7 @@
#include "connection_or.h"
#include "control.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "rendclient.h"
@@ -946,15 +947,15 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
if (info) {
/* need to make sure we don't duplicate hops */
crypt_path_t *hop = circ->cpath;
- const routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
+ const node_t *ri1 = node_get_by_id(info->identity_digest);
do {
- const routerinfo_t *ri2;
+ const node_t *ri2;
if (!memcmp(hop->extend_info->identity_digest,
info->identity_digest, DIGEST_LEN))
goto next;
if (ri1 &&
- (ri2 = router_get_by_digest(hop->extend_info->identity_digest))
- && routers_in_same_family(ri1, ri2))
+ (ri2 = node_get_by_id(hop->extend_info->identity_digest))
+ && nodes_in_same_family(ri1, ri2))
goto next;
hop=hop->next;
} while (hop!=circ->cpath);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index a2a09bedf..ca156d43c 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -17,6 +17,7 @@
#include "connection.h"
#include "connection_edge.h"
#include "control.h"
+#include "nodelist.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -43,7 +44,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
int need_uptime, int need_internal,
time_t now)
{
- const routerinfo_t *exitrouter;
+ const node_t *exitnode;
cpath_build_state_t *build_state;
tor_assert(circ);
tor_assert(conn);
@@ -85,7 +86,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
* of the one we meant to finish at.
*/
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- exitrouter = build_state_get_exit_router(build_state);
+ exitnode = build_state_get_exit_node(build_state);
if (need_uptime && !build_state->need_uptime)
return 0;
@@ -93,7 +94,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
- if (!exitrouter && !build_state->onehop_tunnel) {
+ if (!exitnode && !build_state->onehop_tunnel) {
log_debug(LD_CIRC,"Not considering circuit with unknown router.");
return 0; /* this circuit is screwed and doesn't know it yet,
* or is a rendezvous circuit. */
@@ -127,7 +128,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
}
}
- if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter, 0)) {
+ if (exitnode && !connection_ap_can_use_exit(conn, exitnode, 0)) {
/* can't exit from this router */
return 0;
}
@@ -473,7 +474,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
uint16_t port, int min)
{
circuit_t *circ;
- const routerinfo_t *exitrouter;
+ const node_t *exitnode;
int num=0;
time_t now = time(NULL);
int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
@@ -489,14 +490,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
if (build_state->is_internal || build_state->onehop_tunnel)
continue;
- exitrouter = build_state_get_exit_router(build_state);
- if (exitrouter && (!need_uptime || build_state->need_uptime)) {
+ exitnode = build_state_get_exit_node(build_state);
+ if (exitnode && (!need_uptime || build_state->need_uptime)) {
int ok;
if (conn) {
- ok = connection_ap_can_use_exit(conn, exitrouter, 0);
+ ok = connection_ap_can_use_exit(conn, exitnode, 0);
} else {
- addr_policy_result_t r = compare_addr_to_addr_policy(
- 0, port, exitrouter->exit_policy);
+ addr_policy_result_t r;
+ r = compare_addr_to_node_policy(0, port, exitnode);
ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
}
if (ok) {
@@ -563,7 +564,7 @@ circuit_predict_and_launch_new(void)
log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another exit circ.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -575,7 +576,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d internal), need another internal "
"circ for my hidden service.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -593,7 +594,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d uptime-internal, %d internal), need"
" another hidden service circ.",
num, num_uptime_internal, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -606,7 +607,7 @@ circuit_predict_and_launch_new(void)
flags = CIRCLAUNCH_NEED_CAPACITY;
log_info(LD_CIRC,
"Have %d clean circs need another buildtime test circ.", num);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
}
@@ -644,7 +645,7 @@ circuit_build_needed_circs(time_t now)
circ &&
circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
log_fn(LOG_INFO,"Creating a new testing circuit.");
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0);
}
#endif
}
@@ -1076,17 +1077,9 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
origin_circuit_t *
-circuit_launch_by_router(uint8_t purpose,
- const routerinfo_t *exit, int flags)
+circuit_launch(uint8_t purpose, int flags)
{
- origin_circuit_t *circ;
- extend_info_t *info = NULL;
- if (exit)
- info = extend_info_from_router(exit);
- circ = circuit_launch_by_extend_info(purpose, info, flags);
-
- extend_info_free(info);
- return circ;
+ return circuit_launch_by_extend_info(purpose, NULL, flags);
}
/** Launch a new circuit with purpose <b>purpose</b> and exit node
@@ -1256,9 +1249,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
uint32_t addr = 0;
if (tor_inet_aton(conn->socks_request->address, &in))
addr = ntohl(in.s_addr);
- if (router_exit_policy_all_routers_reject(addr,
- conn->socks_request->port,
- need_uptime)) {
+ if (router_exit_policy_all_nodes_reject(addr,
+ conn->socks_request->port,
+ need_uptime)) {
log_notice(LD_APP,
"No Tor server allows exit to %s:%d. Rejecting.",
safe_str_client(conn->socks_request->address),
@@ -1267,10 +1260,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
}
} else {
/* XXXX022 Duplicates checks in connection_ap_handshake_attach_circuit */
- const routerinfo_t *router =
- router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (router && !connection_ap_can_use_exit(conn, router, 0)) {
+ if (node && !connection_ap_can_use_exit(conn, node, 0)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' would refuse request. %s.",
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
@@ -1318,11 +1310,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
*/
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
- const routerinfo_t *r;
+ const node_t *r;
int opt = conn->chosen_exit_optional;
- r = router_get_by_nickname(conn->chosen_exit_name, 1);
+ r = node_get_by_nickname(conn->chosen_exit_name, 1);
if (r) {
- extend_info = extend_info_from_router(r);
+ extend_info = extend_info_from_node(r);
} else {
log_debug(LD_DIR, "considering %d, %s",
want_onehop, conn->chosen_exit_name);
@@ -1572,9 +1564,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
origin_circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
- const routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (!router && !want_onehop) {
+ if (!node && !want_onehop) {
/* We ran into this warning when trying to extend a circuit to a
* hidden service directory for which we didn't have a router
* descriptor. See flyspray task 767 for more details. We should
@@ -1590,7 +1582,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
}
return -1;
}
- if (router && !connection_ap_can_use_exit(conn, router, 0)) {
+ if (node && !connection_ap_can_use_exit(conn, node, 0)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' would refuse request. %s.",
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index 617685e61..4e4cd1a4d 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -41,8 +41,7 @@ void circuit_build_failed(origin_circuit_t *circ);
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
-origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
- const routerinfo_t *exit, int flags);
+origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
void circuit_reset_failure_count(int timeout);
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
origin_circuit_t *circ,
diff --git a/src/or/command.c b/src/or/command.c
index 6296c471e..46713a513 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -25,6 +25,7 @@
#include "control.h"
#include "cpuworker.h"
#include "hibernate.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "router.h"
@@ -267,15 +268,15 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
}
if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
- const routerinfo_t *router = router_get_by_digest(conn->identity_digest);
+ const node_t *node = node_get_by_id(conn->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).",
cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
- if (router)
+ if (node)
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Details: nickname \"%s\", platform %s.",
- router->nickname, escaped(router->platform));
+ node_get_nickname(node), escaped(node_get_platform(node)));
return;
}
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 2b9ccc596..4ab636a93 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -23,6 +23,7 @@
#include "dirserv.h"
#include "hibernate.h"
#include "main.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -587,7 +588,7 @@ void
circuit_discard_optional_exit_enclaves(extend_info_t *info)
{
edge_connection_t *edge_conn;
- const routerinfo_t *r1, *r2;
+ const node_t *r1, *r2;
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -599,8 +600,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
if (!edge_conn->chosen_exit_optional &&
!edge_conn->chosen_exit_retries)
continue;
- r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
- r2 = router_get_by_nickname(info->nickname, 0);
+ r1 = node_get_by_nickname(edge_conn->chosen_exit_name, 0);
+ r2 = node_get_by_nickname(info->nickname, 0);
if (!r1 || !r2 || r1 != r2)
continue;
tor_assert(edge_conn->socks_request);
@@ -1575,12 +1576,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
} else {
- const routerinfo_t *r;
+ const node_t *r;
conn->chosen_exit_name = tor_strdup(socks->address);
- r = router_get_by_nickname(conn->chosen_exit_name, 1);
+ r = node_get_by_nickname(conn->chosen_exit_name, 1);
*socks->address = 0;
if (r) {
- strlcpy(socks->address, r->address, sizeof(socks->address));
+ node_get_address_string(r, socks->address, sizeof(socks->address));
} else {
log_warn(LD_APP,
"Unrecognized server in exit address '%s.exit'. Refusing.",
@@ -1631,16 +1632,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */
- const routerinfo_t *r =
+ const node_t *r =
router_find_exact_exit_enclave(socks->address, socks->port);
if (r) {
log_info(LD_APP,
"Redirecting address %s to exit at enclave router %s",
- safe_str_client(socks->address), r->nickname);
+ safe_str_client(socks->address), node_get_nickname(r));
/* use the hex digest, not nickname, in case there are two
routers with this nickname */
conn->chosen_exit_name =
- tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
+ tor_strdup(hex_str(r->identity, DIGEST_LEN));
conn->chosen_exit_optional = 1;
}
}
@@ -2896,7 +2897,7 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
* this relay, return 0.
*/
int
-connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
+connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit,
int excluded_means_no)
{
or_options_t *options = get_options();
@@ -2910,10 +2911,10 @@ connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
* make sure the exit node of the existing circuit matches exactly.
*/
if (conn->chosen_exit_name) {
- const routerinfo_t *chosen_exit =
- router_get_by_nickname(conn->chosen_exit_name, 1);
- if (!chosen_exit || memcmp(chosen_exit->cache_info.identity_digest,
- exit->cache_info.identity_digest, DIGEST_LEN)) {
+ const node_t *chosen_exit =
+ node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (!chosen_exit || memcmp(chosen_exit->identity,
+ exit->identity, DIGEST_LEN)) {
/* doesn't match */
// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
// conn->chosen_exit_name, exit->nickname);
@@ -2928,8 +2929,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
addr_policy_result_t r;
if (tor_inet_aton(conn->socks_request->address, &in))
addr = ntohl(in.s_addr);
- r = compare_addr_to_addr_policy(addr, conn->socks_request->port,
- exit->exit_policy);
+ r = compare_addr_to_node_policy(addr, conn->socks_request->port, exit);
if (r == ADDR_POLICY_REJECTED)
return 0; /* We know the address, and the exit policy rejects it. */
if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
@@ -2938,12 +2938,12 @@ connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
* this node, err on the side of caution. */
} else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
/* Don't send DNS requests to non-exit servers by default. */
- if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy))
+ if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit))
return 0;
}
if (options->_ExcludeExitNodesUnion &&
(options->StrictNodes || excluded_means_no) &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) {
+ routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) {
/* If we are trying to avoid this node as exit, and we have StrictNodes
* set, then this is not a suitable exit. Refuse it.
*
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 24ea327ec..f54d7a44e 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -48,7 +48,7 @@ int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
void connection_exit_connect(edge_connection_t *conn);
int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
int connection_ap_can_use_exit(edge_connection_t *conn,
- const routerinfo_t *exit,
+ const node_t *exit,
int excluded_means_no);
void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index ee17282e5..ce285cd3a 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -22,6 +22,7 @@
#include "geoip.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "reasons.h"
#include "relay.h"
#include "rephist.h"
@@ -438,7 +439,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
const char *id_digest,
int started_here)
{
- const routerinfo_t *r = router_get_by_digest(id_digest);
+ const node_t *r = node_get_by_id(id_digest);
connection_or_set_identity_digest(conn, id_digest);
connection_or_update_token_buckets_helper(conn, 1, get_options());
@@ -446,8 +447,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
tor_addr_copy(&conn->_base.addr, addr);
tor_addr_copy(&conn->real_addr, addr);
if (r) {
+ tor_addr_t node_addr;
+ node_get_addr(r, &node_addr);
/* XXXX proposal 118 will make this more complex. */
- if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr))
+ if (tor_addr_eq(&conn->_base.addr, &node_addr))
conn->is_canonical = 1;
if (!started_here) {
/* Override the addr/port, so our log messages will make sense.
@@ -460,12 +463,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
* right IP address and port 56244, that wouldn't be as helpful. now we
* log the "right" port too, so we know if it's moria1 or moria2.
*/
- tor_addr_from_ipv4h(&conn->_base.addr, r->addr);
- conn->_base.port = r->or_port;
+ tor_addr_copy(&conn->_base.addr, &node_addr);
+ conn->_base.port = node_get_orport(r);
}
- conn->nickname = tor_strdup(r->nickname);
+ conn->nickname = tor_strdup(node_get_nickname(r));
tor_free(conn->_base.address);
- conn->_base.address = tor_strdup(r->address);
+ conn->_base.address = tor_dup_addr(&node_addr);
} else {
const char *n;
/* If we're an authoritative directory server, we may know a
diff --git a/src/or/control.c b/src/or/control.c
index 7161fea2d..a46ce2c7f 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -26,6 +26,7 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "router.h"
@@ -2107,7 +2108,7 @@ static int
handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
const char *body)
{
- smartlist_t *router_nicknames=NULL, *routers=NULL;
+ smartlist_t *router_nicknames=NULL, *nodes=NULL;
origin_circuit_t *circ = NULL;
int zero_circ;
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
@@ -2138,8 +2139,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if ((smartlist_len(args) == 1) ||
(smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
// "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
- circ = circuit_launch_by_router(intended_purpose, NULL,
- CIRCLAUNCH_NEED_CAPACITY);
+ circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
if (!circ) {
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
} else {
@@ -2167,17 +2167,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
- routers = smartlist_create();
+ nodes = smartlist_create();
SMARTLIST_FOREACH(router_nicknames, const char *, n,
{
- const routerinfo_t *r = router_get_by_nickname(n, 1);
- if (!r) {
+ const node_t *node = node_get_by_nickname(n, 1);
+ if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
}
- smartlist_add(routers, (void*) r);
+ if (!node_has_descriptor(node)) {
+ connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n);
+ goto done;
+ }
+ smartlist_add(nodes, (void*)node);
});
- if (!smartlist_len(routers)) {
+ if (!smartlist_len(nodes)) {
connection_write_str_to_buf("512 No router names provided\r\n", conn);
goto done;
}
@@ -2188,9 +2192,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
}
/* now circ refers to something that is ready to be extended */
- SMARTLIST_FOREACH(routers, const routerinfo_t *, r,
+ SMARTLIST_FOREACH(nodes, const node_t *, node,
{
- extend_info_t *info = extend_info_from_router(r);
+ extend_info_t *info = extend_info_from_node(node);
+ tor_assert(info); /* True, since node_has_descriptor(node) == true */
circuit_append_new_exit(circ, info);
extend_info_free(info);
});
@@ -2224,7 +2229,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
done:
SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
smartlist_free(router_nicknames);
- smartlist_free(routers);
+ smartlist_free(nodes);
return 0;
}
@@ -2340,16 +2345,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Is this a single hop circuit? */
if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
- const routerinfo_t *r = NULL;
+ const node_t *node = NULL;
char *exit_digest;
if (circ->build_state &&
circ->build_state->chosen_exit &&
!tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
exit_digest = circ->build_state->chosen_exit->identity_digest;
- r = router_get_by_digest(exit_digest);
+ node = node_get_by_id(exit_digest);
}
/* Do both the client and relay allow one-hop exit circuits? */
- if (!r || !r->allow_single_hop_exits ||
+ if (!node ||
+ !node_allows_single_hop_exits(node) ||
!get_options()->AllowSingleHopCircuits) {
connection_write_str_to_buf(
"551 Can't attach stream to this one-hop circuit.\r\n", conn);
@@ -3177,10 +3183,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
static void
orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
{
- const routerinfo_t *ri = router_get_by_digest(conn->identity_digest);
- if (ri) {
+ const node_t *node = node_get_by_id(conn->identity_digest);
+ if (node) {
tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
- router_get_verbose_nickname(name, ri);
+ node_get_verbose_nickname(node, name);
} else if (! tor_digest_is_zero(conn->identity_digest)) {
name[0] = '$';
base16_encode(name+1, len-1, conn->identity_digest,
@@ -3722,9 +3728,9 @@ control_event_guard(const char *nickname, const char *digest,
{
char buf[MAX_VERBOSE_NICKNAME_LEN+1];
- const routerinfo_t *ri = router_get_by_digest(digest);
- if (ri) {
- router_get_verbose_nickname(buf, ri);
+ const node_t *node = node_get_by_id(digest);
+ if (node) {
+ node_get_verbose_nickname(node, buf);
} else {
tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
}
diff --git a/src/or/directory.c b/src/or/directory.c
index 2e0eb00a0..27de0aecd 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -17,6 +17,7 @@
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -219,13 +220,14 @@ dir_conn_purpose_to_string(int purpose)
int
router_supports_extrainfo(const char *identity_digest, int is_authority)
{
- const routerinfo_t *ri = router_get_by_digest(identity_digest);
+ const node_t *node = node_get_by_id(identity_digest);
- if (ri) {
- if (ri->caches_extra_info)
+ if (node->ri) {
+ if (node->ri->caches_extra_info)
return 1;
- if (is_authority && ri->platform &&
- tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
+ if (is_authority && node->ri->platform &&
+ tor_version_as_new_as(node->ri->platform,
+ "Tor 0.2.0.0-alpha-dev (r10070)"))
return 1;
}
if (is_authority) {
@@ -401,10 +403,12 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
* possible directory question. This won't be true forever. -RD */
/* It certainly is not true with conditional consensus downloading,
* so, for now, never assume the server supports that. */
- const routerinfo_t *ri = choose_random_entry(NULL);
- if (ri) {
+ const node_t *node = choose_random_entry(NULL);
+ if (node && node->ri) {
+ /* every bridge has a routerinfo. */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
+ routerinfo_t *ri = node->ri;
+ node_get_addr(node, &addr);
directory_initiate_command(ri->address, &addr,
ri->or_port, 0,
0, /* don't use conditional consensus url */
@@ -523,18 +527,19 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
time_t if_modified_since,
const rend_data_t *rend_query)
{
- const routerinfo_t *router;
+ const node_t *node;
char address_buf[INET_NTOA_BUF_LEN+1];
struct in_addr in;
const char *address;
tor_addr_t addr;
- router = router_get_by_digest(status->identity_digest);
- if (!router && anonymized_connection) {
+ node = node_get_by_id(status->identity_digest);
+ if (!node && anonymized_connection) {
log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
"don't have its router descriptor.", status->nickname);
return;
- } else if (router) {
- address = router->address;
+ } else if (node) {
+ node_get_address_string(node, address_buf, sizeof(address_buf));
+ address = address_buf;
} else {
in.s_addr = htonl(status->addr);
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
@@ -3694,7 +3699,7 @@ dir_microdesc_download_failed(smartlist_t *failed,
if (! consensus)
return;
SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
- rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus, d);
+ rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
if (!rs)
continue;
dls = &rs->dl_status;
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 0da12e41d..dec1577b3 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -16,6 +16,7 @@
#include "hibernate.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rephist.h"
#include "router.h"
@@ -65,8 +66,6 @@ static char *format_versions_list(config_line_t *ln);
struct authdir_config_t;
static int add_fingerprint_to_dir(const char *nickname, const char *fp,
struct authdir_config_t *list);
-static uint32_t dirserv_router_get_status(const routerinfo_t *router,
- const char **msg);
static uint32_t
dirserv_get_status_impl(const char *fp, const char *nickname,
const char *address,
@@ -304,7 +303,7 @@ dirserv_load_fingerprint_file(void)
*
* If the status is 'FP_REJECT' and <b>msg</b> is provided, set
* *<b>msg</b> to an explanation of why. */
-static uint32_t
+uint32_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg)
{
char d[DIGEST_LEN];
@@ -361,7 +360,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
return 0;
}
-/** Helper: As dirserv_get_router_status, but takes the router fingerprint
+/** Helper: As dirserv_router_get_status, but takes the router fingerprint
* (hex, no spaces), nickname, address (used for logging only), IP address, OR
* port, platform (logging only) and contact info (logging only) as arguments.
*
@@ -376,7 +375,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
const char **msg, int should_log)
{
int reject_unlisted = get_options()->AuthDirRejectUnlisted;
- uint32_t result = 0;
+ uint32_t result;
router_status_t *status_by_digest;
if (!fingerprint_list)
@@ -534,7 +533,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
*/
int
authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain)
+ int complain, int *valid_out)
{
/* Okay. Now check whether the fingerprint is recognized. */
uint32_t status = dirserv_router_get_status(ri, msg);
@@ -575,15 +574,24 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
*msg = "Rejected: Address is not an IP, or IP is a private address.";
return -1;
}
- /* Okay, looks like we're willing to accept this one. */
- ri->is_named = (status & FP_NAMED) ? 1 : 0;
- ri->is_valid = (status & FP_INVALID) ? 0 : 1;
- ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
- ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
+
+ *valid_out = ! (status & FP_INVALID);
return 0;
}
+/** Update the relevant flags of <b>node</b> based on our opinion as a
+ * directory authority in <b>authstatus</b>, as returned by
+ * dirserv_router_get_status or equivalent. */
+void
+dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus)
+{
+ node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
+ node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
+ node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+}
+
/** True iff <b>a</b> is more severe than <b>b</b>. */
static int
WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
@@ -752,8 +760,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
routerlist_descriptors_added(changed, 0);
smartlist_free(changed);
if (!*msg) {
- *msg = ri->is_valid ? "Descriptor for valid server accepted" :
- "Descriptor for invalid server accepted";
+ *msg = "Descriptor accepted";
}
log_info(LD_DIRSERV,
"Added descriptor from '%s' (source: %s): %s.",
@@ -808,50 +815,60 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
static void
directory_remove_invalid(void)
{
- int i;
int changed = 0;
routerlist_t *rl = router_get_routerlist();
+ smartlist_t *nodes = smartlist_create();
+ smartlist_add_all(nodes, nodelist_get_list());
- routerlist_assert_ok(rl);
-
- for (i = 0; i < smartlist_len(rl->routers); ++i) {
+ SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
const char *msg;
- routerinfo_t *ent = smartlist_get(rl->routers, i);
- uint32_t r = dirserv_router_get_status(ent, &msg);
+ routerinfo_t *ent = node->ri;
+ uint32_t r;
+ if (!ent)
+ continue;
+ r = dirserv_router_get_status(ent, &msg);
if (r & FP_REJECT) {
log_info(LD_DIRSERV, "Router '%s' is now rejected: %s",
ent->nickname, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
- i--;
changed = 1;
continue;
}
- if (bool_neq((r & FP_NAMED), ent->is_named)) {
+#if 0
+ if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
log_info(LD_DIRSERV,
"Router '%s' is now %snamed.", ent->nickname,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NAMED)?1:0;
changed = 1;
}
- if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
+ if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
+ log_info(LD_DIRSERV,
+ "Router '%s' is now %snamed. (FP_UNNAMED)", ent->nickname,
+ (r&FP_NAMED)?"":"un");
+ ent->is_named = (r&FP_NUNAMED)?0:1;
+ changed = 1;
+ }
+#endif
+ if (bool_neq((r & FP_INVALID), !node->is_valid)) {
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname,
(r&FP_INVALID) ? "in" : "");
- ent->is_valid = (r&FP_INVALID)?0:1;
+ node->is_valid = (r&FP_INVALID)?0:1;
changed = 1;
}
- if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
+ if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname,
(r & FP_BADDIR) ? "bad" : "good");
- ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
+ node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
changed = 1;
}
- if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
+ if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname,
(r & FP_BADEXIT) ? "bad" : "good");
- ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+ node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
changed = 1;
}
- }
+ } SMARTLIST_FOREACH_END(node);
if (changed)
directory_set_dirty();
@@ -894,10 +911,11 @@ directory_set_dirty(void)
* as running iff <b>is_live</b> is true.
*/
static char *
-list_single_server_status(routerinfo_t *desc, int is_live)
+list_single_server_status(const routerinfo_t *desc, int is_live)
{
char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
char *cp;
+ const node_t *node;
tor_assert(desc);
@@ -905,7 +923,8 @@ list_single_server_status(routerinfo_t *desc, int is_live)
if (!is_live) {
*cp++ = '!';
}
- if (desc->is_valid) {
+ node = node_get_by_id(desc->cache_info.identity_digest);
+ if (node && node->is_valid) {
strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
cp += strlen(cp);
*cp++ = '=';
@@ -944,6 +963,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
unreachable.
*/
int answer;
+ node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
+ tor_assert(node);
if (router_is_me(router)) {
/* We always know if we are down ourselves. */
@@ -968,7 +989,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
rep_hist_note_router_unreachable(router->cache_info.identity_digest, now);
}
- router->is_running = answer;
+ node->is_running = answer;
}
/** Based on the routerinfo_ts in <b>routers</b>, allocate the
@@ -996,6 +1017,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
rs_entries = smartlist_create();
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
if (authdir) {
/* Update router status in routerinfo_t. */
dirserv_set_router_is_running(ri, now);
@@ -1003,12 +1026,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
if (for_controller) {
char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
char *cp = name_buf;
- if (!ri->is_running)
+ if (!node->is_running)
*cp++ = '!';
router_get_verbose_nickname(cp, ri);
smartlist_add(rs_entries, tor_strdup(name_buf));
} else if (ri->cache_info.published_on >= cutoff) {
- smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
+ smartlist_add(rs_entries, list_single_server_status(ri,
+ node->is_running));
}
} SMARTLIST_FOREACH_END(ri);
@@ -1046,12 +1070,12 @@ format_versions_list(config_line_t *ln)
* not hibernating, and not too old. Else return 0.
*/
static int
-router_is_active(routerinfo_t *ri, time_t now)
+router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
{
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
if (ri->cache_info.published_on < cutoff)
return 0;
- if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
+ if (!node->is_running || !node->is_valid || ri->is_hibernating)
return 0;
return 1;
}
@@ -1717,7 +1741,7 @@ static uint64_t total_exit_bandwidth = 0;
/** Helper: estimate the uptime of a router given its stated uptime and the
* amount of time since it last stated its stated uptime. */
static INLINE long
-real_uptime(routerinfo_t *router, time_t now)
+real_uptime(const routerinfo_t *router, time_t now)
{
if (now < router->cache_info.published_on)
return router->uptime;
@@ -1768,7 +1792,8 @@ dirserv_thinks_router_is_unreliable(time_t now,
* been set.
*/
static int
-dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
+dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
+ const node_t *node, time_t now)
{
long uptime = real_uptime(router, now);
@@ -1778,7 +1803,7 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
* version is too old. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime > get_options()->MinUptimeHidServDirectoryV2 &&
- router->is_running);
+ node->is_running);
}
/** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1826,19 +1851,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* Weighted fractional uptime for each active router. */
wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
+ nodelist_assert_ok();
+
/* Now, fill in the arrays. */
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
uint32_t bw;
- ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
- exit_policy_is_general_exit(ri->exit_policy));
+ node->is_exit = (!router_exit_policy_rejects_all(ri) &&
+ exit_policy_is_general_exit(ri->exit_policy));
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
mtbfs[n_active] = rep_hist_get_stability(id, now);
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
total_bandwidth += bw;
- if (ri->is_exit && !ri->is_bad_exit) {
+ if (node->is_exit && !node->is_bad_exit) {
total_exit_bandwidth += bw;
} else {
bandwidths_excluding_exits[n_active_nonexit] = bw;
@@ -1846,7 +1874,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
}
++n_active;
}
- });
+ } SMARTLIST_FOREACH_END(node);
/* Now, compute thresholds. */
if (n_active) {
@@ -1872,15 +1900,17 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* Now that we have a time-known that 7/8 routers are known longer than,
* fill wfus with the wfu of every such "familiar" router. */
n_familiar = 0;
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
long tk = rep_hist_get_weighted_time_known(id, now);
if (tk < guard_tk)
continue;
wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
}
- });
+ } SMARTLIST_FOREACH_END(node);
if (n_familiar)
guard_wfu = median_double(wfus, n_familiar);
if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
@@ -2123,6 +2153,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
int first_is_auth, second_is_auth;
uint32_t bw_first, bw_second;
+ const node_t *node_first, *node_second;
+ int first_is_running, second_is_running;
/* we return -1 if first should appear before second... that is,
* if first is a better router. */
@@ -2145,9 +2177,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
else if (!first_is_auth && second_is_auth)
return 1;
- else if (first->is_running && !second->is_running)
+ node_first = node_get_by_id(first->cache_info.identity_digest);
+ node_second = node_get_by_id(second->cache_info.identity_digest);
+ first_is_running = node_first && node_first->is_running;
+ second_is_running = node_second && node_second->is_running;
+
+ if (first_is_running && !second_is_running)
return -1;
- else if (!first->is_running && second->is_running)
+ else if (!first_is_running && second_is_running)
return 1;
bw_first = router_get_advertised_bandwidth(first);
@@ -2216,7 +2253,9 @@ get_possible_sybil_list(const smartlist_t *routers)
*/
void
set_routerstatus_from_routerinfo(routerstatus_t *rs,
- routerinfo_t *ri, time_t now,
+ node_t *node,
+ routerinfo_t *ri,
+ time_t now,
int naming, int listbadexits,
int listbaddirs)
{
@@ -2228,48 +2267,46 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
router_digest_is_trusted_dir(ri->cache_info.identity_digest);
/* Already set by compute_performance_thresholds. */
- rs->is_exit = ri->is_exit;
- rs->is_stable = ri->is_stable =
- router_is_active(ri, now) &&
+ rs->is_exit = node->is_exit;
+ rs->is_stable = node->is_stable =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
!unstable_version;
- rs->is_fast = ri->is_fast =
- router_is_active(ri, now) &&
+ rs->is_fast = node->is_fast =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
- rs->is_running = ri->is_running; /* computed above */
+ rs->is_running = node->is_running; /* computed above */
if (naming) {
uint32_t name_status = dirserv_get_name_status(
- ri->cache_info.identity_digest, ri->nickname);
+ node->identity, ri->nickname);
rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
}
- rs->is_valid = ri->is_valid;
+ rs->is_valid = node->is_valid;
- if (rs->is_fast &&
+ if (node->is_fast &&
(router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
router_get_advertised_bandwidth(ri) >=
MIN(guard_bandwidth_including_exits,
guard_bandwidth_excluding_exits))) {
- long tk = rep_hist_get_weighted_time_known(
- ri->cache_info.identity_digest, now);
- double wfu = rep_hist_get_weighted_fractional_uptime(
- ri->cache_info.identity_digest, now);
+ long tk = rep_hist_get_weighted_time_known(node->identity, now);
+ double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
} else {
rs->is_possible_guard = 0;
}
- rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
- rs->is_bad_exit = listbadexits && ri->is_bad_exit;
- ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
- rs->is_hs_dir = ri->is_hs_dir;
+ rs->is_bad_directory = listbaddirs && node->is_bad_directory;
+ rs->is_bad_exit = listbadexits && node->is_bad_exit;
+ node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
+ rs->is_hs_dir = node->is_hs_dir;
rs->is_v2_dir = ri->dir_port != 0;
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
rs->is_named = rs->is_unnamed = 0;
rs->published_on = ri->cache_info.published_on;
- memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
+ memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
DIGEST_LEN);
rs->addr = ri->addr;
@@ -2294,18 +2331,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
* forget to add it to this clause. */
}
-/** Clear all the status flags in routerinfo <b>router</b>. We put this
- * function here because it's eerily similar to
- * clear_status_flags_on_sybil() above. One day we should merge them. */
-void
-router_clear_status_flags(routerinfo_t *router)
-{
- router->is_valid = router->is_running = router->is_hs_dir =
- router->is_fast = router->is_stable =
- router->is_possible_guard = router->is_exit =
- router->is_bad_exit = router->is_bad_directory = 0;
-}
-
/**
* Helper function to parse out a line in the measured bandwidth file
* into a measured_bw_line_t output structure. Returns -1 on failure
@@ -2553,10 +2578,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
routerstatus_t *rs;
vote_routerstatus_t *vrs;
microdesc_t *md;
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
- set_routerstatus_from_routerinfo(rs, ri, now,
+ set_routerstatus_from_routerinfo(rs, node, ri, now,
naming, listbadexits, listbaddirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
@@ -2796,8 +2824,12 @@ generate_v2_networkstatus_opinion(void)
if (ri->cache_info.published_on >= cutoff) {
routerstatus_t rs;
char *version = version_from_platform(ri->platform);
-
- set_routerstatus_from_routerinfo(&rs, ri, now,
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node) {
+ tor_free(version);
+ continue;
+ }
+ set_routerstatus_from_routerinfo(&rs, node, ri, now,
naming, listbadexits, listbaddirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
@@ -3122,6 +3154,7 @@ dirserv_orconn_tls_done(const char *address,
}
}
});
+
/* FFFF Maybe we should reinstate the code that dumps routers with the same
* addr/port but with nonmatching keys, but instead of dumping, we should
* skip testing. */
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index f14aee614..a77963243 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -40,8 +40,6 @@
MAX_V_LINE_LEN \
)
-#define UNNAMED_ROUTER_NICKNAME "Unnamed"
-
int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
@@ -104,7 +102,13 @@ int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
void dirserv_test_reachability(time_t now);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain);
+ int complain,
+ int *valid_out);
+uint32_t dirserv_router_get_status(const routerinfo_t *router,
+ const char **msg);
+void dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus);
+
int dirserv_would_reject_router(const routerstatus_t *rs);
int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index e384dc53b..33213a88c 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -63,6 +63,7 @@ const char *dirvote_get_pending_detached_signatures(void);
#define DGV_INCLUDE_PREVIOUS 4
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+ node_t *node,
routerinfo_t *ri, time_t now,
int naming, int listbadexits,
int listbaddirs);
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 19970aa78..c3511cf32 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -587,3 +587,4 @@ update_microdescs_from_networkstatus(time_t now)
md->last_listed = ns->valid_after;
} SMARTLIST_FOREACH_END(rs);
}
+
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index e5dd4a9d9..7374ced70 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -107,9 +107,8 @@ void
networkstatus_reset_warnings(void)
{
if (current_consensus) {
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
- rs->name_lookup_warned = 0);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ node->name_lookup_warned = 0);
}
have_warned_about_old_version = 0;
@@ -1070,92 +1069,11 @@ const routerstatus_t *
router_get_consensus_status_by_nickname(const char *nickname,
int warn_if_unnamed)
{
- char digest[DIGEST_LEN];
- routerstatus_t *best=NULL;
- smartlist_t *matches=NULL;
- const char *named_id=NULL;
-
- if (!current_consensus || !nickname)
- return NULL;
-
- /* Is this name really a hexadecimal identity digest? */
- if (nickname[0] == '$') {
- if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
- return NULL;
- return networkstatus_vote_find_entry(current_consensus, digest);
- } else if (strlen(nickname) == HEX_DIGEST_LEN &&
- (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
- return networkstatus_vote_find_entry(current_consensus, digest);
- }
-
- /* Is there a server that is Named with this name? */
- if (named_server_map)
- named_id = strmap_get_lc(named_server_map, nickname);
- if (named_id)
- return networkstatus_vote_find_entry(current_consensus, named_id);
-
- /* Okay; is this name listed as Unnamed? */
- if (unnamed_server_map &&
- strmap_get_lc(unnamed_server_map, nickname)) {
- log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
- "canonical name of any server we know.", escaped(nickname));
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->rs;
+ else
return NULL;
- }
-
- /* This name is not canonical for any server; go through the list and
- * see who it matches. */
- /*XXXX This is inefficient; optimize it if it matters. */
- matches = smartlist_create();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, lrs,
- {
- if (!strcasecmp(lrs->nickname, nickname)) {
- if (lrs->is_named) {
- tor_fragile_assert() /* This should never happen. */
- smartlist_free(matches);
- return lrs;
- } else {
- if (lrs->is_unnamed) {
- tor_fragile_assert(); /* nor should this. */
- smartlist_clear(matches);
- best=NULL;
- break;
- }
- smartlist_add(matches, lrs);
- best = lrs;
- }
- }
- });
-
- if (smartlist_len(matches)>1 && warn_if_unnamed) {
- int any_unwarned=0;
- SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
- {
- if (! lrs->name_lookup_warned) {
- lrs->name_lookup_warned=1;
- any_unwarned=1;
- }
- });
- if (any_unwarned) {
- log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
- " but none is listed as named by the directory authorities. "
- "Choosing one arbitrarily.", nickname);
- }
- } else if (warn_if_unnamed && best && !best->name_lookup_warned) {
- char fp[HEX_DIGEST_LEN+1];
- base16_encode(fp, sizeof(fp),
- best->identity_digest, DIGEST_LEN);
- log_warn(LD_CONFIG,
- "When looking up a status, you specified a server \"%s\" by name, "
- "but the directory authorities do not have any key registered for "
- "this nickname -- so it could be used by any server, "
- "not just the one you meant. "
- "To make sure you get the same server in the future, refer to "
- "it by key, as \"$%s\".", nickname, fp);
- best->name_lookup_warned = 1;
- }
- smartlist_free(matches);
- return best;
}
/** Return the identity digest that's mapped to officially by
@@ -1629,7 +1547,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->identity_digest, DIGEST_LEN),
STMT_NIL) {
/* Okay, so we're looking at the same identity. */
- rs_new->name_lookup_warned = rs_old->name_lookup_warned;
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (!memcmp(rs_old->descriptor_digest, rs_new->descriptor_digest,
@@ -2062,7 +1979,6 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
trusted_dir_server_t *ds;
or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
- int namingdir = authdir && options->NamingAuthoritativeDir;
networkstatus_t *ns = current_consensus;
if (!ns || !smartlist_len(ns->routerstatus_list))
return;
@@ -2076,25 +1992,19 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
memcmp(rs->identity_digest,
router->cache_info.identity_digest, DIGEST_LEN),
{
+#if 0
/* We have no routerstatus for this router. Clear flags and skip it. */
- if (!namingdir)
- router->is_named = 0;
if (!authdir) {
if (router->purpose == ROUTER_PURPOSE_GENERAL)
router_clear_status_flags(router);
}
+#endif
}) {
/* We have a routerstatus for this router. */
const char *digest = router->cache_info.identity_digest;
ds = router_get_trusteddirserver_by_digest(digest);
- if (!namingdir) {
- if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
- router->is_named = 1;
- else
- router->is_named = 0;
- }
/* Is it the same descriptor, or only the same identity? */
if (!memcmp(router->cache_info.signed_descriptor_digest,
rs->descriptor_digest, DIGEST_LEN)) {
@@ -2102,18 +2012,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
router->cache_info.last_listed_as_valid_until = ns->valid_until;
}
- if (!authdir) {
- /* If we're not an authdir, believe others. */
- router->is_valid = rs->is_valid;
- router->is_running = rs->is_running;
- router->is_fast = rs->is_fast;
- router->is_stable = rs->is_stable;
- router->is_possible_guard = rs->is_possible_guard;
- router->is_exit = rs->is_exit;
- router->is_bad_directory = rs->is_bad_directory;
- router->is_bad_exit = rs->is_bad_exit;
- router->is_hs_dir = rs->is_hs_dir;
- } else {
+ if (authdir) {
/* If we _are_ an authority, we should check whether this router
* is one that will cause us to need a reachability test. */
routerinfo_t *old_router =
@@ -2123,7 +2022,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
dirserv_should_launch_reachability_test(router, old_router);
}
}
- if (router->is_running && ds) {
+ if (rs->is_running && ds) {
download_status_reset(&ds->v2_ns_dl_status);
}
if (reset_failures) {
@@ -2214,6 +2113,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
statuses = smartlist_create();
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
if (ri->cache_info.published_on < cutoff)
continue;
if (ri->purpose != purpose)
@@ -2221,7 +2123,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
dirserv_set_router_is_running(ri, now);
/* then generate and write out status lines for each of them */
- set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0);
+ set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0);
smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
});
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 61c475dee..aa5496e2b 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -59,8 +59,9 @@ const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
networkstatus_t *consensus,
const char *digest);
-const routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
- int warn_if_unnamed);
+const routerstatus_t *router_get_consensus_status_by_nickname(
+ const char *nickname,
+ int warn_if_unnamed);
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
int networkstatus_nickname_is_unnamed(const char *nickname);
void networkstatus_consensus_download_failed(int status_code,
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index b620b408e..f2923a4eb 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -5,14 +5,17 @@
/* See LICENSE for licensing information */
#include "or.h"
-#include "nodelist.h"
+#include "config.h"
+#include "dirserv.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
+#include "router.h"
#include "routerlist.h"
#include <string.h>
-static void nodelist_drop_node(node_t *node);
+static void nodelist_drop_node(node_t *node, int remove_from_ht);
static void node_free(node_t *node);
/** A nodelist_t holds a node_t object for every router we're "willing to use
@@ -24,6 +27,7 @@ typedef struct nodelist_t {
smartlist_t *nodes;
/* Hash table to map from node ID digest to node. */
HT_HEAD(nodelist_map, node_t) nodes_by_id;
+
} nodelist_t;
static INLINE unsigned int
@@ -63,10 +67,9 @@ init_nodelist(void)
}
}
-/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
- * if no such node exists. */
+/** As node_get_by_id, but returns a non-const pointer */
node_t *
-node_get_by_id(const char *identity_digest)
+node_get_mutable_by_id(const char *identity_digest)
{
node_t search, *node;
if (PREDICT_UNLIKELY(the_nodelist == NULL))
@@ -77,6 +80,14 @@ node_get_by_id(const char *identity_digest)
return node;
}
+/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
+ * if no such node exists. */
+const node_t *
+node_get_by_id(const char *identity_digest)
+{
+ return node_get_mutable_by_id(identity_digest);
+}
+
/** Internal: return the node_t whose identity_digest is
* <b>identity_digest</b>. If none exists, create a new one, add it to the
* nodelist, and return it.
@@ -88,7 +99,7 @@ node_get_or_create(const char *identity_digest)
{
node_t *node;
- if ((node = node_get_by_id(identity_digest)))
+ if ((node = node_get_mutable_by_id(identity_digest)))
return node;
node = tor_malloc_zero(sizeof(node_t));
@@ -98,6 +109,8 @@ node_get_or_create(const char *identity_digest)
smartlist_add(the_nodelist->nodes, node);
node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1;
+ node->country = -1;
+
return node;
}
@@ -109,6 +122,16 @@ nodelist_add_routerinfo(routerinfo_t *ri)
init_nodelist();
node = node_get_or_create(ri->cache_info.identity_digest);
node->ri = ri;
+
+ if (node->country == -1)
+ node_set_country(node);
+
+ if (authdir_mode(get_options())) {
+ const char *discard=NULL;
+ uint32_t status = dirserv_router_get_status(ri, &discard);
+ dirserv_set_node_flags_from_authoritative_status(node, status);
+ }
+
return node;
}
@@ -133,7 +156,7 @@ nodelist_add_microdesc(microdesc_t *md)
rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
if (rs == NULL)
return NULL;
- node = node_get_by_id(rs->identity_digest);
+ node = node_get_mutable_by_id(rs->identity_digest);
if (node)
node->md = md;
return node;
@@ -147,6 +170,8 @@ nodelist_add_microdesc(microdesc_t *md)
void
nodelist_set_consensus(networkstatus_t *ns)
{
+ or_options_t *options = get_options();
+ int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
init_nodelist();
SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
@@ -162,8 +187,43 @@ nodelist_set_consensus(networkstatus_t *ns)
rs->descriptor_digest);
}
}
+
+ node_set_country(node);
+
+ /* If we're not an authdir, believe others. */
+ if (!authdir) {
+ node->is_valid = rs->is_valid;
+ node->is_running = rs->is_running;
+ node->is_fast = rs->is_fast;
+ node->is_stable = rs->is_stable;
+ node->is_possible_guard = rs->is_possible_guard;
+ node->is_exit = rs->is_exit;
+ node->is_bad_directory = rs->is_bad_directory;
+ node->is_bad_exit = rs->is_bad_exit;
+ node->is_hs_dir = rs->is_hs_dir;
+ }
+
} SMARTLIST_FOREACH_END(rs);
+
nodelist_purge();
+
+ if (! authdir) {
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ /* We have no routerstatus for this router. Clear flags so we can skip
+ * it, maybe.*/
+ if (!node->rs) {
+ tor_assert(node->ri); /* if it had only an md, or nothing, purge
+ * would have removed it. */
+ if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) {
+ /* Clear all flags. */
+ node->is_valid = node->is_running = node->is_hs_dir =
+ node->is_fast = node->is_stable =
+ node->is_possible_guard = node->is_exit =
+ node->is_bad_exit = node->is_bad_directory = 0;
+ }
+ }
+ } SMARTLIST_FOREACH_END(node);
+ }
}
/** Helper: return true iff a node has a usable amount of information*/
@@ -178,7 +238,7 @@ node_is_usable(const node_t *node)
void
nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
{
- node_t *node = node_get_by_id(identity_digest);
+ node_t *node = node_get_mutable_by_id(identity_digest);
if (node && node->md == md)
node->md = NULL;
}
@@ -187,11 +247,11 @@ nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
void
nodelist_remove_routerinfo(routerinfo_t *ri)
{
- node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
if (node && node->ri == ri) {
node->ri = NULL;
if (! node_is_usable(node)) {
- nodelist_drop_node(node);
+ nodelist_drop_node(node, 1);
node_free(node);
}
}
@@ -200,12 +260,14 @@ nodelist_remove_routerinfo(routerinfo_t *ri)
/** Remove <b>node</b> from the nodelist. (Asserts that it was there to begin
* with.) */
static void
-nodelist_drop_node(node_t *node)
+nodelist_drop_node(node_t *node, int remove_from_ht)
{
node_t *tmp;
int idx;
- tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
- tor_assert(tmp == node);
+ if (remove_from_ht) {
+ tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
+ tor_assert(tmp == node);
+ }
idx = node->nodelist_idx;
tor_assert(idx >= 0);
@@ -238,6 +300,7 @@ nodelist_purge(void)
if (PREDICT_UNLIKELY(the_nodelist == NULL))
return;
+ /* Remove the non-usable nodes. */
for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) {
node_t *node = *iter;
@@ -245,11 +308,11 @@ nodelist_purge(void)
iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter);
} else {
iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter);
- nodelist_drop_node(node);
+ nodelist_drop_node(node, 0);
node_free(node);
}
}
-
+ nodelist_assert_ok();
}
/** Release all storage held by the nodelist. */
@@ -286,25 +349,25 @@ nodelist_assert_ok(void)
/* every routerinfo in rl->routers should be in the nodelist. */
if (rl) {
SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
- node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
tor_assert(node && node->ri == ri);
tor_assert(0 == memcmp(ri->cache_info.identity_digest,
node->identity, DIGEST_LEN));
tor_assert(! digestmap_get(dm, node->identity));
- digestmap_set(dm, node->identity, node);
+ digestmap_set(dm, node->identity, (void*)node);
} SMARTLIST_FOREACH_END(ri);
}
/* every routerstatus in ns should be in the nodelist */
if (ns) {
SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
- node_t *node = node_get_by_id(rs->identity_digest);
+ const node_t *node = node_get_by_id(rs->identity_digest);
tor_assert(node && node->rs == rs);
tor_assert(0 == memcmp(rs->identity_digest, node->identity, DIGEST_LEN));
- digestmap_set(dm, node->identity, node);
+ digestmap_set(dm, node->identity, (void*)node);
if (ns->flavor == FLAV_MICRODESC) {
- /* If it's a microdesc consensus, every entry that has a microdescriptor
- * should be in the nodelist.
+ /* If it's a microdesc consensus, every entry that has a
+ * microdescriptor should be in the nodelist.
*/
microdesc_t *md =
microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
@@ -326,3 +389,316 @@ nodelist_assert_ok(void)
digestmap_free(dm, NULL);
}
+/** Return a list of a node_t * for every node we know about. The caller
+ * MUST NOT modify the list. (You can set and clear flags in the nodes if
+ * you must, but you must not add or remove nodes.) */
+smartlist_t *
+nodelist_get_list(void)
+{
+ init_nodelist();
+ return the_nodelist->nodes;
+}
+
+/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
+ * the corresponding node_t, or NULL if none exists. Warn the user if
+ * <b>warn_if_unnamed</b> is set, and they have specified a router by
+ * nickname, but the Named flag isn't set for that router. */
+const node_t *
+node_get_by_nickname(const char *nickname, int warn_if_unnamed)
+{
+ char digest_buf[DIGEST_LEN];
+ char nn_buf[MAX_NICKNAME_LEN+1];
+ char nn_char='\0';
+
+ if (!the_nodelist)
+ return NULL;
+
+ /* ???? NM Naming authorities had an additional weird behavior here where
+ they would treat their own namings as slightly authoritative in a
+ strange and inconsistent way. I think that this way is better, but we
+ could get the old behavior back if we wanted to by adding a function
+ to look in the fp_by_name table in fingerprint_list, and using this
+ function to override the name-to-digest lookup below if we are a
+ naming server. -NM
+ */
+
+ /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
+ if (hex_digest_nickname_decode(nickname, digest_buf, &nn_char, nn_buf)==0) {
+ const node_t *node = node_get_by_id(digest_buf);
+ if (!node)
+ return NULL;
+ if (nn_char) {
+ const char *real_name = node_get_nickname(node);
+ if (!real_name || strcasecmp(real_name, nn_buf))
+ return NULL;
+ if (nn_char == '=') {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nn_buf);
+ if (!named_id || memcmp(named_id, digest_buf, DIGEST_LEN))
+ return NULL;
+ }
+ }
+ return node;
+ }
+
+ if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME))
+ return NULL;
+
+ /* Okay, so if we get here, the nickname is just a nickname. Is there
+ * a binding for it in the consensus? */
+ {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nickname);
+ if (named_id)
+ return node_get_by_id(named_id);
+ }
+
+ /* Is it marked as owned-by-someone-else? */
+ if (networkstatus_nickname_is_unnamed(nickname)) {
+ log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some "
+ "router that holds it, but not one listed in the current "
+ "consensus.", escaped(nickname));
+ return NULL;
+ }
+
+ /* Okay, so the name is not canonical for anybody. */
+ {
+ smartlist_t *matches = smartlist_create();
+ const node_t *choice = NULL;
+
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ if (!strcasecmp(node_get_nickname(node), nickname))
+ smartlist_add(matches, node);
+ } SMARTLIST_FOREACH_END(node);
+
+ if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ int any_unwarned = 0;
+ SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) {
+ if (!node->name_lookup_warned) {
+ node->name_lookup_warned = 1;
+ any_unwarned = 1;
+ }
+ } SMARTLIST_FOREACH_END(node);
+
+ if (any_unwarned) {
+ log_warn(LD_CONFIG, "There are multiple matches for the name %s, "
+ "but none is listed as Named in the directory consensus. "
+ "Choosing one arbitrarily.", nickname);
+ }
+ } else if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ char fp[HEX_DIGEST_LEN+1];
+ node_t *node = smartlist_get(matches, 0);
+ if (node->name_lookup_warned) {
+ base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN);
+ log_warn(LD_CONFIG,
+ "You specified a server \"%s\" by name, but the directory "
+ "authorities do not have any key registered for this "
+ "nickname -- so it could be used by any server, not just "
+ "the one you meant. "
+ "To make sure you get the same server in the future, refer "
+ "to it by key, as \"$%s\".", nickname, fp);
+ node->name_lookup_warned = 1;
+ }
+ }
+
+ if (smartlist_len(matches))
+ choice = smartlist_get(matches, 0);
+
+ smartlist_free(matches);
+ return choice;
+ }
+}
+
+/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
+const char *
+node_get_nickname(const node_t *node)
+{
+ if (node->rs)
+ return node->rs->nickname;
+ else if (node->ri)
+ return node->ri->nickname;
+ else
+ return NULL;
+}
+
+/** Return true iff the nickname of <b>node</b> is canonical, based on the
+ * latest consensus. */
+int
+node_is_named(const node_t *node)
+{
+ const char *named_id;
+ const char *nickname = node_get_nickname(node);
+ if (!nickname)
+ return 0;
+ named_id = networkstatus_get_router_digest_by_nickname(nickname);
+ if (!named_id)
+ return 0;
+ return !memcmp(named_id, node->identity, DIGEST_LEN);
+}
+
+/** Return true iff <b>node</b> appears to be a directory authority or
+ * directory cache */
+int
+node_is_dir(const node_t *node)
+{
+ if (node->rs)
+ return node->rs->dir_port != 0;
+ else if (node->ri)
+ return node->ri->dir_port != 0;
+ else
+ return 0;
+}
+
+
+/** Return true iff <b>node</b> has either kind of usable descriptor -- that
+ * is, a routerdecriptor or a microdescriptor. */
+int
+node_has_descriptor(const node_t *node)
+{
+ return (node->ri ||
+ (node->rs && node->md));
+}
+
+/** Return the router_purpose of <b>node</b>. */
+int
+node_get_purpose(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->purpose;
+ else
+ return ROUTER_PURPOSE_GENERAL;
+}
+
+/** Compute the verbose ("extended") nickname of <b>node</b> and store it
+ * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at
+ * <b>verbose_nickname_out</b> */
+void
+node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out)
+{
+ const char *nickname = node_get_nickname(node);
+ int is_named = node_is_named(node);
+ verbose_name_out[0] = '$';
+ base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity,
+ DIGEST_LEN);
+ if (!nickname)
+ return;
+ verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+ strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+}
+
+/** Return true iff it seems that <b>node</b> allows circuits to exit
+ * through it directlry from the client. */
+int
+node_allows_single_hop_exits(const node_t *node)
+{
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+ return 0;
+}
+
+/** Return true iff it seems that <b>node</b> has an exit policy that
+ * doesn't actually permit anything to exit. */
+int
+node_exit_policy_rejects_all(const node_t *node)
+{
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+ return 0;
+}
+
+/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
+int
+node_get_addr(const node_t *node, tor_addr_t *addr_out)
+{
+ if (node->ri) {
+ tor_addr_from_ipv4h(addr_out, node->ri->addr);
+ return 0;
+ } else if (node->rs) {
+ tor_addr_from_ipv4h(addr_out, node->rs->addr);
+ return 0;
+ }
+ return -1;
+}
+
+/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
+ * seem to have one. */
+uint32_t
+node_get_addr_ipv4h(const node_t *node)
+{
+ if (node->ri) {
+ return node->ri->addr;
+ } else if (node->rs) {
+ return node->rs->addr;
+ }
+ return 0;
+}
+
+/** Copy a string representation of the IP address for <b>node</b> into the
+ * <b>len</b>-byte buffer at <b>buf</b>.
+ */
+void
+node_get_address_string(const node_t *node, char *buf, size_t len)
+{
+ if (node->ri) {
+ strlcpy(buf, node->ri->address, len);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ tor_addr_to_str(buf, &addr, len, 0);
+ } else {
+ buf[0] = '\0';
+ }
+}
+
+/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have
+ * one. */
+long
+node_get_declared_uptime(const node_t *node)
+{
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+ return 0;
+}
+
+/** Return <b>node</b>'s declared or_port */
+uint16_t
+node_get_orport(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->or_port;
+ else if (node->rs)
+ return node->rs->or_port;
+ else
+ return 0;
+}
+
+/** Return <b>node</b>'s platform string */
+const char *
+node_get_platform(const node_t *node)
+{
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+ return NULL;
+}
+
+/** Return <b>node</b>'s time of publication. */
+time_t
+node_get_published_on(const node_t *node)
+{
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+ return 0;
+}
+
+/** Return true iff <b>node</b> is one representing this router. */
+int
+node_is_me(const node_t *node)
+{
+ return router_digest_is_me(node->identity);
+}
+
+/* KILLTHIS XXXX NM -- it's a dummy to keep UNIMPLEMENTED_NODELIST()
+ * working */
+int unimplemented_nodelist_truth = 1;
+
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 6a77ba683..3dceb7573 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -12,7 +12,8 @@
#ifndef _TOR_NODELIST_H
#define _TOR_NODELIST_H
-node_t *node_get_by_id(const char *identity_digest);
+node_t *node_get_mutable_by_id(const char *identity_digest);
+const node_t *node_get_by_id(const char *identity_digest);
node_t *nodelist_add_routerinfo(routerinfo_t *ri);
node_t *nodelist_add_microdesc(microdesc_t *md);
void nodelist_set_consensus(networkstatus_t *ns);
@@ -24,5 +25,41 @@ void nodelist_purge(void);
void nodelist_free_all(void);
void nodelist_assert_ok(void);
+const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed);
+void node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out);
+int node_is_named(const node_t *node);
+int node_is_dir(const node_t *node);
+int node_has_descriptor(const node_t *node);
+int node_get_purpose(const node_t *node);
+#define node_is_bridge(node) \
+ (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
+int node_is_me(const node_t *node);
+int node_exit_policy_rejects_all(const node_t *node);
+int node_get_addr(const node_t *node, tor_addr_t *addr_out);
+uint32_t node_get_addr_ipv4h(const node_t *node);
+int node_allows_single_hop_exits(const node_t *node);
+uint16_t node_get_orport(const node_t *node);
+const char *node_get_nickname(const node_t *node);
+const char *node_get_platform(const node_t *node);
+void node_get_address_string(const node_t *node, char *cp, size_t len);
+long node_get_declared_uptime(const node_t *node);
+time_t node_get_published_on(const node_t *node);
+
+smartlist_t *nodelist_get_list(void);
+
+/* XXXX These need to move out of routerlist.c */
+void nodelist_refresh_countries(void);
+void node_set_country(node_t *node);
+void nodelist_add_node_family(smartlist_t *nodes, const node_t *node);
+int nodes_in_same_family(const node_t *node1, const node_t *node2);
+
+/* This means: implement this code or function or thing, nick! */
+#define UNIMPLEMENTED_NODELIST() \
+ while (unimplemented_nodelist_truth) { \
+ tor_assert(0); \
+ }
+extern int unimplemented_nodelist_truth;
+
#endif
diff --git a/src/or/or.h b/src/or/or.h
index e46237c36..d9be01333 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -809,6 +809,9 @@ typedef enum {
* Tor 0.1.2.x is obsolete, we can remove this. */
#define DEFAULT_CLIENT_NICKNAME "client"
+/** Name chosen by routers that don't configure nicknames */
+#define UNNAMED_ROUTER_NICKNAME "Unnamed"
+
/** Number of bytes in a SOCKS4 header. */
#define SOCKS4_NETWORK_LEN 8
@@ -1510,52 +1513,44 @@ typedef struct {
unsigned int allow_single_hop_exits:1; /**< Whether the router says
* it allows single hop exits. */
- /* local info */
- 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_named:1; /**< Do we believe the nickname that this OR gives
- * us? */
- 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_bad_directory:1; /**< Do we think this directory is junky,
- * underpowered, or otherwise useless? */
unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
* a hidden service directory. */
- unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
- * directory according to the authorities. */
unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
* router rejects everything. */
/** True if, after we have added this router, we should re-launch
* tests for it. */
unsigned int needs_retest_if_added:1;
-/** Tor can use this router for general positions in circuits. */
+/** Tor can use this router for general positions in circuits; we got it
+ * from a directory server as usual, or we're an authority and a server
+ * uploaded it. */
#define ROUTER_PURPOSE_GENERAL 0
-/** Tor should avoid using this router for circuit-building. */
+/** Tor should avoid using this router for circuit-building: we got it
+ * from a crontroller. If the controller wants to use it, it'll have to
+ * ask for it by identity. */
#define ROUTER_PURPOSE_CONTROLLER 1
-/** Tor should use this router only for bridge positions in circuits. */
+/** Tor should use this router only for bridge positions in circuits: we got
+ * it via a directory request from the bridge itself, or a bridge
+ * authority. x*/
#define ROUTER_PURPOSE_BRIDGE 2
/** Tor should not use this router; it was marked in cached-descriptors with
* a purpose we didn't recognize. */
#define ROUTER_PURPOSE_UNKNOWN 255
- uint8_t purpose; /** What positions in a circuit is this router good for? */
+ /* In what way did we find out about this router? One of ROUTER_PURPOSE_*.
+ * Routers of different purposes are kept segregated and used for different
+ * things; see notes on ROUTER_PURPOSE_* macros above.
+ */
+ uint8_t purpose;
/* 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;
/** When did we start testing reachability for this OR? */
time_t testing_since;
- /** According to the geoip db what country is this router in? */
- country_t country;
+
} routerinfo_t;
/** Information needed to keep and cache a signed extra-info document. */
@@ -1643,9 +1638,6 @@ typedef struct routerstatus_t {
* from this authority.) Applies in v2 networkstatus document only.
*/
unsigned int need_to_mirror:1;
- unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
- * to this (unnamed) router by nickname?
- */
time_t last_dir_503_at; /**< When did this router last tell us that it
* was too busy to serve directory info? */
download_status_t dl_status;
@@ -1698,17 +1690,66 @@ typedef struct microdesc_t {
* XXX this probably should not stay a string. */
} microdesc_t;
-/** DOCDOC */
+/** 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 wrapper, 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;
/** 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];
+
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. */
+
+ 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_bad_directory:1; /**< Do we think this directory is junky,
+ * underpowered, or otherwise useless? */
+ 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: derived. */
+
+ /** According to the geoip db what country is this router in? */
+ country_t country;
} node_t;
/** How many times will we try to download a router's descriptor before giving
@@ -3548,7 +3589,8 @@ typedef enum {
CRN_NEED_GUARD = 1<<2,
CRN_ALLOW_INVALID = 1<<3,
/* XXXX not used, apparently. */
- CRN_WEIGHT_AS_EXIT = 1<<5
+ CRN_WEIGHT_AS_EXIT = 1<<5,
+ CRN_NEED_DESC = 1<<6
} router_crn_flags_t;
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
diff --git a/src/or/policies.c b/src/or/policies.c
index b4d359599..1404e20e5 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "config.h"
#include "dirserv.h"
+#include "nodelist.h"
#include "policies.h"
#include "routerparse.h"
#include "ht.h"
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(const routerinfo_t *ri)
return fascist_firewall_allows_address_or(&addr, ri->or_port);
}
+/** Return true iff we think our firewall will let us make an OR connection to
+ * <b>node</b>. */
+int
+fascist_firewall_allows_node(const node_t *node)
+{
+ if (node->ri) {
+ return fascist_firewall_allows_or(node->ri);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+ } else {
+ return 1;
+ }
+}
+
/** Return true iff we think our firewall will let us make a directory
* connection to addr:port. */
int
@@ -858,6 +875,7 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
return 0;
}
+#if 0
/** Replace the exit policy of <b>r</b> with reject *:*. */
void
policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
@@ -868,6 +886,15 @@ policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
item = router_parse_addr_policy_item_from_string("reject *:*", -1);
smartlist_add(r->exit_policy, item);
}
+#endif
+
+/** Replace the exit policy of <b>node</b> with reject *:* */
+void
+policies_set_node_exitpolicy_to_reject_all(node_t *node)
+{
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+}
/** Return 1 if there is at least one /8 subnet in <b>policy</b> that
* allows exiting to <b>port</b>. Otherwise, return 0. */
@@ -1288,6 +1315,31 @@ policy_summarize(smartlist_t *policy)
return result;
}
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_addr_to_node_policy(uint32_t addr, uint16_t port, const node_t *node)
+{
+ tor_addr_t a;
+ tor_addr_from_ipv4h(&a, addr);
+ return compare_tor_addr_to_node_policy(&a, port, node);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
+ const node_t *node)
+{
+ (void)addr;
+ (void)port;
+ (void)node;
+ UNIMPLEMENTED_NODELIST();
+ return 0;
+}
+
/** Implementation for GETINFO control command: knows the answer for questions
* about "exit-policy/..." */
int
diff --git a/src/or/policies.h b/src/or/policies.h
index 4a3474570..acc254da3 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -20,6 +20,7 @@
int firewall_is_fascist_or(void);
int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
int fascist_firewall_allows_or(const routerinfo_t *ri);
+int fascist_firewall_allows_node(const node_t *node);
int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
int dir_policy_permits_address(const tor_addr_t *addr);
int socks_policy_permits_address(const tor_addr_t *addr);
@@ -38,10 +39,16 @@ addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
uint16_t port, const smartlist_t *policy);
addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
uint16_t port, const smartlist_t *policy);
+
+addr_policy_result_t compare_addr_to_node_policy(uint32_t addr,
+ uint16_t port, const node_t *node);
+addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
+ uint16_t port, const node_t *node);
+
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int rejectprivate, const char *local_address,
int add_default_policy);
-void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter);
+void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
int exit_policy_is_general_exit(smartlist_t *policy);
int policy_is_reject_star(const smartlist_t *policy);
int getinfo_helper_policies(control_connection_t *conn,
diff --git a/src/or/relay.c b/src/or/relay.c
index 48948f001..c645b729a 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -24,6 +24,7 @@
#include "main.h"
#include "mempool.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -712,7 +713,7 @@ connection_ap_process_end_not_open(
edge_connection_t *conn, crypt_path_t *layer_hint)
{
struct in_addr in;
- routerinfo_t *exitrouter;
+ node_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE);
int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
(void) layer_hint; /* unused */
@@ -725,7 +726,7 @@ connection_ap_process_end_not_open(
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address),
stream_end_reason_to_string(reason));
- exitrouter = router_get_mutable_by_digest(chosen_exit_digest);
+ exitrouter = node_get_mutable_by_id(chosen_exit_digest);
switch (reason) {
case END_STREAM_REASON_EXITPOLICY:
if (rh->length >= 5) {
@@ -760,8 +761,8 @@ connection_ap_process_end_not_open(
log_info(LD_APP,
"Exitrouter '%s' seems to be more restrictive than its exit "
"policy. Not using this router as exit for now.",
- exitrouter->nickname);
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ node_get_nickname(exitrouter));
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
/* rewrite it to an IP if we learned one. */
if (addressmap_rewrite(conn->socks_request->address,
@@ -824,7 +825,7 @@ connection_ap_process_end_not_open(
case END_STREAM_REASON_HIBERNATING:
case END_STREAM_REASON_RESOURCELIMIT:
if (exitrouter) {
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
if (conn->chosen_exit_optional) {
/* stop wanting a specific exit */
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 67bd55a29..5c5e1bfa4 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -16,6 +16,7 @@
#include "connection_edge.h"
#include "directory.h"
#include "main.h"
+#include "nodelist.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -738,7 +739,6 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
int i;
rend_cache_entry_t *entry;
rend_intro_point_t *intro;
- const routerinfo_t *router;
if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) {
log_warn(LD_REND,
@@ -755,8 +755,8 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
intro = smartlist_get(entry->parsed->intro_nodes, i);
/* Do we need to look up the router or is the extend info complete? */
if (!intro->extend_info->onion_key) {
- router = router_get_by_nickname(intro->extend_info->nickname, 0);
- if (!router) {
+ const node_t *node = node_get_by_nickname(intro->extend_info->nickname, 0);
+ if (!node) {
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
intro->extend_info->nickname);
rend_intro_point_free(intro);
@@ -764,7 +764,7 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
goto again;
}
extend_info_free(intro->extend_info);
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
}
return extend_info_dup(intro->extend_info);
}
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index f6769d558..f67e9ab65 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -14,6 +14,7 @@
#include "config.h"
#include "directory.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendservice.h"
@@ -1001,7 +1002,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
} else {
char *rp_nickname;
size_t nickname_field_len;
- const routerinfo_t *router;
+ const node_t *node;
int version;
if (*buf == 1) {
rp_nickname = buf+1;
@@ -1028,8 +1029,8 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
len -= nickname_field_len;
len -= rp_nickname - buf; /* also remove header space used by version, if
* any */
- router = router_get_by_nickname(rp_nickname, 0);
- if (!router) {
+ node = node_get_by_nickname(rp_nickname, 0);
+ if (!node) {
log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
escaped_safe_str_client(rp_nickname));
/* XXXX Add a no-such-router reason? */
@@ -1037,7 +1038,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
goto err;
}
- extend_info = extend_info_from_router(router);
+ extend_info = extend_info_from_node(node);
}
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -1754,19 +1755,19 @@ void
rend_services_introduce(void)
{
int i,j,r;
- const routerinfo_t *router;
+ const node_t *node;
rend_service_t *service;
rend_intro_point_t *intro;
int changed, prev_intro_nodes;
- smartlist_t *intro_routers;
+ smartlist_t *intro_nodes;
time_t now;
or_options_t *options = get_options();
- intro_routers = smartlist_create();
+ intro_nodes = smartlist_create();
now = time(NULL);
for (i=0; i < smartlist_len(rend_service_list); ++i) {
- smartlist_clear(intro_routers);
+ smartlist_clear(intro_nodes);
service = smartlist_get(rend_service_list, i);
tor_assert(service);
@@ -1786,8 +1787,8 @@ rend_services_introduce(void)
service. */
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router || !find_intro_circuit(intro, service->pk_digest)) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node || !find_intro_circuit(intro, service->pk_digest)) {
log_info(LD_REND,"Giving up on %s as intro point for %s.",
intro->extend_info->nickname, service->service_id);
if (service->desc) {
@@ -1806,8 +1807,8 @@ rend_services_introduce(void)
smartlist_del(service->intro_nodes,j--);
changed = 1;
}
- if (router)
- smartlist_add(intro_routers, (void*)router);
+ if (node)
+ smartlist_add(intro_nodes, (void*)node);
}
/* We have enough intro points, and the intro points we thought we had were
@@ -1836,26 +1837,26 @@ rend_services_introduce(void)
#define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
- router_crn_flags_t flags = CRN_NEED_UPTIME;
+ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
flags |= CRN_ALLOW_INVALID;
- router = router_choose_random_node(intro_routers,
- options->ExcludeNodes, flags);
- if (!router) {
+ node = router_choose_random_node(intro_nodes,
+ options->ExcludeNodes, flags);
+ if (!node) {
log_warn(LD_REND,
"Could only establish %d introduction points for %s.",
smartlist_len(service->intro_nodes), service->service_id);
break;
}
changed = 1;
- smartlist_add(intro_routers, (void*)router);
+ smartlist_add(intro_nodes, (void*)node);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
- router->nickname, service->service_id);
+ node_get_nickname(node), service->service_id);
}
/* If there's no need to launch new circuits, stop here. */
@@ -1872,7 +1873,7 @@ rend_services_introduce(void)
}
}
}
- smartlist_free(intro_routers);
+ smartlist_free(intro_nodes);
}
/** Regenerate and upload rendezvous service descriptors for all
diff --git a/src/or/rephist.c b/src/or/rephist.c
index d998e87ca..97a3c5454 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -14,6 +14,7 @@
#include "circuitlist.h"
#include "circuituse.h"
#include "config.h"
+#include "nodelist.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
@@ -579,7 +580,7 @@ rep_hist_dump_stats(time_t now, int severity)
size_t len;
int ret;
unsigned long upt, downt;
- const routerinfo_t *r;
+ const node_t *node;
rep_history_clean(now - get_options()->RephistTrackTime);
@@ -593,8 +594,8 @@ rep_hist_dump_stats(time_t now, int severity)
digestmap_iter_get(orhist_it, &digest1, &or_history_p);
or_history = (or_history_t*) or_history_p;
- if ((r = router_get_by_digest(digest1)))
- name1 = r->nickname;
+ if ((node = node_get_by_id(digest1)) && node_get_nickname(node))
+ name1 = node_get_nickname(node);
else
name1 = "(unknown)";
base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
@@ -624,8 +625,8 @@ rep_hist_dump_stats(time_t now, int severity)
lhist_it = digestmap_iter_next(or_history->link_history_map,
lhist_it)) {
digestmap_iter_get(lhist_it, &digest2, &link_history_p);
- if ((r = router_get_by_digest(digest2)))
- name2 = r->nickname;
+ if ((node = node_get_by_id(digest2)) && node_get_nickname(node))
+ name2 = node_get_nickname(node);
else
name2 = "(unknown)";
@@ -871,28 +872,28 @@ rep_hist_get_router_stability_doc(time_t now)
}
DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
- const routerinfo_t *ri;
+ const node_t *node;
char dbuf[BASE64_DIGEST_LEN+1];
char header_buf[512];
char *info;
digest_to_base64(dbuf, id);
- ri = router_get_by_digest(id);
- if (ri) {
- char *ip = tor_dup_ip(ri->addr);
+ node = node_get_by_id(id);
+ if (node) {
+ char ip[INET_NTOA_BUF_LEN+1];
char tbuf[ISO_TIME_LEN+1];
- format_iso_time(tbuf, ri->cache_info.published_on);
+ node_get_address_string(node,ip,sizeof(ip));
+ format_iso_time(tbuf, node_get_published_on(node));
tor_snprintf(header_buf, sizeof(header_buf),
"router %s %s %s\n"
"published %s\n"
"relevant-flags %s%s%s\n"
"declared-uptime %ld\n",
- dbuf, ri->nickname, ip,
+ dbuf, node_get_nickname(node), ip,
tbuf,
- ri->is_running ? "Running " : "",
- ri->is_valid ? "Valid " : "",
- ri->is_hibernating ? "Hibernating " : "",
- ri->uptime);
- tor_free(ip);
+ node->is_running ? "Running " : "",
+ node->is_valid ? "Valid " : "",
+ node->ri && node->ri->is_hibernating ? "Hibernating " : "",
+ node_get_declared_uptime(node));
} else {
tor_snprintf(header_buf, sizeof(header_buf),
"router %s {no descriptor}\n", dbuf);
diff --git a/src/or/router.c b/src/or/router.c
index dfb2f06d4..507785ead 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -7,6 +7,7 @@
#define ROUTER_PRIVATE
#include "or.h"
+#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
#include "config.h"
@@ -19,6 +20,7 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "relay.h"
#include "rephist.h"
@@ -780,11 +782,14 @@ consider_testing_reachability(int test_or, int test_dir)
return;
if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
+ extend_info_t *ei;
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port);
- circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
- CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ ei = extend_info_from_router(me);
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ extend_info_free(ei);
}
tor_addr_from_ipv4h(&addr, me->addr);
@@ -1333,13 +1338,12 @@ router_rebuild_descriptor(int force)
ri->policy_is_reject_star =
policy_is_reject_star(ri->exit_policy);
- if (desc_routerinfo) { /* inherit values */
- ri->is_valid = desc_routerinfo->is_valid;
- ri->is_running = desc_routerinfo->is_running;
- ri->is_named = desc_routerinfo->is_named;
- }
+#if 0
+ /* XXXX NM NM I belive this is safe to remove */
if (authdir_mode(options))
ri->is_valid = ri->is_named = 1; /* believe in yourself */
+#endif
+
if (options->MyFamily) {
smartlist_t *family;
if (!warned_nonexistent_family)
@@ -1349,11 +1353,11 @@ router_rebuild_descriptor(int force)
smartlist_split_string(family, options->MyFamily, ",",
SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH_BEGIN(family, char *, name) {
- const routerinfo_t *member;
+ const node_t *member;
if (!strcasecmp(name, options->Nickname))
- member = ri;
+ goto skip; /* Don't list ourself, that's redundant */
else
- member = router_get_by_nickname(name, 1);
+ member = node_get_by_nickname(name, 1);
if (!member) {
int is_legal = is_legal_nickname_or_hexdigest(name);
if (!smartlist_string_isin(warned_nonexistent_family, name) &&
@@ -1373,17 +1377,19 @@ router_rebuild_descriptor(int force)
smartlist_add(ri->declared_family, name);
name = NULL;
}
- } else if (router_is_me(member)) {
+ } else if (router_digest_is_me(member->identity)) {
/* Don't list ourself in our own family; that's redundant */
+ /* XXX shouldn't be possible */
} else {
char *fp = tor_malloc(HEX_DIGEST_LEN+2);
fp[0] = '$';
base16_encode(fp+1,HEX_DIGEST_LEN+1,
- member->cache_info.identity_digest, DIGEST_LEN);
+ member->identity, DIGEST_LEN);
smartlist_add(ri->declared_family, fp);
if (smartlist_string_isin(warned_nonexistent_family, name))
smartlist_string_remove(warned_nonexistent_family, name);
}
+ skip:
tor_free(name);
} SMARTLIST_FOREACH_END(name);
@@ -1443,8 +1449,6 @@ router_rebuild_descriptor(int force)
strlen(ri->cache_info.signed_descriptor_body),
ri->cache_info.signed_descriptor_digest);
- routerinfo_set_country(ri);
-
tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
routerinfo_free(desc_routerinfo);
@@ -2098,10 +2102,15 @@ is_legal_hexdigest(const char *s)
void
router_get_verbose_nickname(char *buf, const routerinfo_t *router)
{
+ const char *good_digest = networkstatus_get_router_digest_by_nickname(
+ router->nickname);
+ int is_named = good_digest && !memcmp(good_digest,
+ router->cache_info.identity_digest,
+ DIGEST_LEN);
buf[0] = '$';
base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
+ buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 0f1bfc0eb..e456f4385 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -1072,7 +1072,7 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
static const routerstatus_t *
router_pick_directory_server_impl(authority_type_t type, int flags)
{
- const routerstatus_t *result;
+ const node_t *result;
smartlist_t *direct, *tunnel;
smartlist_t *trusted_direct, *trusted_tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
@@ -1093,49 +1093,54 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
overloaded_tunnel = smartlist_create();
/* Find all the running dirservers we know about. */
- SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *,
- status) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
int is_trusted;
- int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
+ int is_overloaded;
tor_addr_t addr;
- if (!status->is_running || !status->dir_port || !status->is_valid)
+ const routerstatus_t *status = node->rs;
+ if (!status)
+ continue;
+
+ if (!node->is_running || !status->dir_port || !node->is_valid)
continue;
- if (status->is_bad_directory)
+ if (node->is_bad_directory)
continue;
- if (requireother && router_digest_is_me(status->identity_digest))
+ if (requireother && router_digest_is_me(node->identity))
continue;
if (type & V3_AUTHORITY) {
if (!(status->version_supports_v3_dir ||
- router_digest_is_trusted_dir_type(status->identity_digest,
+ router_digest_is_trusted_dir_type(node->identity,
V3_AUTHORITY)))
continue;
}
- is_trusted = router_digest_is_trusted_dir(status->identity_digest);
- if ((type & V2_AUTHORITY) && !(status->is_v2_dir || is_trusted))
+ is_trusted = router_digest_is_trusted_dir(node->identity);
+ if ((type & V2_AUTHORITY) && !(node->rs->is_v2_dir || is_trusted))
continue;
if ((type & EXTRAINFO_CACHE) &&
- !router_supports_extrainfo(status->identity_digest, 0))
+ !router_supports_extrainfo(node->identity, 0))
continue;
/* XXXX IP6 proposal 118 */
- tor_addr_from_ipv4h(&addr, status->addr);
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+
+ is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
if (prefer_tunnel &&
status->version_supports_begindir &&
(!fascistfirewall ||
fascist_firewall_allows_address_or(&addr, status->or_port)))
smartlist_add(is_trusted ? trusted_tunnel :
- is_overloaded ? overloaded_tunnel : tunnel, status);
+ is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
else if (!fascistfirewall ||
fascist_firewall_allows_address_dir(&addr, status->dir_port))
smartlist_add(is_trusted ? trusted_direct :
- is_overloaded ? overloaded_direct : direct, status);
- } SMARTLIST_FOREACH_END(status);
+ is_overloaded ? overloaded_direct : direct, (void*)node);
+ } SMARTLIST_FOREACH_END(node);
if (smartlist_len(tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_tunnel,
+ result = node_sl_choose_by_bandwidth(overloaded_tunnel,
WEIGHT_FOR_DIR);
} else if (smartlist_len(trusted_tunnel)) {
/* FFFF We don't distinguish between trusteds and overloaded trusteds
@@ -1144,10 +1149,10 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
* is a feature, but it could easily be a bug. -RD */
result = smartlist_choose(trusted_tunnel);
} else if (smartlist_len(direct)) {
- result = routerstatus_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_direct)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_direct,
- WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(overloaded_direct,
+ WEIGHT_FOR_DIR);
} else {
result = smartlist_choose(trusted_direct);
}
@@ -1157,7 +1162,7 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
smartlist_free(trusted_tunnel);
smartlist_free(overloaded_direct);
smartlist_free(overloaded_tunnel);
- return result;
+ return result->rs;
}
/** Choose randomly from among the trusted dirservers that are up. Flags
@@ -1260,13 +1265,10 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
static void
mark_all_trusteddirservers_up(void)
{
- if (routerlist) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- if (router_digest_is_trusted_dir(router->cache_info.identity_digest) &&
- router->dir_port > 0) {
- router->is_running = 1;
- });
- }
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, {
+ if (router_digest_is_trusted_dir(node->identity))
+ node->is_running = 1;
+ });
if (trusted_dir_servers) {
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
{
@@ -1306,6 +1308,7 @@ routers_in_same_network_family(const routerinfo_t *r1, const routerinfo_t *r2)
return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000);
}
+#if 0
/** Look through the routerlist and identify routers that
* advertise the same /16 network address as <b>router</b>.
* Add each of them to <b>sl</b>.
@@ -1319,14 +1322,17 @@ routerlist_add_network_family(smartlist_t *sl, const routerinfo_t *router)
smartlist_add(sl, r);
});
}
+#endif
/** Add all the family of <b>router</b> to the smartlist <b>sl</b>.
* This is used to make sure we don't pick siblings in a single path,
* or pick more than one relay from a family for our entry guard list.
*/
void
-routerlist_add_family(smartlist_t *sl, const routerinfo_t *router)
+nodelist_add_node_family(smartlist_t *sl, const node_t *router)
{
+ /* XXXX MOVE */
+#if 0
const routerinfo_t *r;
config_line_t *cl;
or_options_t *options = get_options();
@@ -1357,6 +1363,23 @@ routerlist_add_family(smartlist_t *sl, const routerinfo_t *router)
add_nickname_list_to_smartlist(sl, cl->value, 0);
}
}
+#endif
+ (void)sl;
+ (void)router;
+ UNIMPLEMENTED_NODELIST();
+}
+
+/** Given a <b>router</b>, add every node_t in its family to <b>sl</b>.
+ *
+ * Note the type mismatch: This function takes a routerinfo, but adds nodes
+ * to the smartlist!
+ */
+static void
+routerlist_add_nodes_in_family(smartlist_t *sl, const routerinfo_t *router)
+{
+ (void)router;
+ (void)sl;
+ UNIMPLEMENTED_NODELIST();
}
/** Return true iff r is named by some nickname in <b>lst</b>. */
@@ -1373,12 +1396,14 @@ router_in_nickname_smartlist(smartlist_t *lst, const routerinfo_t *r)
/** Return true iff r1 and r2 are in the same family, but not the same
* router. */
int
-routers_in_same_family(const routerinfo_t *r1, const routerinfo_t *r2)
+nodes_in_same_family(const node_t *node1, const node_t *node2)
{
+#if 0
or_options_t *options = get_options();
config_line_t *cl;
- if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2))
+ if (options->EnforceDistinctSubnets &&
+ nodes_in_same_network_family(node1,node2))
return 1;
if (router_in_nickname_smartlist(r1->declared_family, r2) &&
@@ -1390,19 +1415,26 @@ routers_in_same_family(const routerinfo_t *r1, const routerinfo_t *r2)
router_nickname_is_in_list(r2, cl->value))
return 1;
}
+#endif
+ (void)node1;
+ (void)node2;
+ UNIMPLEMENTED_NODELIST();
return 0;
}
+#if 0
/** Given a (possibly NULL) comma-and-whitespace separated list of nicknames,
- * see which nicknames in <b>list</b> name routers in our routerlist, and add
- * the routerinfos for those routers to <b>sl</b>. If <b>must_be_running</b>,
+ * see which nicknames in <b>list</b> name nodes we know about, and add
+ * the nodes for those routers to <b>sl</b>. If <b>must_be_running</b>,
* only include routers that we think are running.
* Warn if any non-Named routers are specified by nickname.
*/
-void
+static void
add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
int must_be_running)
-{
+{ /*XXXX MOVE */
+ /*XXXX this is only used in one place. Can we kill it?*/
+ const node_t *node;
const routerinfo_t *router;
smartlist_t *nickname_list;
int have_dir_info = router_have_minimum_dir_info();
@@ -1424,11 +1456,12 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
log_warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick);
continue;
}
- router = router_get_by_nickname(nick, 1);
+ node = node_get_by_nickname(nick, 1);
+ router = node->ri;
warned = smartlist_string_isin(warned_nicknames, nick);
- if (router) {
- if (!must_be_running || router->is_running) {
- smartlist_add(sl,(void*)router);
+ if (node) {
+ if (!must_be_running || node->is_running) {
+ smartlist_add(sl,(void*)node);
}
} else if (!router_get_consensus_status_by_nickname(nick,1)) {
if (!warned) {
@@ -1441,6 +1474,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
SMARTLIST_FOREACH(nickname_list, char *, nick, tor_free(nick));
smartlist_free(nickname_list);
}
+#endif
/** Return 1 iff any member of the (possibly NULL) comma-separated list
* <b>list</b> is an acceptable nickname or hexdigest for <b>router</b>. Else
@@ -1466,29 +1500,27 @@ router_nickname_is_in_list(const routerinfo_t *router, const char *list)
return v;
}
-/** Add every suitable router from our routerlist to <b>sl</b>, so that
+/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
static void
-router_add_running_routers_to_smartlist(smartlist_t *sl, int allow_invalid,
- int need_uptime, int need_capacity,
- int need_guard)
-{
- if (!routerlist)
- return;
+router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
+ int need_uptime, int need_capacity,
+ int need_guard, int need_desc)
+{ /* XXXX MOVE */
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (!node->is_running ||
+ (!node->is_valid && !allow_invalid))
+ continue;
+ if (need_desc && !(node->ri || (node->rs && node->md)))
+ continue;
+ if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL)
+ continue;
+ if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
+ continue;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- router->purpose == ROUTER_PURPOSE_GENERAL &&
- (router->is_valid || allow_invalid) &&
- !router_is_unreliable(router, need_uptime,
- need_capacity, need_guard)) {
- /* If it's running, and it's suitable according to the
- * other flags we had in mind */
- smartlist_add(sl, router);
- }
- });
+ smartlist_add(sl, (void *)node);
+ } SMARTLIST_FOREACH_END(node);
}
/** Look through the routerlist until we find a router that has my key.
@@ -1511,9 +1543,9 @@ routerlist_find_my_routerinfo(void)
* that allows exit to this address:port, or return NULL if there
* isn't a good one.
*/
-const routerinfo_t *
+const node_t *
router_find_exact_exit_enclave(const char *address, uint16_t port)
-{
+{/*XXXX MOVE*/
uint32_t addr;
struct in_addr in;
tor_addr_t a;
@@ -1524,13 +1556,12 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
tor_addr_from_ipv4h(&a, addr);
- SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, router,
- {
- if (router->addr == addr &&
- router->is_running &&
- compare_tor_addr_to_addr_policy(&a, port, router->exit_policy) ==
+ SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, {
+ if (node_get_addr_ipv4h(node) == addr &&
+ node->is_running &&
+ compare_tor_addr_to_node_policy(&a, port, node) ==
ADDR_POLICY_ACCEPTED)
- return router;
+ return node;
});
return NULL;
}
@@ -1542,14 +1573,14 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
* If <b>need_guard</b>, we require that the router is a possible entry guard.
*/
int
-router_is_unreliable(const routerinfo_t *router, int need_uptime,
- int need_capacity, int need_guard)
+node_is_unreliable(const node_t *node, int need_uptime,
+ int need_capacity, int need_guard)
{
- if (need_uptime && !router->is_stable)
+ if (need_uptime && !node->is_stable)
return 1;
- if (need_capacity && !router->is_fast)
+ if (need_capacity && !node->is_fast)
return 1;
- if (need_guard && !router->is_possible_guard)
+ if (need_guard && !node->is_possible_guard)
return 1;
return 0;
}
@@ -1613,13 +1644,10 @@ kb_to_bytes(uint32_t bw)
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random element of smartlist <b>sl</b> of nodes, weighted by
* the advertised bandwidth of each element using the consensus
* bandwidth weights.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1629,10 +1657,9 @@ kb_to_bytes(uint32_t bw)
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
- bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
int64_t weight_scale;
int64_t rand_bw;
@@ -1727,15 +1754,14 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
bandwidths = tor_malloc_zero(sizeof(double)*smartlist_len(sl));
// Cycle through smartlist and total the bandwidth.
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0, is_me = 0;
double weight = 1;
- if (statuses) {
- routerstatus_t *status = smartlist_get(sl, i);
- is_exit = status->is_exit;
- is_guard = status->is_possible_guard;
- is_dir = (status->dir_port != 0);
- if (!status->has_bandwidth) {
+ is_exit = node->is_exit;
+ is_guard = node->is_possible_guard;
+ is_dir = node_is_dir(node);
+ if (node->rs) {
+ if (!node->rs->has_bandwidth) {
tor_free(bandwidths);
/* This should never happen, unless all the authorites downgrade
* to 0.2.0 or rogue routerstatuses get inserted into our consensus. */
@@ -1744,26 +1770,17 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
"old router selection algorithm.");
return NULL;
}
- this_bw = kb_to_bytes(status->bandwidth);
- if (router_digest_is_me(status->identity_digest))
- is_me = 1;
+ this_bw = kb_to_bytes(node->rs->bandwidth);
+ } else if (node->ri) {
+ /* bridge or other descriptor not in our consensus */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
+ have_unknown = 1;
} else {
- const routerstatus_t *rs;
- routerinfo_t *router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- is_exit = router->is_exit;
- is_guard = router->is_possible_guard;
- is_dir = (router->dir_port != 0);
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else { /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
- have_unknown = 1;
- }
- if (router_digest_is_me(router->cache_info.identity_digest))
- is_me = 1;
+ /* We can't use this one. */
+ continue;
}
+ is_me = router_digest_is_me(node->identity);
+
if (is_guard && is_exit) {
weight = (is_dir ? Wdb*Wd : Wd);
} else if (is_guard) {
@@ -1774,11 +1791,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
weight = (is_dir ? Wmb*Wm : Wm);
}
- bandwidths[i] = weight*this_bw;
+ bandwidths[node_sl_idx] = weight*this_bw;
weighted_bw += weight*this_bw;
if (is_me)
sl_last_weighted_bw_of_me = weight*this_bw;
- }
+ } SMARTLIST_FOREACH_END(node);
/* XXXX022 this is a kludge to expose these values. */
sl_last_total_weighted_bw = weighted_bw;
@@ -1826,12 +1843,9 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random node_t element of smartlist <b>sl</b>, weighted by
* the advertised bandwidth of each element.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1841,12 +1855,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
unsigned int i;
- const routerinfo_t *router;
const routerstatus_t *status=NULL;
int32_t *bandwidths;
int is_exit;
@@ -1888,19 +1901,19 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
guard_bits = bitarray_init_zero(smartlist_len(sl));
/* Iterate over all the routerinfo_t or routerstatus_t, and */
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
/* first, learn what bandwidth we think i has */
int is_known = 1;
int32_t flags = 0;
uint32_t this_bw = 0;
- if (statuses) {
- status = smartlist_get(sl, i);
- if (router_digest_is_me(status->identity_digest))
- me_idx = i;
- router = router_get_by_digest(status->identity_digest);
- is_exit = status->is_exit;
- is_guard = status->is_possible_guard;
- if (status->has_bandwidth) {
+
+ if (router_digest_is_me(node->identity))
+ me_idx = node_sl_idx;
+
+ is_exit = node->is_exit;
+ is_guard = node->is_possible_guard;
+ if (node->rs) {
+ if (node->rs->has_bandwidth) {
this_bw = kb_to_bytes(status->bandwidth);
} else { /* guess */
/* XXX022 once consensuses always list bandwidths, we can take
@@ -1910,27 +1923,11 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
flags |= is_exit ? 2 : 0;
flags |= is_guard ? 4 : 0;
}
- } else {
- const routerstatus_t *rs;
- router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- if (router_digest_is_me(router->cache_info.identity_digest))
- me_idx = i;
- is_exit = router->is_exit;
- is_guard = router->is_possible_guard;
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else if (rs) { /* guess; don't trust the descriptor */
- /* XXX022 once consensuses always list bandwidths, we can take
- * this guessing business out. -RD */
- is_known = 0;
- flags = router->is_fast ? 1 : 0;
- flags |= is_exit ? 2 : 0;
- flags |= is_guard ? 4 : 0;
- } else /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
+ } else if (node->ri) {
+ /* Must be a bridge if we're willing to use it */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
}
+
if (is_exit)
bitarray_set(exit_bits, i);
if (is_guard)
@@ -1950,9 +1947,9 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
total_nonexit_bw += this_bw;
} else {
++n_unknown;
- bandwidths[i] = -flags;
+ bandwidths[node_sl_idx] = -flags;
}
- }
+ } SMARTLIST_FOREACH_END(node);
/* Now, fill in the unknown values. */
if (n_unknown) {
@@ -2094,40 +2091,23 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
return smartlist_get(sl, i);
}
-/** Choose a random element of router list <b>sl</b>, weighted by
- * the advertised bandwidth of each router.
- */
-const routerinfo_t *
-routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- routerinfo_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 0))) {
- return ret;
- } else {
- return smartlist_choose_by_bandwidth(sl, rule, 0);
- }
-}
-
/** Choose a random element of status list <b>sl</b>, weighted by
- * the advertised bandwidth of each status.
- */
-const routerstatus_t *
-routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- /* We are choosing neither exit nor guard here. Weight accordingly. */
- routerstatus_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 1))) {
+ * the advertised bandwidth of each node */
+const node_t *
+node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
+{ /*XXXX MOVE */
+ const node_t *ret;
+ if ((ret = smartlist_choose_node_by_bandwidth_weights(sl, rule))) {
return ret;
} else {
- return smartlist_choose_by_bandwidth(sl, rule, 1);
+ return smartlist_choose_node_by_bandwidth(sl, rule);
}
}
-/** Return a random running router from the routerlist. Never
- * pick a node whose routerinfo is in
- * <b>excludedsmartlist</b>, or whose routerinfo matches <b>excludedset</b>,
+/** Return a random running node from the nodelist. Never
+ * pick a node that is in
+ * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>,
* even if they are the only nodes available.
* If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than
* a minimum uptime, return one of those.
@@ -2139,21 +2119,26 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
* If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if
* picking an exit node, otherwise we weight bandwidths for picking a relay
* node (that is, possibly discounting exit nodes).
+ * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that
+ * have a routerinfo or microdescriptor -- that is, enough info to be
+ * used to build a circuit.
*/
-const routerinfo_t *
+const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
routerset_t *excludedset,
router_crn_flags_t flags)
-{
+{ /* XXXX MOVE */
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
+ const int need_desc = (flags & CRN_NEED_DESC) != 0;
smartlist_t *sl=smartlist_create(),
- *excludednodes=smartlist_create();
- const routerinfo_t *choice = NULL, *r;
+ *excludednodes=smartlist_create();
+ const node_t *choice = NULL;
+ const routerinfo_t *r;
bandwidth_weight_rule_t rule;
tor_assert(!(weight_for_exit && need_guard));
@@ -2163,29 +2148,30 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
/* Exclude relays that allow single hop exit circuits, if the user
* wants to (such relays might be risky) */
if (get_options()->ExcludeSingleHopRelays) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- if (r->allow_single_hop_exits) {
- smartlist_add(excludednodes, r);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ if (node_allows_single_hop_exits(node)) {
+ smartlist_add(excludednodes, node);
});
}
if ((r = routerlist_find_my_routerinfo())) {
- smartlist_add(excludednodes, (void *)r);
- routerlist_add_family(excludednodes, r);
+ const node_t *me = node_get_by_id(r->cache_info.identity_digest);
+ if (me)
+ smartlist_add(excludednodes, (void *)me);
+ routerlist_add_nodes_in_family(excludednodes, r);
}
- router_add_running_routers_to_smartlist(sl, allow_invalid,
- need_uptime, need_capacity,
- need_guard);
+ router_add_running_nodes_to_smartlist(sl, allow_invalid,
+ need_uptime, need_capacity,
+ need_guard, need_desc);
smartlist_subtract(sl,excludednodes);
if (excludedsmartlist)
smartlist_subtract(sl,excludedsmartlist);
if (excludedset)
- routerset_subtract_routers(sl,excludedset);
+ routerset_subtract_nodes(sl,excludedset);
// Always weight by bandwidth
- choice = routerlist_sl_choose_by_bandwidth(sl, rule);
+ choice = node_sl_choose_by_bandwidth(sl, rule);
smartlist_free(sl);
if (!choice && (need_uptime || need_capacity || need_guard)) {
@@ -2208,35 +2194,87 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
return choice;
}
-/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
- * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
- * (which is optionally prefixed with a single dollar sign). Return false if
- * <b>hexdigest</b> is malformed, or it doesn't match. */
-static INLINE int
-hex_digest_matches(const char *hexdigest, const char *identity_digest,
- const char *nickname, int is_named)
+/** Helper: given an extended nickname in <b>hexdigest</b> try to decode it.
+ * Return 0 on success, -1 on failure. Store the result into the
+ * DIGEST_LEN-byte buffer at <b>digest_out</b>, the single character at
+ * <b>nickname_qualifier_char_out</b>, and the MAXNICKNAME_LEN+1-byte buffer
+ * at <b>nickname_out</b>.
+ *
+ * The recognized format is:
+ * HexName = Dollar? HexDigest NamePart?
+ * Dollar = '?'
+ * HexDigest = HexChar*20
+ * HexChar = 'a'..'f' | 'A'..'F' | '0'..'9'
+ * NamePart = QualChar Name
+ * QualChar = '=' | '~'
+ * Name = NameChar*(1..MAX_NICKNAME_LEN)
+ * NameChar = Any ASCII alphanumeric character
+ */
+int
+hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_char_out,
+ char *nickname_out)
{
- char digest[DIGEST_LEN];
size_t len;
+
tor_assert(hexdigest);
if (hexdigest[0] == '$')
++hexdigest;
len = strlen(hexdigest);
- if (len < HEX_DIGEST_LEN)
+ if (len < HEX_DIGEST_LEN) {
+ return -1;
+ } else if (len > HEX_DIGEST_LEN && (hexdigest[HEX_DIGEST_LEN] == '=' ||
+ hexdigest[HEX_DIGEST_LEN] == '~') &&
+ len <= HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN) {
+ *nickname_qualifier_char_out = hexdigest[HEX_DIGEST_LEN];
+ strlcpy(nickname_out, hexdigest+HEX_DIGEST_LEN+1 , MAX_NICKNAME_LEN+1);
+ } else if (len == HEX_DIGEST_LEN) {
+ ;
+ } else {
+ return -1;
+ }
+
+ if (base16_decode(digest_out, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
+ return -1;
+ return 0;
+}
+
+/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
+ * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
+ * (which is optionally prefixed with a single dollar sign). Return false if
+ * <b>hexdigest</b> is malformed, or it doesn't match. */
+static int
+hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
+ const char *nickname, int is_named)
+{
+ char digest[DIGEST_LEN];
+ char nn_char='\0';
+ char nn_buf[MAX_NICKNAME_LEN+1];
+
+ if (hex_digest_nickname_decode(hexdigest, digest, &nn_char, nn_buf) == -1)
return 0;
- else if (len > HEX_DIGEST_LEN &&
- (hexdigest[HEX_DIGEST_LEN] == '=' ||
- hexdigest[HEX_DIGEST_LEN] == '~')) {
- if (strcasecmp(hexdigest+HEX_DIGEST_LEN+1, nickname))
+
+ if (nn_char == '=' || nn_char == '~') {
+ if (strcasecmp(nn_buf, nickname))
return 0;
- if (hexdigest[HEX_DIGEST_LEN] == '=' && !is_named)
+ if (nn_char == '=' && !is_named)
return 0;
}
- if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
- return 0;
- return (!memcmp(digest, identity_digest, DIGEST_LEN));
+ return !memcmp(digest, identity_digest, DIGEST_LEN);
+}
+
+/* Return true iff <b>router</b> is listed as named in the current consensus. */
+static int
+router_is_named(const routerinfo_t *router)
+{
+ const char *digest =
+ networkstatus_get_router_digest_by_nickname(router->nickname);
+
+ return (digest &&
+ !memcmp(digest, router->cache_info.identity_digest, DIGEST_LEN));
}
/** Return true iff the digest of <b>router</b>'s identity key,
@@ -2246,8 +2284,10 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest,
static INLINE int
router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest)
{
- return hex_digest_matches(hexdigest, router->cache_info.identity_digest,
- router->nickname, router->is_named);
+ return hex_digest_nickname_matches(hexdigest,
+ router->cache_info.identity_digest,
+ router->nickname,
+ router_is_named(router));
}
/** Return true if <b>router</b>'s nickname matches <b>nickname</b>
@@ -2269,6 +2309,13 @@ router_nickname_matches(const routerinfo_t *router, const char *nickname)
const routerinfo_t *
router_get_by_nickname(const char *nickname, int warn_if_unnamed)
{
+#if 1
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->ri;
+ else
+ return NULL;
+#else
int maybedigest;
char digest[DIGEST_LEN];
routerinfo_t *best_match=NULL;
@@ -2366,8 +2413,8 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
}
return best_match;
}
-
return NULL;
+#endif
}
/** Try to find a routerinfo for <b>digest</b>. If we don't have one,
@@ -2433,35 +2480,11 @@ hexdigest_to_digest(const char *hexdigest, char *digest)
const routerinfo_t *
router_get_by_hexdigest(const char *hexdigest)
{
- char digest[DIGEST_LEN];
- size_t len;
- const routerinfo_t *ri;
-
- tor_assert(hexdigest);
- if (!routerlist)
+ if (is_legal_nickname(hexdigest))
return NULL;
- if (hexdigest[0]=='$')
- ++hexdigest;
- len = strlen(hexdigest);
- if (hexdigest_to_digest(hexdigest, digest) < 0)
- return NULL;
-
- ri = router_get_by_digest(digest);
- if (ri && len > HEX_DIGEST_LEN) {
- if (hexdigest[HEX_DIGEST_LEN] == '=') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1) ||
- !ri->is_named)
- return NULL;
- } else if (hexdigest[HEX_DIGEST_LEN] == '~') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1))
- return NULL;
- } else {
- return NULL;
- }
- }
-
- return ri;
+ /* It's not a legal nickname, so it must be a hexdigest or nothing. */
+ return router_get_by_nickname(hexdigest, 1);
}
/** As router_get_by_digest,but return a pointer that you're allowed to
@@ -3162,7 +3185,7 @@ routerlist_reset_warnings(void)
void
router_set_status(const char *digest, int up)
{
- routerinfo_t *router;
+ node_t *node;
routerstatus_t *status;
tor_assert(digest);
@@ -3170,15 +3193,21 @@ router_set_status(const char *digest, int up)
if (!memcmp(d->digest, digest, DIGEST_LEN))
d->is_running = up);
- router = router_get_mutable_by_digest(digest);
- if (router) {
- log_debug(LD_DIR,"Marking router '%s/%s' as %s.",
- router->nickname, router->address, up ? "up" : "down");
- if (!up && router_is_me(router) && !we_are_hibernating())
+ node = node_get_mutable_by_id(digest);
+ if (node) {
+#if 0
+ char buf[MAX_VERBOSE_NICKNAME_LEN+1];
+ node_get_verbose_nickname(node,buf);
+ log_debug(LD_DIR,"Marking router %s as %s.",
+ buf, up ? "up" : "down");
+#endif
+ if (!up && node_is_me(node) && !we_are_hibernating())
log_warn(LD_NET, "We just marked ourself as down. Are your external "
"addresses reachable?");
- router->is_running = up;
+ node->is_running = up;
}
+
+ /*XXXX NM don't change routerstatus's is_running. */
status = router_get_mutable_consensus_status_by_id(digest);
if (status && status->is_running != up) {
status->is_running = up;
@@ -3249,12 +3278,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (authdir) {
if (authdir_wants_to_reject_router(router, msg,
- !from_cache && !from_fetch)) {
+ !from_cache && !from_fetch,
+ &authdir_believes_valid)) {
tor_assert(*msg);
routerinfo_free(router);
return ROUTER_AUTHDIR_REJECTS;
}
- authdir_believes_valid = router->is_valid;
} else if (from_fetch) {
/* Only check the descriptor digest against the network statuses when
* we are receiving in response to a fetch. */
@@ -3925,24 +3954,24 @@ routerlist_retry_directory_downloads(time_t now)
update_microdesc_downloads(now);
}
-/** Return 1 if all running sufficiently-stable routers will reject
+/** Return 1 if all running sufficiently-stable routers we can use will reject
* addr:port, return 0 if any might accept it. */
int
-router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime)
-{
+router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+ int need_uptime)
+{ /* XXXX MOVE */
addr_policy_result_t r;
- if (!routerlist) return 1;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- !router_is_unreliable(router, need_uptime, 0, 0)) {
- r = compare_addr_to_addr_policy(addr, port, router->exit_policy);
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (node->is_running &&
+ !node_is_unreliable(node, need_uptime, 0, 0)) {
+
+ r = compare_addr_to_node_policy(addr, port, node);
+
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 0; /* this one could be ok. good enough. */
}
- });
+ } SMARTLIST_FOREACH_END(node);
return 1; /* all will reject. */
}
@@ -4796,7 +4825,7 @@ count_usable_descriptors(int *num_present, int *num_usable,
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
{
- if (in_set && ! routerset_contains_routerstatus(in_set, rs))
+ if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
continue;
if (client_would_use_router(rs, now, options)) {
++*num_usable; /* the consensus says we want it. */
@@ -5437,7 +5466,7 @@ refresh_all_country_info(void)
if (options->_ExcludeExitNodesUnion)
routerset_refresh_countries(options->_ExcludeExitNodesUnion);
- routerlist_refresh_countries();
+ nodelist_refresh_countries();
}
/** Add all members of the set <b>source</b> to <b>target</b>. */
@@ -5487,11 +5516,10 @@ routerset_is_empty(const routerset_t *set)
static int
routerset_contains(const routerset_t *set, const tor_addr_t *addr,
uint16_t orport,
- const char *nickname, const char *id_digest, int is_named,
+ const char *nickname, const char *id_digest,
country_t country)
{
if (!set || !set->list) return 0;
- (void) is_named; /* not supported */
if (nickname && strmap_get_lc(set->names, nickname))
return 4;
if (id_digest && digestmap_get(set->digests, id_digest))
@@ -5519,13 +5547,14 @@ routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
ei->port,
ei->nickname,
ei->identity_digest,
- -1, /*is_named*/
-1 /*country*/);
}
-/** Return true iff <b>ri</b> is in <b>set</b>. */
+/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_router(const routerset_t *set, const routerinfo_t *ri)
+routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -5534,13 +5563,15 @@ routerset_contains_router(const routerset_t *set, const routerinfo_t *ri)
ri->or_port,
ri->nickname,
ri->cache_info.identity_digest,
- ri->is_named,
- ri->country);
+ country);
}
-/** Return true iff <b>rs</b> is in <b>set</b>. */
+/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_routerstatus(const routerset_t *set, const routerstatus_t *rs)
+routerset_contains_routerstatus(const routerset_t *set,
+ const routerstatus_t *rs,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, rs->addr);
@@ -5549,46 +5580,55 @@ routerset_contains_routerstatus(const routerset_t *set, const routerstatus_t *rs
rs->or_port,
rs->nickname,
rs->identity_digest,
- rs->is_named,
- -1);
+ country);
+}
+
+/** Return true iff <b>node</b> is in <b>set</b>. */
+int
+routerset_contains_node(const routerset_t *set, const node_t *node)
+{
+ if (node->rs)
+ return routerset_contains_routerstatus(set, node->rs, node->country);
+ else if (node->ri)
+ return routerset_contains_router(set, node->ri, node->country);
+ else
+ return 0;
}
-/** Add every known routerinfo_t that is a member of <b>routerset</b> to
+/** Add every known node_t that is a member of <b>routerset</b> to
* <b>out</b>. If <b>running_only</b>, only add the running ones. */
void
-routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- int running_only)
-{
+routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ int running_only)
+{ /* XXXX MOVE */
tor_assert(out);
if (!routerset || !routerset->list)
return;
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
- if (routerset_is_list(routerset)) {
+ if (routerset_is_list(routerset)) {
/* No routers are specified by type; all are given by name or digest.
* we can do a lookup in O(len(list)). */
SMARTLIST_FOREACH(routerset->list, const char *, name, {
- const routerinfo_t *router = router_get_by_nickname(name, 1);
- if (router) {
- if (!running_only || router->is_running)
- smartlist_add(out, (void*)router);
+ const node_t *node = node_get_by_nickname(name, 1);
+ if (node) {
+ if (!running_only || node->is_running)
+ smartlist_add(out, (void*)node);
}
});
} else {
/* We need to iterate over the routerlist to get all the ones of the
* right kind. */
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
- if (running_only && !router->is_running)
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (running_only && !node->is_running)
continue;
- if (routerset_contains_router(routerset, router))
- smartlist_add(out, (void*)router);
+ if (routerset_contains_node(routerset, node))
+ smartlist_add(out, (void*)node);
});
}
}
-/** Add to <b>target</b> every routerinfo_t from <b>source</b> except:
+/** Add to <b>target</b> every node_t from <b>source</b> except:
*
* 1) Don't add it if <b>include</b> is non-empty and the relay isn't in
* <b>include</b>; and
@@ -5597,39 +5637,39 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
* 3) If <b>running_only</b>, don't add non-running routers.
*/
void
-routersets_get_disjunction(smartlist_t *target,
+routersets_get_node_disjunction(smartlist_t *target,
const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only)
{
- SMARTLIST_FOREACH(source, routerinfo_t *, router, {
+ SMARTLIST_FOREACH(source, const node_t *, node, {
int include_result;
- if (running_only && !router->is_running)
+ if (running_only && !node->is_running)
continue;
if (!routerset_is_empty(include))
- include_result = routerset_contains_router(include, router);
+ include_result = routerset_contains_node(include, node);
else
include_result = 1;
if (include_result) {
- int exclude_result = routerset_contains_router(exclude, router);
+ int exclude_result = routerset_contains_node(exclude, node);
if (include_result >= exclude_result)
- smartlist_add(target, router);
+ smartlist_add(target, (void*)node);
}
});
}
-/** Remove every routerinfo_t from <b>lst</b> that is in <b>routerset</b>. */
+/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */
void
-routerset_subtract_routers(smartlist_t *lst, const routerset_t *routerset)
-{
+routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset)
+{ /*XXXX MOVE ? */
tor_assert(lst);
if (!routerset)
return;
- SMARTLIST_FOREACH(lst, routerinfo_t *, r, {
- if (routerset_contains_router(routerset, r)) {
+ SMARTLIST_FOREACH(lst, const node_t *, node, {
+ if (routerset_contains_node(routerset, node)) {
//log_debug(LD_DIR, "Subtracting %s",r->nickname);
- SMARTLIST_DEL_CURRENT(lst, r);
+ SMARTLIST_DEL_CURRENT(lst, node);
}
});
}
@@ -5690,18 +5730,23 @@ routerset_free(routerset_t *routerset)
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
-routerinfo_set_country(routerinfo_t *ri)
+node_set_country(node_t *node)
{
- ri->country = geoip_get_country_by_ip(ri->addr);
+ if (node->rs)
+ node->country = geoip_get_country_by_ip(node->rs->addr);
+ else if (node->ri)
+ node->country = geoip_get_country_by_ip(node->ri->addr);
+ else
+ node->country = -1;
}
/** Set the country code of all routers in the routerlist. */
void
-routerlist_refresh_countries(void)
+nodelist_refresh_countries(void) /* MOVE */
{
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
- routerinfo_set_country(ri));
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node,
+ node_set_country(node));
}
/** Determine the routers that are responsible for <b>id</b> (binary) and
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 90975e78e..cda2d2ef5 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -27,33 +27,30 @@ int router_reload_router_list(void);
int authority_cert_dl_looks_uncertain(const char *id_digest);
smartlist_t *router_get_trusted_dir_servers(void);
-const routerstatus_t *router_pick_directory_server(authority_type_t type, int flags);
+const routerstatus_t *router_pick_directory_server(authority_type_t type,
+ int flags);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
-const routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags);
+const routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
+ int flags);
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
void routerlist_add_family(smartlist_t *sl, const routerinfo_t *router);
-int routers_in_same_family(const routerinfo_t *r1, const routerinfo_t *r2);
int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
-void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running);
int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
const routerinfo_t *routerlist_find_my_routerinfo(void);
-const routerinfo_t *router_find_exact_exit_enclave(const char *address,
+const node_t *router_find_exact_exit_enclave(const char *address,
uint16_t port);
-int router_is_unreliable(const routerinfo_t *router, int need_uptime,
+int node_is_unreliable(const node_t *router, int need_uptime,
int need_capacity, int need_guard);
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
-const routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
-const routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
+const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule);
-const routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
+const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
struct routerset_t *excludedset,
router_crn_flags_t flags);
@@ -133,8 +130,9 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
int descriptor_digests);
void routerlist_retry_directory_downloads(time_t now);
-int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime);
+int router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+ int need_uptime);
+
int router_exit_policy_rejects_all(const routerinfo_t *router);
trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
const char *address,
@@ -165,29 +163,31 @@ const char *esc_router_info(const routerinfo_t *router);
void routers_sort_by_identity(smartlist_t *routers);
routerset_t *routerset_new(void);
+void routerset_refresh_countries(routerset_t *rs);
int routerset_parse(routerset_t *target, const char *s,
const char *description);
void routerset_union(routerset_t *target, const routerset_t *source);
int routerset_is_list(const routerset_t *set);
int routerset_needs_geoip(const routerset_t *set);
-int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri);
+int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country);
int routerset_contains_routerstatus(const routerset_t *set,
- const routerstatus_t *rs);
+ const routerstatus_t *rs,
+ country_t country);
int routerset_contains_extendinfo(const routerset_t *set,
const extend_info_t *ei);
-void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- int running_only);
-void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
+int routerset_contains_node(const routerset_t *set, const node_t *node);
+void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ int running_only);
+void routersets_get_node_disjunction(smartlist_t *target,
+ const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only);
-void routerset_subtract_routers(smartlist_t *out,
- const routerset_t *routerset);
+void routerset_subtract_nodes(smartlist_t *out,
+ const routerset_t *routerset);
char *routerset_to_string(const routerset_t *routerset);
-void routerset_refresh_countries(routerset_t *target);
int routerset_equal(const routerset_t *old, const routerset_t *new);
void routerset_free(routerset_t *routerset);
-void routerinfo_set_country(routerinfo_t *ri);
-void routerlist_refresh_countries(void);
void refresh_all_country_info(void);
int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
@@ -201,5 +201,10 @@ void launch_descriptor_downloads(int purpose,
const routerstatus_t *source,
time_t now);
+int hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_out,
+ char *nickname_out);
+
#endif
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index f7e645e8f..b987d6f59 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1344,7 +1344,6 @@ router_parse_entry_from_string(const char *s, const char *end,
tor_assert(tok->n_args >= 5);
router = tor_malloc_zero(sizeof(routerinfo_t));
- router->country = -1;
router->cache_info.routerlist_index = -1;
router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
router->cache_info.signed_descriptor_len = end-s;
@@ -1543,8 +1542,6 @@ router_parse_entry_from_string(const char *s, const char *end,
"router descriptor") < 0)
goto err;
- routerinfo_set_country(router);
-
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;