From fe309e7ad633bee36e175e600f0b9a0ac18cf981 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 28 Sep 2010 13:29:31 -0400 Subject: [PATCH 01/15] Implement a basic node and nodelist type The node_t type is meant to serve two key functions: 1) Abstracting difference between routerinfo_t and microdesc_t so that clients can use microdesc_t instead of routerinfo_t. 2) Being a central place to hold mutable state about nodes formerly held in routerstatus_t and routerinfo_t. This patch implements a nodelist type that holds a node for every router that we would consider using. --- src/common/container.c | 1 - src/or/Makefile.am | 3 +- src/or/main.c | 11 ++ src/or/microdesc.c | 7 + src/or/networkstatus.c | 3 + src/or/nodelist.c | 328 +++++++++++++++++++++++++++++++++++++++++ src/or/nodelist.h | 28 ++++ src/or/or.h | 13 ++ src/or/routerlist.c | 7 + 9 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 src/or/nodelist.c create mode 100644 src/or/nodelist.h diff --git a/src/common/container.c b/src/common/container.c index 72f3470344..0a95f33aad 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -268,7 +268,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2) /** Remove the idxth element of sl; if idx is not the last * element, swap the last element of sl into the idxth space. - * Return the old value of the idxth element. */ void smartlist_del(smartlist_t *sl, int idx) diff --git a/src/or/Makefile.am b/src/or/Makefile.am index 9d8fb663cf..ef9c9903b3 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -21,7 +21,7 @@ libtor_a_SOURCES = buffers.c circuitbuild.c circuitlist.c \ cpuworker.c directory.c dirserv.c dirvote.c \ dns.c dnsserv.c geoip.c hibernate.c main.c $(tor_platform_source) \ microdesc.c \ - networkstatus.c onion.c policies.c \ + networkstatus.c nodelist.c onion.c policies.c \ reasons.c relay.c rendcommon.c rendclient.c rendmid.c \ rendservice.c rephist.c router.c routerlist.c routerparse.c \ $(evdns_source) config_codedigest.c @@ -56,6 +56,7 @@ noinst_HEADERS = buffers.h circuitbuild.h circuitlist.h circuituse.h \ command.h config.h connection_edge.h connection.h connection_or.h \ control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \ dnsserv.h geoip.h hibernate.h main.h microdesc.h networkstatus.h \ + nodelist.h \ ntmain.h onion.h policies.h reasons.h relay.h rendclient.h \ rendcommon.h rendmid.h rendservice.h rephist.h router.h routerlist.h \ routerparse.h or.h eventdns.h eventdns_tor.h micro-revision.i diff --git a/src/or/main.c b/src/or/main.c index ddd5da3643..072fd93a0b 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -33,6 +33,7 @@ #include "main.h" #include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "ntmain.h" #include "onion.h" #include "policies.h" @@ -1039,6 +1040,15 @@ run_scheduled_events(time_t now) */ consider_hibernation(now); + /* XXXX NM REMOVE THIS. XXXX NM XXXX NM XXXX NM*/ + { + static time_t nl_check_time = 0; + if (nl_check_time <= now) { + nodelist_assert_ok(); + nl_check_time = now + 30; + } + } + /* 0b. If we've deferred a signewnym, make sure it gets handled * eventually. */ if (signewnym_is_pending && @@ -2205,6 +2215,7 @@ tor_free_all(int postfork) connection_free_all(); buf_shrink_freelists(1); memarea_clear_freelist(); + nodelist_free_all(); microdesc_free_all(); if (!postfork) { config_free_all(); diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 2752d15c8c..19970aa783 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -5,6 +5,7 @@ #include "config.h" #include "directory.h" #include "microdesc.h" +#include "nodelist.h" #include "routerparse.h" #include "networkstatus.h" #include "routerlist.h" @@ -249,6 +250,12 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, microdesc_cache_rebuild(cache); } + { + networkstatus_t *ns = networkstatus_get_latest_consensus(); + if (ns && ns->flavor == FLAV_MICRODESC) + SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md)); + } + return added; } diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index cba02f3709..c41bcab6ff 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -22,6 +22,7 @@ #include "main.h" #include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "relay.h" #include "router.h" #include "routerlist.h" @@ -1833,6 +1834,8 @@ networkstatus_set_current_consensus(const char *consensus, /* XXXXNM Microdescs: needs a non-ns variant. */ update_consensus_networkstatus_fetch_time(now); + nodelist_set_consensus(current_consensus); + dirvote_recalculate_timing(options, now); routerstatus_list_update_named_server_map(); cell_ewma_set_scale_factor(options, current_consensus); diff --git a/src/or/nodelist.c b/src/or/nodelist.c new file mode 100644 index 0000000000..9c8714c354 --- /dev/null +++ b/src/or/nodelist.c @@ -0,0 +1,328 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "nodelist.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "routerlist.h" + +#include + +static void nodelist_drop_node(node_t *node); +static void node_free(node_t *node); + +/** A nodelist_t holds a node_t object for every router we're "willing to use + * for something". Specifically, it should hold a node_t for every node that + * is currently in the routerlist, or currently in the consensus we're using. + */ +typedef struct nodelist_t { + /* A list of all the nodes. */ + 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 +node_id_hash(const node_t *node) +{ +#if SIZEOF_INT == 4 + const uint32_t *p = (const uint32_t*)node->identity; + return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]; +#elif SIZEOF_INT == 8 + const uint64_t *p = (const uint32_t*)node->identity; + const uint32_t *p32 = (const uint32_t*)node->identity; + return p[0] ^ p[1] ^ p32[4]; +#endif +} + +static INLINE unsigned int +node_id_eq(const node_t *node1, const node_t *node2) +{ + return 0 == memcmp(node1->identity, node2->identity, DIGEST_LEN); +} + +HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq); +HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq, + 0.6, malloc, realloc, free); + +/** The global nodelist. */ +static nodelist_t *the_nodelist=NULL; + +/** Create an empty nodelist if we haven't done so already. */ +static void +init_nodelist(void) +{ + if (PREDICT_UNLIKELY(the_nodelist == NULL)) { + the_nodelist = tor_malloc_zero(sizeof(nodelist_t)); + HT_INIT(nodelist_map, &the_nodelist->nodes_by_id); + the_nodelist->nodes = smartlist_create(); + } +} + +/** Return the node_t whose identity is identity_digest, or NULL + * if no such node exists. */ +node_t * +node_get_by_id(const char *identity_digest) +{ + node_t search, *node; + if (PREDICT_UNLIKELY(the_nodelist == NULL)) + return NULL; + + memcpy(&search.identity, identity_digest, DIGEST_LEN); + node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search); + return node; +} + +/** Internal: return the node_t whose identity_digest is + * identity_digest. If none exists, create a new one, add it to the + * nodelist, and return it. + * + * Requires that the nodelist be initialized. + */ +static node_t * +node_get_or_create(const char *identity_digest) +{ + node_t *node; + + if ((node = node_get_by_id(identity_digest))) + return node; + + node = tor_malloc_zero(sizeof(node_t)); + memcpy(node->identity, identity_digest, DIGEST_LEN); + HT_INSERT(nodelist_map, &the_nodelist->nodes_by_id, node); + + smartlist_add(the_nodelist->nodes, node); + node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1; + + return node; +} + +/** Add ri to the nodelist. */ +node_t * +nodelist_add_routerinfo(routerinfo_t *ri) +{ + node_t *node; + init_nodelist(); + node = node_get_or_create(ri->cache_info.identity_digest); + node->ri = ri; + return node; +} + +/** Set the appropriate node_t to use md as its microdescriptor. + * + * Called when a new microdesc has arrived and the usable consensus flavor + * is "microdesc". + **/ +node_t * +nodelist_add_microdesc(microdesc_t *md) +{ + networkstatus_t *ns = + networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC); + routerstatus_t *rs; + node_t *node; + if (ns == NULL) + return NULL; + init_nodelist(); + + /* Microdescriptors don't carry an identity digest, so we need to figure + * it out by looking up the routerstatus. */ + rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest); + if (rs == NULL) + return NULL; + node = node_get_by_id(rs->identity_digest); + if (node) + node->md = md; + return node; +} + +/** Tell the nodelist that the current usable consensus to ns. + * This makes the nodelist change all of the routerstatus entries for + * the nodes, drop nodes that no longer have enough info to get used, + * and grab microdescriptors into nodes as appropriate. + */ +void +nodelist_set_consensus(networkstatus_t *ns) +{ + init_nodelist(); + + SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node, + node->rs = NULL); + + SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + node_t *node = node_get_or_create(rs->identity_digest); + node->rs = rs; + if (ns->flavor == FLAV_MICRODESC) { + if (node->md == NULL || + 0!=memcmp(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) { + node->md = microdesc_cache_lookup_by_digest256(NULL, + rs->descriptor_digest); + } + } + } SMARTLIST_FOREACH_END(rs); + nodelist_purge(); +} + +/** Helper: return true iff a node has a usable amount of information*/ +static INLINE int +node_is_usable(const node_t *node) +{ + return (node->rs) || (node->ri); +} + +/** Tell the nodelist that md is no longer a microdescriptor for the + * node with identity_digest. */ +void +nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md) +{ + node_t *node = node_get_by_id(identity_digest); + if (node && node->md == md) + node->md = NULL; +} + +/** Tell the nodelist that ri is no longer in the routerlist. */ +void +nodelist_remove_routerinfo(routerinfo_t *ri) +{ + node_t *node = node_get_by_id(ri->cache_info.identity_digest); + if (node && node->ri == ri) { + node->ri = NULL; + if (! node_is_usable(node)) { + nodelist_drop_node(node); + node_free(node); + } + } +} + +/** Remove node from the nodelist. (Asserts that it was there to begin + * with.) */ +static void +nodelist_drop_node(node_t *node) +{ + node_t *tmp; + int idx; + tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node); + tor_assert(tmp == node); + + idx = node->nodelist_idx; + tor_assert(idx >= 0); + + tor_assert(node == smartlist_get(the_nodelist->nodes, idx)); + smartlist_del(the_nodelist->nodes, idx); + if (idx < smartlist_len(the_nodelist->nodes)) { + tmp = smartlist_get(the_nodelist->nodes, idx); + tmp->nodelist_idx = idx; + } + node->nodelist_idx = -1; +} + +/** Release storage held by node */ +static void +node_free(node_t *node) +{ + if (!node) + return; + tor_assert(node->nodelist_idx == -1); + tor_free(node); +} + +/** Remove all entries from the nodelist that don't have enough info to be + * usable for anything. */ +void +nodelist_purge(void) +{ + node_t **iter; + if (PREDICT_UNLIKELY(the_nodelist == NULL)) + return; + + for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) { + node_t *node = *iter; + + if (node_is_usable(node)) { + 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); + node_free(node); + } + } + +} + +/** Release all storage held by the nodelist. */ +void +nodelist_free_all(void) +{ + if (PREDICT_UNLIKELY(the_nodelist == NULL)) + return; + + HT_CLEAR(nodelist_map, &the_nodelist->nodes_by_id); + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + node->nodelist_idx = -1; + node_free(node); + } SMARTLIST_FOREACH_END(node); + + smartlist_free(the_nodelist->nodes); + + tor_free(the_nodelist); +} + +/** Check that the nodelist is internally consistent, and consistent with + * the directory info it's derived from. + */ +void +nodelist_assert_ok(void) +{ + routerlist_t *rl = router_get_routerlist(); + networkstatus_t *ns = networkstatus_get_latest_consensus(); + digestmap_t *dm = digestmap_new(); + + if (!the_nodelist) + return; + + /* 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); + 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); + } 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); + tor_assert(node && node->rs == rs); + tor_assert(0 == memcmp(rs->identity_digest, node->identity, DIGEST_LEN)); + digestmap_set(dm, node->identity, node); + if (ns->flavor == FLAV_MICRODESC) { + /* 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); + tor_assert(md == node->md); + } + } SMARTLIST_FOREACH_END(rs); + } + + /* The nodelist should have no other entries, and its entries should be + * well-formed. */ + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + tor_assert(digestmap_get(dm, node->identity) != NULL); + tor_assert(node_sl_idx == node->nodelist_idx); + } SMARTLIST_FOREACH_END(node); + + tor_assert((long)smartlist_len(the_nodelist->nodes) == + (long)HT_SIZE(&the_nodelist->nodes_by_id)); + + digestmap_free(dm, NULL); +} + diff --git a/src/or/nodelist.h b/src/or/nodelist.h new file mode 100644 index 0000000000..6a77ba6836 --- /dev/null +++ b/src/or/nodelist.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file microdesc.h + * \brief Header file for microdesc.c. + **/ + +#ifndef _TOR_NODELIST_H +#define _TOR_NODELIST_H + +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); + +void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md); +void nodelist_remove_routerinfo(routerinfo_t *ri); +void nodelist_purge(void); + +void nodelist_free_all(void); +void nodelist_assert_ok(void); + +#endif + diff --git a/src/or/or.h b/src/or/or.h index 673a3920cf..e46237c365 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1698,6 +1698,19 @@ typedef struct microdesc_t { * XXX this probably should not stay a string. */ } microdesc_t; +/** DOCDOC */ +typedef struct node_t { + /** 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; + + char identity[DIGEST_LEN]; + microdesc_t *md; + routerinfo_t *ri; + routerstatus_t *rs; +} node_t; + /** How many times will we try to download a router's descriptor before giving * up? */ #define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8 diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 43be8346cc..3c38f9c814 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -24,6 +24,7 @@ #include "main.h" #include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "reasons.h" #include "rendcommon.h" @@ -2783,6 +2784,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) &ri->cache_info); smartlist_add(rl->routers, ri); ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1; + nodelist_add_routerinfo(ri); router_dir_info_changed(); #ifdef DEBUG_ROUTERLIST routerlist_assert_ok(rl); @@ -2890,6 +2892,8 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, time_t now) tor_assert(0 <= idx && idx < smartlist_len(rl->routers)); tor_assert(smartlist_get(rl->routers, idx) == ri); + nodelist_remove_routerinfo(ri); + /* make sure the rephist module knows that it's not running */ rep_hist_note_router_unreachable(ri->cache_info.identity_digest, now); @@ -3011,6 +3015,9 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, tor_assert(0 <= idx && idx < smartlist_len(rl->routers)); tor_assert(smartlist_get(rl->routers, idx) == ri_old); + nodelist_remove_routerinfo(ri_old); + nodelist_add_routerinfo(ri_new); + router_dir_info_changed(); if (idx >= 0) { smartlist_set(rl->routers, idx, ri_new); From d84d20cbb2c8ca8d248378ce21f0d3969f9b5ef8 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 29 Sep 2010 00:38:32 -0400 Subject: [PATCH 02/15] Try to make most routerinfo_t interfaces const --- src/or/circuitbuild.c | 100 +++++++++++++-------------- src/or/circuitbuild.h | 12 ++-- src/or/circuitlist.c | 4 +- src/or/circuituse.c | 13 ++-- src/or/circuituse.h | 2 +- src/or/command.c | 2 +- src/or/connection_edge.c | 10 +-- src/or/connection_edge.h | 3 +- src/or/connection_or.c | 4 +- src/or/control.c | 34 ++++----- src/or/directory.c | 8 +-- src/or/dirserv.c | 44 ++++++------ src/or/dirserv.h | 4 +- src/or/dns.c | 2 +- src/or/main.c | 4 +- src/or/networkstatus.c | 2 +- src/or/policies.c | 2 +- src/or/policies.h | 2 +- src/or/relay.c | 5 +- src/or/rendclient.c | 2 +- src/or/rendservice.c | 8 +-- src/or/rephist.c | 4 +- src/or/router.c | 19 +++-- src/or/router.h | 4 +- src/or/routerlist.c | 146 +++++++++++++++++++++------------------ src/or/routerlist.h | 45 ++++++------ 26 files changed, 251 insertions(+), 234 deletions(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 473b28e872..c8e950883c 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1401,7 +1401,7 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) hop = circ->cpath; do { - routerinfo_t *ri; + const routerinfo_t *ri; routerstatus_t *rs; char *elt; const char *id; @@ -1500,13 +1500,13 @@ void circuit_rep_hist_note_result(origin_circuit_t *circ) { crypt_path_t *hop; - char *prev_digest = NULL; - routerinfo_t *router; + const char *prev_digest = NULL; + const routerinfo_t *router; hop = circ->cpath; if (!hop) /* circuit hasn't started building yet. */ return; if (server_mode(get_options())) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) return; prev_digest = me->cache_info.identity_digest; @@ -1794,7 +1794,7 @@ int inform_testing_reachability(void) { char dirbuf[128]; - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) return 0; control_event_server_status(LOG_NOTICE, @@ -1866,7 +1866,7 @@ int circuit_send_next_onion_skin(origin_circuit_t *circ) { crypt_path_t *hop; - routerinfo_t *router; + const routerinfo_t *router; char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN]; char *onionskin; size_t payload_len; @@ -2479,7 +2479,7 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime, * needed_ports, else return 0. */ static int -router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports) +router_handles_some_port(const routerinfo_t *router, smartlist_t *needed_ports) { int i; uint16_t port; @@ -2523,7 +2523,7 @@ ap_stream_wants_exit_attention(connection_t *conn) * * Return NULL if we can't find any suitable routers. */ -static routerinfo_t * +static const routerinfo_t * choose_good_exit_server_general(routerlist_t *dir, int need_uptime, int need_capacity) { @@ -2533,7 +2533,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, smartlist_t *connections; int best_support = -1; int n_best_support=0; - routerinfo_t *router; + const routerinfo_t *router; or_options_t *options = get_options(); connections = get_connection_array(); @@ -2600,8 +2600,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, } n_supported[i] = 0; /* iterate over connections */ - SMARTLIST_FOREACH(connections, connection_t *, conn, - { + 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)) { @@ -2612,7 +2611,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, // log_fn(LOG_DEBUG,"%s (index %d) would reject this stream.", // router->nickname, i); } - }); /* End looping over connections. */ + } SMARTLIST_FOREACH_END(conn); if (n_pending_connections > 0 && n_supported[i] == 0) { /* Leave best_support at -1 if that's where it is, so we can * distinguish it later. */ @@ -2688,7 +2687,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, (attempt || router_handles_some_port(router, needed_ports))) { // log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.", // try, router->nickname); - smartlist_add(supporting, router); + smartlist_add(supporting, (void*)router); } } @@ -2737,7 +2736,7 @@ 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 routerinfo_t * +static const routerinfo_t * choose_good_exit_server(uint8_t purpose, routerlist_t *dir, int need_uptime, int need_capacity, int is_internal) { @@ -2853,7 +2852,7 @@ 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 */ - routerinfo_t *router = + const routerinfo_t *router = choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime, state->need_capacity, state->is_internal); if (!router) { @@ -2967,14 +2966,14 @@ 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 routerinfo_t * +static const routerinfo_t * choose_good_middle_server(uint8_t purpose, cpath_build_state_t *state, crypt_path_t *head, int cur_len) { int i; - routerinfo_t *r, *choice; + const routerinfo_t *r, *choice; crypt_path_t *cpath; smartlist_t *excluded; or_options_t *options = get_options(); @@ -2985,12 +2984,12 @@ choose_good_middle_server(uint8_t purpose, log_debug(LD_CIRC, "Contemplating intermediate hop: random choice."); excluded = smartlist_create(); if ((r = build_state_get_exit_router(state))) { - smartlist_add(excluded, r); + smartlist_add(excluded, (void*) r); routerlist_add_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))) { - smartlist_add(excluded, r); + smartlist_add(excluded, (void*)r); routerlist_add_family(excluded, r); } } @@ -3014,10 +3013,10 @@ choose_good_middle_server(uint8_t purpose, * If state is NULL, we're choosing a router to serve as an entry * guard, not for any particular circuit. */ -static routerinfo_t * +static const routerinfo_t * choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) { - routerinfo_t *r, *choice; + const routerinfo_t *r, *choice; smartlist_t *excluded; or_options_t *options = get_options(); router_crn_flags_t flags = CRN_NEED_GUARD; @@ -3030,7 +3029,7 @@ 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, r); + smartlist_add(excluded, (void*)r); routerlist_add_family(excluded, r); } if (firewall_is_fascist_or()) { @@ -3042,7 +3041,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) for (i=0; i < smartlist_len(rl->routers); i++) { r = smartlist_get(rl->routers, i); if (!fascist_firewall_allows_or(r)) - smartlist_add(excluded, r); + smartlist_add(excluded, (void*)r); } } /* and exclude current entry guards, if applicable */ @@ -3050,7 +3049,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, { if ((r = router_get_by_digest(entry->identity))) { - smartlist_add(excluded, r); + smartlist_add(excluded, (void*)r); routerlist_add_family(excluded, r); } }); @@ -3107,11 +3106,11 @@ 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 */ - routerinfo_t *r = choose_good_entry_server(purpose, state); + const routerinfo_t *r = choose_good_entry_server(purpose, state); if (r) info = extend_info_from_router(r); } else { - routerinfo_t *r = + const routerinfo_t *r = choose_good_middle_server(purpose, state, circ->cpath, cur_len); if (r) info = extend_info_from_router(r); @@ -3173,7 +3172,7 @@ extend_info_alloc(const char *nickname, const char *digest, /** Allocate and return a new extend_info_t that can be used to build a * circuit to or through the router r. */ extend_info_t * -extend_info_from_router(routerinfo_t *r) +extend_info_from_router(const routerinfo_t *r) { tor_addr_t addr; tor_assert(r); @@ -3212,7 +3211,7 @@ 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. */ -routerinfo_t * +const routerinfo_t * build_state_get_exit_router(cpath_build_state_t *state) { if (!state || !state->chosen_exit) @@ -3241,7 +3240,7 @@ build_state_get_exit_nickname(cpath_build_state_t *state) */ /*XXXX take a routerstatus, not a routerinfo. */ static int -entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri, +entry_guard_set_status(entry_guard_t *e, const routerinfo_t *ri, time_t now, or_options_t *options, const char **reason) { char buf[HEX_DIGEST_LEN+1]; @@ -3317,11 +3316,11 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now) * * If the answer is no, set *msg to an explanation of why. */ -static INLINE routerinfo_t * +static INLINE const routerinfo_t * entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, int assume_reachable, const char **msg) { - routerinfo_t *r; + const routerinfo_t *r; or_options_t *options = get_options(); tor_assert(msg); @@ -3459,10 +3458,10 @@ control_event_guard_deferred(void) * If chosen 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 routerinfo_t * +static const routerinfo_t * add_an_entry_guard(routerinfo_t *chosen, int reset_status) { - routerinfo_t *router; + const routerinfo_t *router; entry_guard_t *entry; if (chosen) { @@ -3652,7 +3651,7 @@ entry_guards_compute_status(or_options_t *options, time_t now) reasons = digestmap_new(); SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { - routerinfo_t *r = router_get_by_digest(entry->identity); + const routerinfo_t *r = router_get_by_digest(entry->identity); const char *reason = NULL; if (entry_guard_set_status(entry, r, now, options, &reason)) changed = 1; @@ -3673,7 +3672,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 = ""; - routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg); + const routerinfo_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", @@ -3790,7 +3789,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded, break; if (e->made_contact) { const char *msg; - routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg); + const routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg); if (r && e->unreachable_since) { refuse_conn = 1; e->can_retry = 1; @@ -3936,20 +3935,21 @@ 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 state is NULL, we're looking for a random * guard (likely a bridge). */ -routerinfo_t * +const routerinfo_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(); - routerinfo_t *chosen_exit = state?build_state_get_exit_router(state) : NULL; - routerinfo_t *r = NULL; + const routerinfo_t *chosen_exit = + state?build_state_get_exit_router(state) : NULL; + const routerinfo_t *r = 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, chosen_exit); + smartlist_add(exit_family, (void*) chosen_exit); routerlist_add_family(exit_family, chosen_exit); consider_exit_family = 1; } @@ -3966,8 +3966,7 @@ choose_random_entry(cpath_build_state_t *state) retry: smartlist_clear(live_entry_guards); - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, - { + 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) @@ -3988,7 +3987,7 @@ choose_random_entry(cpath_build_state_t *state) "No relays from EntryNodes available. Using others."); } } - smartlist_add(live_entry_guards, r); + smartlist_add(live_entry_guards, (void*)r); if (!entry->made_contact) { /* Always start with the first not-yet-contacted entry * guard. Otherwise we might add several new ones, pick @@ -3998,7 +3997,7 @@ choose_random_entry(cpath_build_state_t *state) } if (smartlist_len(live_entry_guards) >= options->NumEntryGuards) break; /* we have enough */ - }); + } SMARTLIST_FOREACH_END(entry); if (entry_list_is_constrained(options)) { /* If we prefer the entry nodes we've got, and we have at least @@ -4308,7 +4307,7 @@ getinfo_helper_entry_guards(control_connection_t *conn, char *c = tor_malloc(len); const char *status = NULL; time_t when = 0; - routerinfo_t *ri; + const routerinfo_t *ri; if (!e->made_contact) { status = "never-connected"; @@ -4398,7 +4397,7 @@ get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port, /** Wrapper around get_configured_bridge_by_addr_port_digest() to look * it up via router descriptor ri. */ static bridge_info_t * -get_configured_bridge_by_routerinfo(routerinfo_t *ri) +get_configured_bridge_by_routerinfo(const routerinfo_t *ri) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, ri->addr); @@ -4408,7 +4407,7 @@ get_configured_bridge_by_routerinfo(routerinfo_t *ri) /** Return 1 if ri is one of our known bridges, else 0. */ int -routerinfo_is_a_configured_bridge(routerinfo_t *ri) +routerinfo_is_a_configured_bridge(const routerinfo_t *ri) { return get_configured_bridge_by_routerinfo(ri) ? 1 : 0; } @@ -4635,9 +4634,8 @@ entries_retry_helper(or_options_t *options, int act) ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL; if (!entry_guards) entry_guards = smartlist_create(); - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, - { - ri = router_get_by_digest(e->identity); + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + ri = router_get_mutable_by_digest(e->identity); if (ri && ri->purpose == purpose) { any_known = 1; if (ri->is_running) @@ -4657,7 +4655,7 @@ entries_retry_helper(or_options_t *options, int act) e->bad_since = 0; } } - }); + } SMARTLIST_FOREACH_END(e); log_debug(LD_DIR, "%d: any_known %d, any_running %d", act, any_known, any_running); return any_known && !any_running; diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 888bf9d255..59e818d5f3 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -44,10 +44,10 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop); 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(routerinfo_t *r); +extend_info_t *extend_info_from_router(const routerinfo_t *r); extend_info_t *extend_info_dup(extend_info_t *info); void extend_info_free(extend_info_t *info); -routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state); +const routerinfo_t *build_state_get_exit_router(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 +55,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); -routerinfo_t *choose_random_entry(cpath_build_state_t *state); +const routerinfo_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, @@ -63,9 +63,9 @@ int getinfo_helper_entry_guards(control_connection_t *conn, const char **errmsg); void clear_bridge_list(void); -int routerinfo_is_a_configured_bridge(routerinfo_t *ri); -void -learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest); +int routerinfo_is_a_configured_bridge(const routerinfo_t *ri); +void learned_router_identity(tor_addr_t *addr, uint16_t port, + const char *digest); void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, char *digest); void retry_bridge_descriptor_fetch_directly(const char *digest); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index fb4b69be0d..96a06c05f2 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -946,9 +946,9 @@ 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; - routerinfo_t *ri1 = router_get_by_digest(info->identity_digest); + const routerinfo_t *ri1 = router_get_by_digest(info->identity_digest); do { - routerinfo_t *ri2; + const routerinfo_t *ri2; if (!memcmp(hop->extend_info->identity_digest, info->identity_digest, DIGEST_LEN)) goto next; diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 3af0fb642d..a2a09bedff 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -43,7 +43,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, int need_uptime, int need_internal, time_t now) { - routerinfo_t *exitrouter; + const routerinfo_t *exitrouter; cpath_build_state_t *build_state; tor_assert(circ); tor_assert(conn); @@ -473,7 +473,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, int min) { circuit_t *circ; - routerinfo_t *exitrouter; + const routerinfo_t *exitrouter; int num=0; time_t now = time(NULL); int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts, @@ -1077,7 +1077,7 @@ static int did_circs_fail_last_period = 0; * details on arguments. */ origin_circuit_t * circuit_launch_by_router(uint8_t purpose, - routerinfo_t *exit, int flags) + const routerinfo_t *exit, int flags) { origin_circuit_t *circ; extend_info_t *info = NULL; @@ -1267,7 +1267,8 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, } } else { /* XXXX022 Duplicates checks in connection_ap_handshake_attach_circuit */ - routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); + const routerinfo_t *router = + router_get_by_nickname(conn->chosen_exit_name, 1); int opt = conn->chosen_exit_optional; if (router && !connection_ap_can_use_exit(conn, router, 0)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, @@ -1317,7 +1318,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, */ if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) { if (conn->chosen_exit_name) { - routerinfo_t *r; + const routerinfo_t *r; int opt = conn->chosen_exit_optional; r = router_get_by_nickname(conn->chosen_exit_name, 1); if (r) { @@ -1571,7 +1572,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) origin_circuit_t *circ=NULL; if (conn->chosen_exit_name) { - routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); + const routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); int opt = conn->chosen_exit_optional; if (!router && !want_onehop) { /* We ran into this warning when trying to extend a circuit to a diff --git a/src/or/circuituse.h b/src/or/circuituse.h index 269b6c5f8f..617685e610 100644 --- a/src/or/circuituse.h +++ b/src/or/circuituse.h @@ -42,7 +42,7 @@ 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, - routerinfo_t *exit, int flags); + const routerinfo_t *exit, 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 ea0bbea1e5..6296c471eb 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -267,7 +267,7 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) } if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) { - routerinfo_t *router = router_get_by_digest(conn->identity_digest); + const routerinfo_t *router = router_get_by_digest(conn->identity_digest); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received CREATE cell (circID %d) for known circ. " "Dropping (age %d).", diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 9627631ad9..2b9ccc5968 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -587,7 +587,7 @@ void circuit_discard_optional_exit_enclaves(extend_info_t *info) { edge_connection_t *edge_conn; - routerinfo_t *r1, *r2; + const routerinfo_t *r1, *r2; smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { @@ -1575,7 +1575,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, return -1; } } else { - routerinfo_t *r; + const routerinfo_t *r; conn->chosen_exit_name = tor_strdup(socks->address); r = router_get_by_nickname(conn->chosen_exit_name, 1); *socks->address = 0; @@ -1631,7 +1631,7 @@ 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 */ - routerinfo_t *r = + const routerinfo_t *r = router_find_exact_exit_enclave(socks->address, socks->port); if (r) { log_info(LD_APP, @@ -2896,7 +2896,7 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn) * this relay, return 0. */ int -connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit, +connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit, int excluded_means_no) { or_options_t *options = get_options(); @@ -2910,7 +2910,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit, * make sure the exit node of the existing circuit matches exactly. */ if (conn->chosen_exit_name) { - routerinfo_t *chosen_exit = + 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)) { diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 0f7bf07809..24ea327ec6 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -47,7 +47,8 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); 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, routerinfo_t *exit, +int connection_ap_can_use_exit(edge_connection_t *conn, + const routerinfo_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 069c3e133d..ee17282e5e 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -438,7 +438,7 @@ connection_or_init_conn_from_address(or_connection_t *conn, const char *id_digest, int started_here) { - routerinfo_t *r = router_get_by_digest(id_digest); + const routerinfo_t *r = router_get_by_digest(id_digest); connection_or_set_identity_digest(conn, id_digest); connection_or_update_token_buckets_helper(conn, 1, get_options()); @@ -1491,7 +1491,7 @@ connection_or_send_netinfo(or_connection_t *conn) { cell_t cell; time_t now = time(NULL); - routerinfo_t *me; + const routerinfo_t *me; int len; char *out; diff --git a/src/or/control.c b/src/or/control.c index 37ebfd88dc..be887f4ffd 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1344,7 +1344,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, } else if (!strcmp(question, "dir-usage")) { *answer = directory_dump_request_log(); } else if (!strcmp(question, "fingerprint")) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) { *errmsg = "No routerdesc known; am I really a server?"; return -1; @@ -1366,8 +1366,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, * NOTE: ri_body is as returned by signed_descriptor_get_body: it might * not be NUL-terminated. */ static char * -munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri, - signed_descriptor_t *ei) +munge_extrainfo_into_routerinfo(const char *ri_body, + const signed_descriptor_t *ri, + const signed_descriptor_t *ei) { char *out = NULL, *outp; int i; @@ -1412,16 +1413,17 @@ getinfo_helper_dir(control_connection_t *control_conn, const char *question, char **answer, const char **errmsg) { + const routerinfo_t *ri; (void) control_conn; if (!strcmpstart(question, "desc/id/")) { - routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/")); + ri = router_get_by_hexdigest(question+strlen("desc/id/")); if (ri) { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len); } } else if (!strcmpstart(question, "desc/name/")) { - routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1); + ri = router_get_by_nickname(question+strlen("desc/name/"),1); if (ri) { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) @@ -1431,7 +1433,7 @@ getinfo_helper_dir(control_connection_t *control_conn, routerlist_t *routerlist = router_get_routerlist(); smartlist_t *sl = smartlist_create(); if (routerlist && routerlist->routers) { - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri, + SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri, { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) @@ -1447,7 +1449,7 @@ getinfo_helper_dir(control_connection_t *control_conn, routerlist_t *routerlist = router_get_routerlist(); smartlist_t *sl = smartlist_create(); if (routerlist && routerlist->routers) { - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri, + SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri, { const char *body = signed_descriptor_get_body(&ri->cache_info); signed_descriptor_t *ei = extrainfo_get_by_descriptor_digest( @@ -1465,8 +1467,8 @@ getinfo_helper_dir(control_connection_t *control_conn, SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); } else if (!strcmpstart(question, "desc-annotations/id/")) { - routerinfo_t *ri = router_get_by_hexdigest(question+ - strlen("desc-annotations/id/")); + ri = router_get_by_hexdigest(question+ + strlen("desc-annotations/id/")); if (ri) { const char *annotations = signed_descriptor_get_annotations(&ri->cache_info); @@ -2168,12 +2170,12 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, routers = smartlist_create(); SMARTLIST_FOREACH(router_nicknames, const char *, n, { - routerinfo_t *r = router_get_by_nickname(n, 1); + const routerinfo_t *r = router_get_by_nickname(n, 1); if (!r) { connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n); goto done; } - smartlist_add(routers, r); + smartlist_add(routers, (void*) r); }); if (!smartlist_len(routers)) { connection_write_str_to_buf("512 No router names provided\r\n", conn); @@ -2186,7 +2188,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, } /* now circ refers to something that is ready to be extended */ - SMARTLIST_FOREACH(routers, routerinfo_t *, r, + SMARTLIST_FOREACH(routers, const routerinfo_t *, r, { extend_info_t *info = extend_info_from_router(r); circuit_append_new_exit(circ, info); @@ -2338,8 +2340,8 @@ 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)) { - routerinfo_t *r = NULL; - char* exit_digest; + const routerinfo_t *r = NULL; + char *exit_digest; if (circ->build_state && circ->build_state->chosen_exit && !tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) { @@ -3175,7 +3177,7 @@ 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) { - routerinfo_t *ri = router_get_by_digest(conn->identity_digest); + const routerinfo_t *ri = router_get_by_digest(conn->identity_digest); if (ri) { tor_assert(len > MAX_VERBOSE_NICKNAME_LEN); router_get_verbose_nickname(name, ri); @@ -3720,7 +3722,7 @@ control_event_guard(const char *nickname, const char *digest, { char buf[MAX_VERBOSE_NICKNAME_LEN+1]; - routerinfo_t *ri = router_get_by_digest(digest); + const routerinfo_t *ri = router_get_by_digest(digest); if (ri) { router_get_verbose_nickname(buf, ri); } else { diff --git a/src/or/directory.c b/src/or/directory.c index 657b210b5f..0b40b29eb3 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -219,7 +219,7 @@ dir_conn_purpose_to_string(int purpose) int router_supports_extrainfo(const char *identity_digest, int is_authority) { - routerinfo_t *ri = router_get_by_digest(identity_digest); + const routerinfo_t *ri = router_get_by_digest(identity_digest); if (ri) { if (ri->caches_extra_info) @@ -400,7 +400,7 @@ 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. */ - routerinfo_t *ri = choose_random_entry(NULL); + const routerinfo_t *ri = choose_random_entry(NULL); if (ri) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, ri->addr); @@ -522,7 +522,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status, time_t if_modified_since, const rend_data_t *rend_query) { - routerinfo_t *router; + const routerinfo_t *router; char address_buf[INET_NTOA_BUF_LEN+1]; struct in_addr in; const char *address; @@ -590,7 +590,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn) { if (conn->requested_resource && !strcmpstart(conn->requested_resource,"authority")) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (me && router_digest_is_me(conn->identity_digest) && tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/ diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 75e3e86109..148147b149 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -74,7 +74,8 @@ dirserv_get_status_impl(const char *fp, const char *nickname, const char *platform, const char *contact, const char **msg, int should_log); static void clear_cached_dir(cached_dir_t *d); -static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp, +static const signed_descriptor_t *get_signed_descriptor_by_fp( + const char *fp, int extrainfo, time_t publish_cutoff); static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg); @@ -707,7 +708,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) * from this server. (We do this here and not in router_add_to_routerlist * because we want to be able to accept the newest router descriptor that * another authority has, so we all converge on the same one.) */ - ri_old = router_get_by_digest(ri->cache_info.identity_digest); + ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest); if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on && router_differences_are_cosmetic(ri_old, ri) && !router_is_me(ri)) { @@ -767,7 +768,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei, const char **msg) { - routerinfo_t *ri; + const routerinfo_t *ri; int r; tor_assert(msg); *msg = NULL; @@ -1151,7 +1152,7 @@ dirserv_dump_directory_to_string(char **dir_out, int directory_fetches_from_authorities(or_options_t *options) { - routerinfo_t *me; + const routerinfo_t *me; uint32_t addr; int refuseunknown; if (options->FetchDirInfoEarly) @@ -2026,7 +2027,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, } if (format != NS_V2) { - routerinfo_t* desc = router_get_by_digest(rs->identity_digest); + const routerinfo_t* desc = router_get_by_digest(rs->identity_digest); uint32_t bw; if (format != NS_CONTROL_PORT) { @@ -2879,7 +2880,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, if (!strcmp(key,"authority")) { if (authdir_mode_v2(get_options())) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (me) smartlist_add(result, tor_memdup(me->cache_info.identity_digest, DIGEST_LEN)); @@ -2965,7 +2966,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, smartlist_add(fps_out, tor_memdup(r->cache_info.identity_digest, DIGEST_LEN))); } else if (!strcmp(key, "authority")) { - routerinfo_t *ri = router_get_my_routerinfo(); + const routerinfo_t *ri = router_get_my_routerinfo(); if (ri) smartlist_add(fps_out, tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN)); @@ -2985,8 +2986,8 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, if (for_unencrypted_conn) { /* Remove anything that insists it not be sent unencrypted. */ - SMARTLIST_FOREACH(fps_out, char *, cp, { - signed_descriptor_t *sd; + SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) { + const signed_descriptor_t *sd; if (by_id) sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0); else if (is_extrainfo) @@ -2997,7 +2998,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, tor_free(cp); SMARTLIST_DEL_CURRENT(fps_out, cp); } - }); + } SMARTLIST_FOREACH_END(cp); } if (!smartlist_len(fps_out)) { @@ -3036,9 +3037,9 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r, smartlist_add(descs_out, &(r->cache_info))); } else if (!strcmp(key, "/tor/server/authority")) { - routerinfo_t *ri = router_get_my_routerinfo(); + const routerinfo_t *ri = router_get_my_routerinfo(); if (ri) - smartlist_add(descs_out, &(ri->cache_info)); + smartlist_add(descs_out, (void*) &(ri->cache_info)); } else if (!strcmpstart(key, "/tor/server/d/")) { smartlist_t *digests = smartlist_create(); key += strlen("/tor/server/d/"); @@ -3062,17 +3063,17 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, { if (router_digest_is_me(d)) { /* make sure desc_routerinfo exists */ - routerinfo_t *ri = router_get_my_routerinfo(); + const routerinfo_t *ri = router_get_my_routerinfo(); if (ri) - smartlist_add(descs_out, &(ri->cache_info)); + smartlist_add(descs_out, (void*) &(ri->cache_info)); } else { - routerinfo_t *ri = router_get_by_digest(d); + const routerinfo_t *ri = router_get_by_digest(d); /* Don't actually serve a descriptor that everyone will think is * expired. This is an (ugly) workaround to keep buggy 0.1.1.10 * Tors from downloading descriptors that they will throw away. */ if (ri && ri->cache_info.published_on > cutoff) - smartlist_add(descs_out, &(ri->cache_info)); + smartlist_add(descs_out, (void*) &(ri->cache_info)); } }); SMARTLIST_FOREACH(digests, char *, d, tor_free(d)); @@ -3130,7 +3131,8 @@ dirserv_orconn_tls_done(const char *address, * an upload or a download. Used to decide whether to relaunch reachability * testing for the server. */ int -dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old) +dirserv_should_launch_reachability_test(const routerinfo_t *ri, + const routerinfo_t *ri_old) { if (!authdir_mode_handles_descs(get_options(), ri->purpose)) return 0; @@ -3254,7 +3256,7 @@ dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff) * its extra-info document if extrainfo is true. Return * NULL if not found or if the descriptor is older than * publish_cutoff. */ -static signed_descriptor_t * +static const signed_descriptor_t * get_signed_descriptor_by_fp(const char *fp, int extrainfo, time_t publish_cutoff) { @@ -3264,7 +3266,7 @@ get_signed_descriptor_by_fp(const char *fp, int extrainfo, else return &(router_get_my_routerinfo()->cache_info); } else { - routerinfo_t *ri = router_get_by_digest(fp); + const routerinfo_t *ri = router_get_by_digest(fp); if (ri && ri->cache_info.published_on > publish_cutoff) { if (extrainfo) @@ -3332,7 +3334,7 @@ dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, tor_assert(fps); if (is_serverdescs) { int n = smartlist_len(fps); - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); result = (me?me->cache_info.signed_descriptor_len:2048) * n; if (compressed) result /= 2; /* observed compressibility is between 35 and 55%. */ @@ -3399,7 +3401,7 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) { const char *body; char *fp = smartlist_pop_last(conn->fingerprint_stack); - signed_descriptor_t *sd = NULL; + const signed_descriptor_t *sd = NULL; if (by_fp) { sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff); } else { diff --git a/src/or/dirserv.h b/src/or/dirserv.h index 94e4e811d6..9be4935a13 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -99,8 +99,8 @@ void dirserv_orconn_tls_done(const char *address, uint16_t or_port, const char *digest_rcvd, int as_advertised); -int dirserv_should_launch_reachability_test(routerinfo_t *ri, - routerinfo_t *ri_old); +int dirserv_should_launch_reachability_test(const routerinfo_t *ri, + const routerinfo_t *ri_old); 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, diff --git a/src/or/dns.c b/src/or/dns.c index 4e319b7d83..83d47914e4 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -668,7 +668,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, cached_resolve_t *resolve; cached_resolve_t search; pending_connection_t *pending_connection; - routerinfo_t *me; + const routerinfo_t *me; tor_addr_t addr; time_t now = time(NULL); uint8_t is_reverse = 0; diff --git a/src/or/main.c b/src/or/main.c index 072fd93a0b..4c305ca9b8 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1273,7 +1273,7 @@ run_scheduled_events(time_t now) /* If we haven't checked for 12 hours and our bandwidth estimate is * low, do another bandwidth test. This is especially important for * bridges, since they might go long periods without much use. */ - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (time_to_recheck_bandwidth && me && me->bandwidthcapacity < me->bandwidthrate && me->bandwidthcapacity < 51200) { @@ -1474,7 +1474,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) (stats_n_seconds_working+seconds_elapsed) / TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) { /* every 20 minutes, check and complain if necessary */ - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (me && !check_whether_orport_reachable()) { log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that " "its ORPort is reachable. Please check your firewalls, ports, " diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index c41bcab6ff..3451a2d402 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -2083,7 +2083,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, /* 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 = - router_get_by_digest(router->cache_info.identity_digest); + router_get_mutable_by_digest(router->cache_info.identity_digest); if (old_router != router) { router->needs_retest_if_added = dirserv_should_launch_reachability_test(router, old_router); diff --git a/src/or/policies.c b/src/or/policies.c index 4fd0904152..b4d359599c 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -261,7 +261,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port) /** Return true iff we think our firewall will let us make an OR connection to * ri. */ int -fascist_firewall_allows_or(routerinfo_t *ri) +fascist_firewall_allows_or(const routerinfo_t *ri) { /* XXXX proposal 118 */ tor_addr_t addr; diff --git a/src/or/policies.h b/src/or/policies.h index dd46f4de9c..4a34745709 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -19,7 +19,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(routerinfo_t *ri); +int fascist_firewall_allows_or(const routerinfo_t *ri); 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); diff --git a/src/or/relay.c b/src/or/relay.c index f9a44cf16a..48948f0011 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -720,11 +720,12 @@ connection_ap_process_end_not_open( if (rh->length > 0 && edge_reason_is_retriable(reason) && !connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */ ) { + const char *chosen_exit_digest = + circ->build_state->chosen_exit->identity_digest; 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_by_digest(circ->build_state->chosen_exit->identity_digest); + exitrouter = router_get_mutable_by_digest(chosen_exit_digest); switch (reason) { case END_STREAM_REASON_EXITPOLICY: if (rh->length >= 5) { diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 68abb886a8..67bd55a291 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -738,7 +738,7 @@ rend_client_get_random_intro(const rend_data_t *rend_query) int i; rend_cache_entry_t *entry; rend_intro_point_t *intro; - routerinfo_t *router; + const routerinfo_t *router; if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) { log_warn(LD_REND, diff --git a/src/or/rendservice.c b/src/or/rendservice.c index b0d791529b..f6769d5580 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1001,7 +1001,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request, } else { char *rp_nickname; size_t nickname_field_len; - routerinfo_t *router; + const routerinfo_t *router; int version; if (*buf == 1) { rp_nickname = buf+1; @@ -1754,7 +1754,7 @@ void rend_services_introduce(void) { int i,j,r; - routerinfo_t *router; + const routerinfo_t *router; rend_service_t *service; rend_intro_point_t *intro; int changed, prev_intro_nodes; @@ -1807,7 +1807,7 @@ rend_services_introduce(void) changed = 1; } if (router) - smartlist_add(intro_routers, router); + smartlist_add(intro_routers, (void*)router); } /* We have enough intro points, and the intro points we thought we had were @@ -1848,7 +1848,7 @@ rend_services_introduce(void) break; } changed = 1; - smartlist_add(intro_routers, router); + smartlist_add(intro_routers, (void*)router); intro = tor_malloc_zero(sizeof(rend_intro_point_t)); intro->extend_info = extend_info_from_router(router); intro->intro_key = crypto_new_pk_env(); diff --git a/src/or/rephist.c b/src/or/rephist.c index 056fc5cc12..d998e87ca6 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -579,7 +579,7 @@ rep_hist_dump_stats(time_t now, int severity) size_t len; int ret; unsigned long upt, downt; - routerinfo_t *r; + const routerinfo_t *r; rep_history_clean(now - get_options()->RephistTrackTime); @@ -871,7 +871,7 @@ rep_hist_get_router_stability_doc(time_t now) } DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) { - routerinfo_t *ri; + const routerinfo_t *ri; char dbuf[BASE64_DIGEST_LEN+1]; char header_buf[512]; char *info; diff --git a/src/or/router.c b/src/or/router.c index 8b3a1849ac..dfb2f06d4c 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -773,7 +773,7 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port) void consider_testing_reachability(int test_or, int test_dir) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); int orport_reachable = check_whether_orport_reachable(); tor_addr_t addr; if (!me) @@ -808,7 +808,7 @@ void router_orport_found_reachable(void) { if (!can_reach_or_port) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " "the outside. Excellent.%s", get_options()->_PublishServerDescriptor != NO_AUTHORITY ? @@ -831,7 +831,7 @@ void router_dirport_found_reachable(void) { if (!can_reach_dir_port) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable " "from the outside. Excellent."); can_reach_dir_port = 1; @@ -1093,7 +1093,7 @@ static int desc_needs_upload = 0; void router_upload_dir_desc_to_dirservers(int force) { - routerinfo_t *ri; + const routerinfo_t *ri; extrainfo_t *ei; char *msg; size_t desc_len, extra_len = 0, total_len; @@ -1186,7 +1186,7 @@ router_extrainfo_digest_is_me(const char *digest) /** A wrapper around router_digest_is_me(). */ int -router_is_me(routerinfo_t *router) +router_is_me(const routerinfo_t *router) { return router_digest_is_me(router->cache_info.identity_digest); } @@ -1205,7 +1205,7 @@ router_fingerprint_is_me(const char *fp) /** Return a routerinfo for this OR, rebuilding a fresh one if * necessary. Return NULL on error, or if called on an OP. */ -routerinfo_t * +const routerinfo_t * router_get_my_routerinfo(void) { if (!server_mode(get_options())) @@ -1348,9 +1348,8 @@ router_rebuild_descriptor(int force) ri->declared_family = smartlist_create(); smartlist_split_string(family, options->MyFamily, ",", SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH(family, char *, name, - { - routerinfo_t *member; + SMARTLIST_FOREACH_BEGIN(family, char *, name) { + const routerinfo_t *member; if (!strcasecmp(name, options->Nickname)) member = ri; else @@ -1386,7 +1385,7 @@ router_rebuild_descriptor(int force) smartlist_string_remove(warned_nonexistent_family, name); } tor_free(name); - }); + } SMARTLIST_FOREACH_END(name); /* remove duplicates from the list */ smartlist_sort_strings(ri->declared_family); diff --git a/src/or/router.h b/src/or/router.h index c17fc78bd0..13ea6f80e6 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -62,12 +62,12 @@ void router_new_address_suggestion(const char *suggestion, const dir_connection_t *d_conn); int router_compare_to_my_exit_policy(edge_connection_t *conn); int router_my_exit_policy_is_reject_star(void); -routerinfo_t *router_get_my_routerinfo(void); +const routerinfo_t *router_get_my_routerinfo(void); extrainfo_t *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); int router_digest_is_me(const char *digest); int router_extrainfo_digest_is_me(const char *digest); -int router_is_me(routerinfo_t *router); +int router_is_me(const routerinfo_t *router); int router_fingerprint_is_me(const char *fp); int router_pick_published_address(or_options_t *options, uint32_t *addr); int router_rebuild_descriptor(int force); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 3c38f9c814..d2edeadc9f 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -44,12 +44,14 @@ static routerstatus_t *router_pick_directory_server_impl( static routerstatus_t *router_pick_trusteddirserver_impl( authority_type_t auth, int flags, int *n_busy_out); static void mark_all_trusteddirservers_up(void); -static int router_nickname_matches(routerinfo_t *router, const char *nickname); +static int router_nickname_matches(const routerinfo_t *router, + const char *nickname); static void trusted_dir_server_free(trusted_dir_server_t *ds); static int signed_desc_digest_is_recognized(signed_descriptor_t *desc); static void update_router_have_minimum_dir_info(void); -static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc, - int with_annotations); +static const char *signed_descriptor_get_body_impl( + const signed_descriptor_t *desc, + int with_annotations); static void list_pending_downloads(digestmap_t *result, int purpose, const char *prefix); @@ -599,7 +601,7 @@ router_should_rebuild_store(desc_store_t *store) /** Return the desc_store_t in rl that should be used to store * sd. */ static INLINE desc_store_t * -desc_get_store(routerlist_t *rl, signed_descriptor_t *sd) +desc_get_store(routerlist_t *rl, const signed_descriptor_t *sd) { if (sd->is_extrainfo) return &rl->extrainfo_store; @@ -957,7 +959,7 @@ int router_get_my_share_of_directory_requests(double *v2_share_out, double *v3_share_out) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); routerstatus_t *rs; const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL; *v2_share_out = *v3_share_out = 0.0; @@ -1167,7 +1169,7 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags, { smartlist_t *direct, *tunnel; smartlist_t *overloaded_direct, *overloaded_tunnel; - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); routerstatus_t *result; time_t now = time(NULL); const int requireother = ! (flags & PDS_ALLOW_SELF); @@ -1299,7 +1301,7 @@ router_reset_status_download_failures(void) /** Return true iff router1 and router2 have the same /16 network. */ static INLINE int -routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2) +routers_in_same_network_family(const routerinfo_t *r1, const routerinfo_t *r2) { return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000); } @@ -1309,7 +1311,7 @@ routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2) * Add each of them to sl. */ static void -routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router) +routerlist_add_network_family(smartlist_t *sl, const routerinfo_t *router) { SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r, { @@ -1323,9 +1325,9 @@ routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router) * or pick more than one relay from a family for our entry guard list. */ void -routerlist_add_family(smartlist_t *sl, routerinfo_t *router) +routerlist_add_family(smartlist_t *sl, const routerinfo_t *router) { - routerinfo_t *r; + const routerinfo_t *r; config_line_t *cl; or_options_t *options = get_options(); @@ -1336,8 +1338,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router) if (router->declared_family) { /* Add every r such that router declares familyness with r, and r * declares familyhood with router. */ - SMARTLIST_FOREACH(router->declared_family, const char *, n, - { + SMARTLIST_FOREACH_BEGIN(router->declared_family, const char *, n) { if (!(r = router_get_by_nickname(n, 0))) continue; if (!r->declared_family) @@ -1345,9 +1346,9 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router) SMARTLIST_FOREACH(r->declared_family, const char *, n2, { if (router_nickname_matches(router, n2)) - smartlist_add(sl, r); + smartlist_add(sl, (void*)r); }); - }); + } SMARTLIST_FOREACH_END(n); } /* If the user declared any families locally, honor those too. */ @@ -1360,7 +1361,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router) /** Return true iff r is named by some nickname in lst. */ static INLINE int -router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r) +router_in_nickname_smartlist(smartlist_t *lst, const routerinfo_t *r) { if (!lst) return 0; SMARTLIST_FOREACH(lst, const char *, name, @@ -1372,7 +1373,7 @@ router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r) /** Return true iff r1 and r2 are in the same family, but not the same * router. */ int -routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2) +routers_in_same_family(const routerinfo_t *r1, const routerinfo_t *r2) { or_options_t *options = get_options(); config_line_t *cl; @@ -1402,7 +1403,7 @@ void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int must_be_running) { - routerinfo_t *router; + const routerinfo_t *router; smartlist_t *nickname_list; int have_dir_info = router_have_minimum_dir_info(); @@ -1417,7 +1418,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, smartlist_split_string(nickname_list, list, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH(nickname_list, const char *, nick, { + SMARTLIST_FOREACH_BEGIN(nickname_list, const char *, nick) { int warned; if (!is_legal_nickname_or_hexdigest(nick)) { log_warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick); @@ -1427,7 +1428,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, warned = smartlist_string_isin(warned_nicknames, nick); if (router) { if (!must_be_running || router->is_running) { - smartlist_add(sl,router); + smartlist_add(sl,(void*)router); } } else if (!router_get_consensus_status_by_nickname(nick,1)) { if (!warned) { @@ -1436,7 +1437,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, smartlist_add(warned_nicknames, tor_strdup(nick)); } } - }); + } SMARTLIST_FOREACH_END(nick); SMARTLIST_FOREACH(nickname_list, char *, nick, tor_free(nick)); smartlist_free(nickname_list); } @@ -1446,7 +1447,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, * return 0. */ int -router_nickname_is_in_list(routerinfo_t *router, const char *list) +router_nickname_is_in_list(const routerinfo_t *router, const char *list) { smartlist_t *nickname_list; int v = 0; @@ -1492,7 +1493,7 @@ router_add_running_routers_to_smartlist(smartlist_t *sl, int allow_invalid, /** Look through the routerlist until we find a router that has my key. Return it. */ -routerinfo_t * +const routerinfo_t * routerlist_find_my_routerinfo(void) { if (!routerlist) @@ -1510,7 +1511,7 @@ routerlist_find_my_routerinfo(void) * that allows exit to this address:port, or return NULL if there * isn't a good one. */ -routerinfo_t * +const routerinfo_t * router_find_exact_exit_enclave(const char *address, uint16_t port) { uint32_t addr; @@ -1523,7 +1524,7 @@ router_find_exact_exit_enclave(const char *address, uint16_t port) tor_addr_from_ipv4h(&a, addr); - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, + SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, router, { if (router->addr == addr && router->is_running && @@ -1541,7 +1542,7 @@ router_find_exact_exit_enclave(const char *address, uint16_t port) * If need_guard, we require that the router is a possible entry guard. */ int -router_is_unreliable(routerinfo_t *router, int need_uptime, +router_is_unreliable(const routerinfo_t *router, int need_uptime, int need_capacity, int need_guard) { if (need_uptime && !router->is_stable) @@ -1556,7 +1557,7 @@ router_is_unreliable(routerinfo_t *router, int need_uptime, /** Return the smaller of the router's configured BandwidthRate * and its advertised capacity. */ uint32_t -router_get_advertised_bandwidth(routerinfo_t *router) +router_get_advertised_bandwidth(const routerinfo_t *router) { if (router->bandwidthcapacity < router->bandwidthrate) return router->bandwidthcapacity; @@ -1570,7 +1571,7 @@ router_get_advertised_bandwidth(routerinfo_t *router) /** Return the smaller of the router's configured BandwidthRate * and its advertised capacity, capped by max-believe-bw. */ uint32_t -router_get_advertised_bandwidth_capped(routerinfo_t *router) +router_get_advertised_bandwidth_capped(const routerinfo_t *router) { uint32_t result = router->bandwidthcapacity; if (result > router->bandwidthrate) @@ -1845,8 +1846,8 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, int statuses) { unsigned int i; - routerinfo_t *router; - routerstatus_t *status=NULL; + const routerinfo_t *router; + const routerstatus_t *status=NULL; int32_t *bandwidths; int is_exit; int is_guard; @@ -2096,7 +2097,7 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, /** Choose a random element of router list sl, weighted by * the advertised bandwidth of each router. */ -routerinfo_t * +const routerinfo_t * routerlist_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule) { @@ -2139,7 +2140,7 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, * picking an exit node, otherwise we weight bandwidths for picking a relay * node (that is, possibly discounting exit nodes). */ -routerinfo_t * +const routerinfo_t * router_choose_random_node(smartlist_t *excludedsmartlist, routerset_t *excludedset, router_crn_flags_t flags) @@ -2152,7 +2153,7 @@ router_choose_random_node(smartlist_t *excludedsmartlist, smartlist_t *sl=smartlist_create(), *excludednodes=smartlist_create(); - routerinfo_t *choice = NULL, *r; + const routerinfo_t *choice = NULL, *r; bandwidth_weight_rule_t rule; tor_assert(!(weight_for_exit && need_guard)); @@ -2170,7 +2171,7 @@ router_choose_random_node(smartlist_t *excludedsmartlist, } if ((r = routerlist_find_my_routerinfo())) { - smartlist_add(excludednodes, r); + smartlist_add(excludednodes, (void *)r); routerlist_add_family(excludednodes, r); } @@ -2243,7 +2244,7 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest, * optionally prefixed with a single dollar sign). Return false if * hexdigest is malformed, or it doesn't match. */ static INLINE int -router_hex_digest_matches(routerinfo_t *router, const char *hexdigest) +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); @@ -2254,7 +2255,7 @@ router_hex_digest_matches(routerinfo_t *router, const char *hexdigest) * matches a hexadecimal value stored in nickname. Return * false otherwise. */ static int -router_nickname_matches(routerinfo_t *router, const char *nickname) +router_nickname_matches(const routerinfo_t *router, const char *nickname) { if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname)) return 1; @@ -2265,7 +2266,7 @@ router_nickname_matches(routerinfo_t *router, const char *nickname) * nickname or (case-sensitive) hexadecimal key digest is * nickname. Return NULL if no such router is known. */ -routerinfo_t * +const routerinfo_t * router_get_by_nickname(const char *nickname, int warn_if_unnamed) { int maybedigest; @@ -2376,7 +2377,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) int router_digest_version_as_new_as(const char *digest, const char *cutoff) { - routerinfo_t *router = router_get_by_digest(digest); + const routerinfo_t *router = router_get_by_digest(digest); if (!router) return 1; return tor_version_as_new_as(router->platform, cutoff); @@ -2430,12 +2431,12 @@ hexdigest_to_digest(const char *hexdigest, char *digest) /** Return the router in our routerlist whose hexadecimal key digest * is hexdigest. Return NULL if no such router is known. */ -routerinfo_t * +const routerinfo_t * router_get_by_hexdigest(const char *hexdigest) { char digest[DIGEST_LEN]; size_t len; - routerinfo_t *ri; + const routerinfo_t *ri; tor_assert(hexdigest); if (!routerlist) @@ -2464,10 +2465,10 @@ router_get_by_hexdigest(const char *hexdigest) return ri; } -/** Return the router in our routerlist whose 20-byte key digest - * is digest. Return NULL if no such router is known. */ +/** As router_get_by_digest,but return a pointer that you're allowed to + * modify */ routerinfo_t * -router_get_by_digest(const char *digest) +router_get_mutable_by_digest(const char *digest) { tor_assert(digest); @@ -2478,6 +2479,14 @@ router_get_by_digest(const char *digest) return rimap_get(routerlist->identity_map, digest); } +/** Return the router in our routerlist whose 20-byte key digest + * is digest. Return NULL if no such router is known. */ +const routerinfo_t * +router_get_by_digest(const char *digest) +{ + return router_get_mutable_by_digest(digest); +} + /** Return the router in our routerlist whose 20-byte descriptor * is digest. Return NULL if no such router is known. */ signed_descriptor_t * @@ -2528,7 +2537,7 @@ extrainfo_get_by_descriptor_digest(const char *digest) * The caller must not free the string returned. */ static const char * -signed_descriptor_get_body_impl(signed_descriptor_t *desc, +signed_descriptor_get_body_impl(const signed_descriptor_t *desc, int with_annotations) { const char *r = NULL; @@ -2577,7 +2586,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc, * The caller must not free the string returned. */ const char * -signed_descriptor_get_body(signed_descriptor_t *desc) +signed_descriptor_get_body(const signed_descriptor_t *desc) { return signed_descriptor_get_body_impl(desc, 0); } @@ -2585,7 +2594,7 @@ signed_descriptor_get_body(signed_descriptor_t *desc) /** As signed_descriptor_get_body(), but points to the beginning of the * annotations section rather than the beginning of the descriptor. */ const char * -signed_descriptor_get_annotations(signed_descriptor_t *desc) +signed_descriptor_get_annotations(const signed_descriptor_t *desc) { return signed_descriptor_get_body_impl(desc, 1); } @@ -2770,7 +2779,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) routerinfo_t *ri_old; { /* XXXX Remove if this slows us down. */ - routerinfo_t *ri_generated = router_get_my_routerinfo(); + const routerinfo_t *ri_generated = router_get_my_routerinfo(); tor_assert(ri_generated != ri); } tor_assert(ri->cache_info.routerlist_index == -1); @@ -2852,7 +2861,7 @@ routerlist_insert_old(routerlist_t *rl, routerinfo_t *ri) { { /* XXXX remove this code if it slows us down. */ - routerinfo_t *ri_generated = router_get_my_routerinfo(); + const routerinfo_t *ri_generated = router_get_my_routerinfo(); tor_assert(ri_generated != ri); } tor_assert(ri->cache_info.routerlist_index == -1); @@ -3005,7 +3014,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, extrainfo_t *ei_tmp; { /* XXXX Remove this if it turns out to slow us down. */ - routerinfo_t *ri_generated = router_get_my_routerinfo(); + const routerinfo_t *ri_generated = router_get_my_routerinfo(); tor_assert(ri_generated != ri_new); } tor_assert(ri_old != ri_new); @@ -3162,7 +3171,7 @@ router_set_status(const char *digest, int up) if (!memcmp(d->digest, digest, DIGEST_LEN)) d->is_running = up); - router = router_get_by_digest(digest); + 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"); @@ -3218,7 +3227,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, id_digest = router->cache_info.identity_digest; - old_router = router_get_by_digest(id_digest); + old_router = router_get_mutable_by_digest(id_digest); /* Make sure that we haven't already got this exact descriptor. */ if (sdmap_get(routerlist->desc_digest_map, @@ -3940,7 +3949,7 @@ router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port, /** Return true iff router does not permit exit streams. */ int -router_exit_policy_rejects_all(routerinfo_t *router) +router_exit_policy_rejects_all(const routerinfo_t *router) { return router->policy_is_reject_star; } @@ -4524,13 +4533,12 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, map = digestmap_new(); list_pending_descriptor_downloads(map, 0); - SMARTLIST_FOREACH(consensus->routerstatus_list, void *, rsp, - { + SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) { routerstatus_t *rs = is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp; signed_descriptor_t *sd; if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) { - routerinfo_t *ri; + const routerinfo_t *ri; ++n_have; if (!(ri = router_get_by_digest(rs->identity_digest)) || memcmp(ri->cache_info.signed_descriptor_digest, @@ -4565,7 +4573,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, if (is_vote && source) { char time_bufnew[ISO_TIME_LEN+1]; char time_bufold[ISO_TIME_LEN+1]; - routerinfo_t *oldrouter = router_get_by_digest(rs->identity_digest); + const routerinfo_t *oldrouter; + oldrouter = router_get_by_digest(rs->identity_digest); format_iso_time(time_bufnew, rs->published_on); if (oldrouter) format_iso_time(time_bufold, oldrouter->cache_info.published_on); @@ -4575,7 +4584,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, source->nickname, oldrouter ? "known" : "unknown"); } smartlist_add(downloadable, rs->descriptor_digest); - }); + } SMARTLIST_FOREACH_END(rsp); if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL) && smartlist_len(no_longer_old)) { @@ -4950,7 +4959,7 @@ router_reset_descriptor_download_failures(void) * would not cause a recent (post 0.1.1.6) dirserver to republish. */ int -router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) +router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) { time_t r1pub, r2pub; long time_difference; @@ -4958,7 +4967,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) /* r1 should be the one that was published first. */ if (r1->cache_info.published_on > r2->cache_info.published_on) { - routerinfo_t *ri_tmp = r2; + const routerinfo_t *ri_tmp = r2; r2 = r1; r1 = ri_tmp; } @@ -5031,7 +5040,8 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) * incompatibility (if any). **/ int -routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, +routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri, + extrainfo_t *ei, signed_descriptor_t *sd, const char **msg) { @@ -5039,7 +5049,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, tor_assert(ri); tor_assert(ei); if (!sd) - sd = &ri->cache_info; + sd = (signed_descriptor_t*)&ri->cache_info; if (ei->bad_sig) { if (msg) *msg = "Extrainfo signature was bad, or signed with wrong key."; @@ -5102,7 +5112,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, /** Assert that the internal representation of rl is * self-consistent. */ void -routerlist_assert_ok(routerlist_t *rl) +routerlist_assert_ok(const routerlist_t *rl) { routerinfo_t *r2; signed_descriptor_t *sd2; @@ -5192,7 +5202,7 @@ routerlist_assert_ok(routerlist_t *rl) * If router is NULL, it just frees its internal memory and returns. */ const char * -esc_router_info(routerinfo_t *router) +esc_router_info(const routerinfo_t *router) { static char *info=NULL; char *esc_contact, *esc_platform; @@ -5515,7 +5525,7 @@ routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei) /** Return true iff ri is in set. */ int -routerset_contains_router(const routerset_t *set, routerinfo_t *ri) +routerset_contains_router(const routerset_t *set, const routerinfo_t *ri) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, ri->addr); @@ -5559,10 +5569,10 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *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, { - routerinfo_t *router = router_get_by_nickname(name, 1); + const routerinfo_t *router = router_get_by_nickname(name, 1); if (router) { if (!running_only || router->is_running) - smartlist_add(out, router); + smartlist_add(out, (void*)router); } }); } else { @@ -5573,7 +5583,7 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, if (running_only && !router->is_running) continue; if (routerset_contains_router(routerset, router)) - smartlist_add(out, router); + smartlist_add(out, (void*)router); }); } } @@ -5740,7 +5750,7 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, int hid_serv_acting_as_directory(void) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); networkstatus_t *c; routerstatus_t *rs; if (!me) @@ -5774,7 +5784,7 @@ hid_serv_acting_as_directory(void) int hid_serv_responsible_for_desc_id(const char *query) { - routerinfo_t *me; + const routerinfo_t *me; routerstatus_t *last_rs; const char *my_id, *last_id; int result; diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 804be2abaa..a805469b7e 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -34,30 +34,30 @@ 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, routerinfo_t *router); -int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2); +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(routerinfo_t *router, const char *list); -routerinfo_t *routerlist_find_my_routerinfo(void); -routerinfo_t *router_find_exact_exit_enclave(const char *address, +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, uint16_t port); -int router_is_unreliable(routerinfo_t *router, int need_uptime, +int router_is_unreliable(const routerinfo_t *router, int need_uptime, int need_capacity, int need_guard); -uint32_t router_get_advertised_bandwidth(routerinfo_t *router); -uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router); +uint32_t router_get_advertised_bandwidth(const routerinfo_t *router); +uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router); -routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl, +const routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule); routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule); -routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist, +const routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist, struct routerset_t *excludedset, router_crn_flags_t flags); -routerinfo_t *router_get_by_nickname(const char *nickname, +const routerinfo_t *router_get_by_nickname(const char *nickname, int warn_if_unnamed); int router_digest_version_as_new_as(const char *digest, const char *cutoff); int router_digest_is_trusted_dir_type(const char *digest, @@ -67,13 +67,14 @@ int router_digest_is_trusted_dir_type(const char *digest, int router_addr_is_trusted_dir(uint32_t addr); int hexdigest_to_digest(const char *hexdigest, char *digest); -routerinfo_t *router_get_by_hexdigest(const char *hexdigest); -routerinfo_t *router_get_by_digest(const char *digest); +const routerinfo_t *router_get_by_hexdigest(const char *hexdigest); +const routerinfo_t *router_get_by_digest(const char *digest); +routerinfo_t *router_get_mutable_by_digest(const char *digest); signed_descriptor_t *router_get_by_descriptor_digest(const char *digest); signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest); signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest); -const char *signed_descriptor_get_body(signed_descriptor_t *desc); -const char *signed_descriptor_get_annotations(signed_descriptor_t *desc); +const char *signed_descriptor_get_body(const signed_descriptor_t *desc); +const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc); routerlist_t *router_get_routerlist(void); void routerinfo_free(routerinfo_t *router); void extrainfo_free(extrainfo_t *extrainfo); @@ -134,7 +135,7 @@ void router_load_extrainfo_from_string(const char *s, const char *eos, 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_rejects_all(routerinfo_t *router); +int router_exit_policy_rejects_all(const routerinfo_t *router); trusted_dir_server_t *add_trusted_dir_server(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, @@ -152,13 +153,15 @@ void router_dir_info_changed(void); const char *get_dir_info_status_string(void); int count_loading_descriptors_progress(void); void router_reset_descriptor_download_failures(void); -int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2); -int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, +int router_differences_are_cosmetic(const routerinfo_t *r1, + const routerinfo_t *r2); +int routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri, + extrainfo_t *ei, signed_descriptor_t *sd, const char **msg); -void routerlist_assert_ok(routerlist_t *rl); -const char *esc_router_info(routerinfo_t *router); +void routerlist_assert_ok(const routerlist_t *rl); +const char *esc_router_info(const routerinfo_t *router); void routers_sort_by_identity(smartlist_t *routers); routerset_t *routerset_new(void); @@ -167,7 +170,7 @@ int routerset_parse(routerset_t *target, const char *s, 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, routerinfo_t *ri); +int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri); int routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs); int routerset_contains_extendinfo(const routerset_t *set, From 6dd7f85bc7fa9887736feb7604e76d7226d03ca5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 29 Sep 2010 01:35:08 -0400 Subject: [PATCH 03/15] Try to make most routerstatus_t interfaces const --- src/or/circuitbuild.c | 2 +- src/or/control.c | 6 +-- src/or/control.h | 2 +- src/or/directory.c | 14 ++++--- src/or/directory.h | 4 +- src/or/dirserv.c | 4 +- src/or/dirserv.h | 4 +- src/or/networkstatus.c | 88 +++++++++++++++++++++++++++++------------- src/or/networkstatus.h | 21 +++++++--- src/or/nodelist.c | 2 +- src/or/routerlist.c | 56 +++++++++++++-------------- src/or/routerlist.h | 10 ++--- 12 files changed, 129 insertions(+), 84 deletions(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index c8e950883c..02f361ce38 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1402,7 +1402,7 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) hop = circ->cpath; do { const routerinfo_t *ri; - routerstatus_t *rs; + const routerstatus_t *rs; char *elt; const char *id; if (!hop) diff --git a/src/or/control.c b/src/or/control.c index be887f4ffd..7161fea2d5 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -3497,7 +3497,7 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses, smartlist_add(strs, tor_strdup("650+")); smartlist_add(strs, tor_strdup(event_string)); smartlist_add(strs, tor_strdup("\r\n")); - SMARTLIST_FOREACH(statuses, routerstatus_t *, rs, + SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs, { s = networkstatus_getinfo_helper_single(rs); if (!s) continue; @@ -3588,7 +3588,7 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt, /** Called when a single local_routerstatus_t has changed: Sends an NS event * to any controller that cares. */ int -control_event_networkstatus_changed_single(routerstatus_t *rs) +control_event_networkstatus_changed_single(const routerstatus_t *rs) { smartlist_t *statuses; int r; @@ -3597,7 +3597,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs) return 0; statuses = smartlist_create(); - smartlist_add(statuses, rs); + smartlist_add(statuses, (void*)rs); r = control_event_networkstatus_changed(statuses); smartlist_free(statuses); return r; diff --git a/src/or/control.h b/src/or/control.h index 27ef5c37f7..275c6de8e1 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -53,7 +53,7 @@ int control_event_my_descriptor_changed(void); int control_event_networkstatus_changed(smartlist_t *statuses); int control_event_newconsensus(const networkstatus_t *consensus); -int control_event_networkstatus_changed_single(routerstatus_t *rs); +int control_event_networkstatus_changed_single(const routerstatus_t *rs); int control_event_general_status(int severity, const char *format, ...) CHECK_PRINTF(2,3); int control_event_client_status(int severity, const char *format, ...) diff --git a/src/or/directory.c b/src/or/directory.c index 0b40b29eb3..2e0eb00a09 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -229,7 +229,8 @@ router_supports_extrainfo(const char *identity_digest, int is_authority) return 1; } if (is_authority) { - routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest); + const routerstatus_t *rs = + router_get_consensus_status_by_id(identity_digest); if (rs && rs->version_supports_extrainfo_upload) return 1; } @@ -328,7 +329,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, const char *resource, int pds_flags) { - routerstatus_t *rs = NULL; + const routerstatus_t *rs = NULL; or_options_t *options = get_options(); int prefer_authority = directory_fetches_from_authorities(options); int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose); @@ -512,7 +513,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, /** Same as directory_initiate_command_routerstatus(), but accepts * rendezvous data to fetch a hidden service descriptor. */ void -directory_initiate_command_routerstatus_rend(routerstatus_t *status, +directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -566,7 +567,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status, * want to fetch. */ void -directory_initiate_command_routerstatus(routerstatus_t *status, +directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -1597,7 +1598,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "'%s:%d'. I'll try again soon.", status_code, escaped(reason), conn->_base.address, conn->_base.port); - if ((rs = router_get_consensus_status_by_id(conn->identity_digest))) + rs = router_get_mutable_consensus_status_by_id(conn->identity_digest); + if (rs) rs->last_dir_503_at = now; if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest))) ds->fake_status.last_dir_503_at = now; @@ -3692,7 +3694,7 @@ dir_microdesc_download_failed(smartlist_t *failed, if (! consensus) return; SMARTLIST_FOREACH_BEGIN(failed, const char *, d) { - rs = router_get_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/directory.h b/src/or/directory.h index 6fd2c0beff..5782df9267 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -23,7 +23,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, void directory_get_from_all_authorities(uint8_t dir_purpose, uint8_t router_purpose, const char *resource); -void directory_initiate_command_routerstatus(routerstatus_t *status, +void directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -31,7 +31,7 @@ void directory_initiate_command_routerstatus(routerstatus_t *status, const char *payload, size_t payload_len, time_t if_modified_since); -void directory_initiate_command_routerstatus_rend(routerstatus_t *status, +void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 148147b149..0da12e41df 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -326,7 +326,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg) /** Return true if there is no point in downloading the router described by * rs because this directory would reject it. */ int -dirserv_would_reject_router(routerstatus_t *rs) +dirserv_would_reject_router(const routerstatus_t *rs) { uint32_t res; @@ -1951,7 +1951,7 @@ version_from_platform(const char *platform) */ int routerstatus_format_entry(char *buf, size_t buf_len, - routerstatus_t *rs, const char *version, + const routerstatus_t *rs, const char *version, routerstatus_format_type_t format) { int r; diff --git a/src/or/dirserv.h b/src/or/dirserv.h index 9be4935a13..f14aee6149 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -105,7 +105,7 @@ 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 dirserv_would_reject_router(routerstatus_t *rs); +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); int dirserv_have_any_microdesc(const smartlist_t *fps); @@ -114,7 +114,7 @@ size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, size_t dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed); int routerstatus_format_entry(char *buf, size_t buf_len, - routerstatus_t *rs, const char *platform, + const routerstatus_t *rs, const char *platform, routerstatus_format_type_t format); void dirserv_free_all(void); void cached_dir_decref(cached_dir_t *d); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 3451a2d402..e5dd4a9d9e 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -940,10 +940,9 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member) return memcmp(key, rs->identity_digest, DIGEST_LEN); } -/** Return the entry in ns for the identity digest digest, or - * NULL if none was found. */ +/** As networkstatus_v2_find_entry, but do not return a const pointer */ routerstatus_t * -networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) +networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest) { return smartlist_bsearch(ns->entries, digest, compare_digest_to_routerstatus_entry); @@ -951,13 +950,28 @@ networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) /** Return the entry in ns for the identity digest digest, or * NULL if none was found. */ +const routerstatus_t * +networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) +{ + return networkstatus_v2_find_mutable_entry(ns, digest); +} + +/** As networkstatus_find_entry, but do not return a const pointer */ routerstatus_t * -networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest) +networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest) { return smartlist_bsearch(ns->routerstatus_list, digest, compare_digest_to_routerstatus_entry); } +/** Return the entry in ns for the identity digest digest, or + * NULL if none was found. */ +const routerstatus_t * +networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest) +{ + return networkstatus_vote_find_mutable_entry(ns, digest); +} + /*XXXX make this static once functions are moved into this file. */ /** Search the routerstatuses in ns for one whose identity digest is * digest. Return value and set *found_out as for @@ -980,11 +994,11 @@ networkstatus_get_v2_list(void) return networkstatus_v2_list; } -/** Return the consensus view of the status of the router whose current - * descriptor digest in consensus is digest, or NULL if - * no such router is known. */ +/* As router_get_consensus_status_by_descriptor_digest, but does not return + * a const pointer */ routerstatus_t * -router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus, +router_get_mutable_consensus_status_by_descriptor_digest( + networkstatus_t *consensus, const char *digest) { if (!consensus) @@ -1002,6 +1016,17 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus, return digestmap_get(consensus->desc_digest_map, digest); } +/** Return the consensus view of the status of the router whose current + * descriptor digest in consensus is digest, or NULL if + * no such router is known. */ +const routerstatus_t * +router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus, + const char *digest) +{ + return router_get_mutable_consensus_status_by_descriptor_digest( + consensus, digest); +} + /** Given the digest of a router descriptor, return its current download * status, or NULL if the digest is unrecognized. */ download_status_t * @@ -1010,8 +1035,8 @@ router_get_dl_status_by_descriptor_digest(const char *d) routerstatus_t *rs; if (!current_ns_consensus) return NULL; - if ((rs = router_get_consensus_status_by_descriptor_digest( - current_ns_consensus, d))) + if ((rs = router_get_mutable_consensus_status_by_descriptor_digest( + current_ns_consensus, d))) return &rs->dl_status; if (v2_download_status_map) return digestmap_get(v2_download_status_map, d); @@ -1019,10 +1044,9 @@ router_get_dl_status_by_descriptor_digest(const char *d) return NULL; } -/** Return the consensus view of the status of the router whose identity - * digest is digest, or NULL if we don't know about any such router. */ +/** As router_get_consensus_status_by_id, but do not return a const pointer */ routerstatus_t * -router_get_consensus_status_by_id(const char *digest) +router_get_mutable_consensus_status_by_id(const char *digest) { if (!current_consensus) return NULL; @@ -1030,11 +1054,19 @@ router_get_consensus_status_by_id(const char *digest) compare_digest_to_routerstatus_entry); } +/** Return the consensus view of the status of the router whose identity + * digest is digest, or NULL if we don't know about any such router. */ +const routerstatus_t * +router_get_consensus_status_by_id(const char *digest) +{ + return router_get_mutable_consensus_status_by_id(digest); +} + /** Given a nickname (possibly verbose, possibly a hexadecimal digest), return * the corresponding routerstatus_t, or NULL if none exists. Warn the * user if warn_if_unnamed is set, and they have specified a router by * nickname, but the Named flag isn't set for that router. */ -routerstatus_t * +const routerstatus_t * router_get_consensus_status_by_nickname(const char *nickname, int warn_if_unnamed) { @@ -1566,13 +1598,14 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c, } changed = smartlist_create(); - SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old, - new_c->routerstatus_list, routerstatus_t *, rs_new, - memcmp(rs_old->identity_digest, - rs_new->identity_digest, DIGEST_LEN), - smartlist_add(changed, rs_new)) { + SMARTLIST_FOREACH_JOIN( + old_c->routerstatus_list, const routerstatus_t *, rs_old, + new_c->routerstatus_list, const routerstatus_t *, rs_new, + memcmp(rs_old->identity_digest, + rs_new->identity_digest, DIGEST_LEN), + smartlist_add(changed, (void*) rs_new)) { if (routerstatus_has_changed(rs_old, rs_new)) - smartlist_add(changed, rs_new); + smartlist_add(changed, (void*)rs_new); } SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new); control_event_networkstatus_changed(changed); @@ -1978,7 +2011,7 @@ download_status_map_update_from_v2_networkstatus(void) dl_status = digestmap_new(); SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) { - SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) { + SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) { const char *d = rs->descriptor_digest; download_status_t *s; if (digestmap_get(dl_status, d)) @@ -2006,7 +2039,8 @@ routerstatus_list_update_named_server_map(void) named_server_map = strmap_new(); strmap_free(unnamed_server_map, NULL); unnamed_server_map = strmap_new(); - SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs, + SMARTLIST_FOREACH(current_consensus->routerstatus_list, + const routerstatus_t *, rs, { if (rs->is_named) { strmap_set_lc(named_server_map, rs->nickname, @@ -2101,7 +2135,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, /* XXXX If this is slow, we need to rethink the code. */ SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, { time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME; - SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs, + SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs, routers, routerinfo_t *, ri, memcmp(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN), @@ -2134,7 +2168,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs) } SMARTLIST_FOREACH(descs, signed_descriptor_t *, d, { - routerstatus_t *rs = digestmap_get(ns->desc_digest_map, + const routerstatus_t *rs = digestmap_get(ns->desc_digest_map, d->signed_descriptor_digest); if (rs) { if (ns->valid_until > d->last_listed_as_valid_until) @@ -2147,7 +2181,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs) * return the result in a newly allocated string. Used only by controller * interface (for now.) */ char * -networkstatus_getinfo_helper_single(routerstatus_t *rs) +networkstatus_getinfo_helper_single(const routerstatus_t *rs) { char buf[RS_ENTRY_LEN+1]; routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT); @@ -2303,7 +2337,7 @@ getinfo_helper_networkstatus(control_connection_t *conn, const char *question, char **answer, const char **errmsg) { - routerstatus_t *status; + const routerstatus_t *status; (void) conn; if (!current_consensus) { @@ -2314,7 +2348,7 @@ getinfo_helper_networkstatus(control_connection_t *conn, if (!strcmp(question, "ns/all")) { smartlist_t *statuses = smartlist_create(); SMARTLIST_FOREACH(current_consensus->routerstatus_list, - routerstatus_t *, rs, + const routerstatus_t *, rs, { smartlist_add(statuses, networkstatus_getinfo_helper_single(rs)); }); diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index adaddc4982..61c475dee3 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -38,19 +38,28 @@ int router_set_networkstatus_v2(const char *s, time_t arrived_at, void networkstatus_v2_list_clean(time_t now); int compare_digest_to_routerstatus_entry(const void *_key, const void **_member); -routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns, +const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest); -routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns, +const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns, + const char *digest); +routerstatus_t *networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, + const char *digest); +routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest); int networkstatus_vote_find_entry_idx(networkstatus_t *ns, const char *digest, int *found_out); const smartlist_t *networkstatus_get_v2_list(void); download_status_t *router_get_dl_status_by_descriptor_digest(const char *d); -routerstatus_t *router_get_consensus_status_by_id(const char *digest); -routerstatus_t *router_get_consensus_status_by_descriptor_digest( +const routerstatus_t *router_get_consensus_status_by_id(const char *digest); +routerstatus_t *router_get_mutable_consensus_status_by_id( + const char *digest); +const routerstatus_t *router_get_consensus_status_by_descriptor_digest( networkstatus_t *consensus, const char *digest); -routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname, +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 char *networkstatus_get_router_digest_by_nickname(const char *nickname); int networkstatus_nickname_is_unnamed(const char *nickname); @@ -83,7 +92,7 @@ void routers_update_status_from_consensus_networkstatus(smartlist_t *routers, void signed_descs_update_status_from_consensus_networkstatus( smartlist_t *descs); -char *networkstatus_getinfo_helper_single(routerstatus_t *rs); +char *networkstatus_getinfo_helper_single(const routerstatus_t *rs); char *networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now); void networkstatus_dump_bridge_status_to_file(time_t now); int32_t get_net_param_from_list(smartlist_t *net_params, const char *name, diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 9c8714c354..b620b408ea 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -122,7 +122,7 @@ nodelist_add_microdesc(microdesc_t *md) { networkstatus_t *ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC); - routerstatus_t *rs; + const routerstatus_t *rs; node_t *node; if (ns == NULL) return NULL; diff --git a/src/or/routerlist.c b/src/or/routerlist.c index d2edeadc9f..0f1bfc0ebb 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -39,9 +39,9 @@ /****************************************************************************/ /* static function prototypes */ -static routerstatus_t *router_pick_directory_server_impl( +static const routerstatus_t *router_pick_directory_server_impl( authority_type_t auth, int flags); -static routerstatus_t *router_pick_trusteddirserver_impl( +static const routerstatus_t *router_pick_trusteddirserver_impl( authority_type_t auth, int flags, int *n_busy_out); static void mark_all_trusteddirservers_up(void); static int router_nickname_matches(const routerinfo_t *router, @@ -927,10 +927,10 @@ router_get_trusted_dir_servers(void) * Don't pick an authority if any non-authority is viable; try to avoid using * servers that have returned 503 recently. */ -routerstatus_t * +const routerstatus_t * router_pick_directory_server(authority_type_t type, int flags) { - routerstatus_t *choice; + const routerstatus_t *choice; if (get_options()->PreferTunneledDirConns) flags |= _PDS_PREFER_TUNNELED_DIR_CONNS; @@ -960,7 +960,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out, double *v3_share_out) { const routerinfo_t *me = router_get_my_routerinfo(); - routerstatus_t *rs; + const routerstatus_t *rs; const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL; *v2_share_out = *v3_share_out = 0.0; if (!me) @@ -1033,10 +1033,10 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest) /** Try to find a running trusted dirserver. Flags are as for * router_pick_directory_server. */ -routerstatus_t * +const routerstatus_t * router_pick_trusteddirserver(authority_type_t type, int flags) { - routerstatus_t *choice; + const routerstatus_t *choice; int busy = 0; if (get_options()->PreferTunneledDirConns) flags |= _PDS_PREFER_TUNNELED_DIR_CONNS; @@ -1069,10 +1069,10 @@ router_pick_trusteddirserver(authority_type_t type, int flags) * If the _PDS_PREFER_TUNNELED_DIR_CONNS flag is set, prefer directory servers * that we can use with BEGINDIR. */ -static routerstatus_t * +static const routerstatus_t * router_pick_directory_server_impl(authority_type_t type, int flags) { - routerstatus_t *result; + const routerstatus_t *result; smartlist_t *direct, *tunnel; smartlist_t *trusted_direct, *trusted_tunnel; smartlist_t *overloaded_direct, *overloaded_tunnel; @@ -1163,14 +1163,14 @@ router_pick_directory_server_impl(authority_type_t type, int flags) /** Choose randomly from among the trusted dirservers that are up. Flags * are as for router_pick_directory_server_impl(). */ -static routerstatus_t * +static const routerstatus_t * router_pick_trusteddirserver_impl(authority_type_t type, int flags, int *n_busy_out) { smartlist_t *direct, *tunnel; smartlist_t *overloaded_direct, *overloaded_tunnel; const routerinfo_t *me = router_get_my_routerinfo(); - routerstatus_t *result; + const routerstatus_t *result; time_t now = time(NULL); const int requireother = ! (flags & PDS_ALLOW_SELF); const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL); @@ -1273,7 +1273,7 @@ mark_all_trusteddirservers_up(void) routerstatus_t *rs; dir->is_running = 1; download_status_reset(&dir->v2_ns_dl_status); - rs = router_get_consensus_status_by_id(dir->digest); + rs = router_get_mutable_consensus_status_by_id(dir->digest); if (rs && !rs->is_running) { rs->is_running = 1; rs->last_dir_503_at = 0; @@ -1748,7 +1748,7 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl, if (router_digest_is_me(status->identity_digest)) is_me = 1; } else { - routerstatus_t *rs; + const routerstatus_t *rs; routerinfo_t *router = smartlist_get(sl, i); rs = router_get_consensus_status_by_id( router->cache_info.identity_digest); @@ -1911,7 +1911,7 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, flags |= is_guard ? 4 : 0; } } else { - routerstatus_t *rs; + const routerstatus_t *rs; router = smartlist_get(sl, i); rs = router_get_consensus_status_by_id( router->cache_info.identity_digest); @@ -2112,7 +2112,7 @@ routerlist_sl_choose_by_bandwidth(smartlist_t *sl, /** Choose a random element of status list sl, weighted by * the advertised bandwidth of each status. */ -routerstatus_t * +const routerstatus_t * routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule) { @@ -2317,15 +2317,14 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) if (warn_if_unnamed && n_matches > 1) { smartlist_t *fps = smartlist_create(); int any_unwarned = 0; - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - { + SMARTLIST_FOREACH_BEGIN(routerlist->routers, routerinfo_t *, router) { routerstatus_t *rs; char *desc; size_t dlen; char fp[HEX_DIGEST_LEN+1]; if (strcasecmp(router->nickname, nickname)) continue; - rs = router_get_consensus_status_by_id( + rs = router_get_mutable_consensus_status_by_id( router->cache_info.identity_digest); if (rs && !rs->name_lookup_warned) { rs->name_lookup_warned = 1; @@ -2338,7 +2337,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d", fp, router->address, router->or_port); smartlist_add(fps, desc); - }); + } SMARTLIST_FOREACH_END(router); if (any_unwarned) { char *alternatives = smartlist_join_strings(fps, "; ",0,NULL); log_warn(LD_CONFIG, @@ -2351,7 +2350,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp)); smartlist_free(fps); } else if (warn_if_unnamed) { - routerstatus_t *rs = router_get_consensus_status_by_id( + routerstatus_t *rs = router_get_mutable_consensus_status_by_id( best_match->cache_info.identity_digest); if (rs && !rs->name_lookup_warned) { char fp[HEX_DIGEST_LEN+1]; @@ -3180,7 +3179,7 @@ router_set_status(const char *digest, int up) "addresses reachable?"); router->is_running = up; } - status = router_get_consensus_status_by_id(digest); + status = router_get_mutable_consensus_status_by_id(digest); if (status && status->is_running != up) { status->is_running = up; control_event_networkstatus_changed_single(status); @@ -3282,14 +3281,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, { routerstatus_t *rs = - networkstatus_v2_find_entry(ns, id_digest); + networkstatus_v2_find_mutable_entry(ns, id_digest); if (rs && !memcmp(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) rs->need_to_mirror = 0; }); if (consensus) { - routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest); + routerstatus_t *rs = networkstatus_vote_find_mutable_entry( + consensus, id_digest); if (rs && !memcmp(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) { @@ -3889,7 +3889,7 @@ router_load_extrainfo_from_string(const char *s, const char *eos, static int signed_desc_digest_is_recognized(signed_descriptor_t *desc) { - routerstatus_t *rs; + const routerstatus_t *rs; networkstatus_t *consensus = networkstatus_get_latest_consensus(); int caches = directory_caches_dir_info(get_options()); const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list(); @@ -4144,7 +4144,7 @@ list_pending_microdesc_downloads(digestmap_t *result) * otherwise, download from an appropriate random directory server. */ static void -initiate_descriptor_downloads(routerstatus_t *source, +initiate_descriptor_downloads(const routerstatus_t *source, int purpose, smartlist_t *digests, int lo, int hi, int pds_flags) @@ -4256,7 +4256,7 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) void launch_descriptor_downloads(int purpose, smartlist_t *downloadable, - routerstatus_t *source, time_t now) + const routerstatus_t *source, time_t now) { int should_delay = 0, n_downloadable; or_options_t *options = get_options(); @@ -5540,7 +5540,7 @@ routerset_contains_router(const routerset_t *set, const routerinfo_t *ri) /** Return true iff rs is in set. */ int -routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs) +routerset_contains_routerstatus(const routerset_t *set, const routerstatus_t *rs) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, rs->addr); @@ -5752,7 +5752,7 @@ hid_serv_acting_as_directory(void) { const routerinfo_t *me = router_get_my_routerinfo(); networkstatus_t *c; - routerstatus_t *rs; + const routerstatus_t *rs; if (!me) return 0; if (!get_options()->HidServDirectoryV2) { diff --git a/src/or/routerlist.h b/src/or/routerlist.h index a805469b7e..90975e78e6 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -27,10 +27,10 @@ int router_reload_router_list(void); int authority_cert_dl_looks_uncertain(const char *id_digest); smartlist_t *router_get_trusted_dir_servers(void); -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); -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); @@ -50,7 +50,7 @@ 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); -routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, +const routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule); const routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist, @@ -172,7 +172,7 @@ 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_routerstatus(const routerset_t *set, - routerstatus_t *rs); + const routerstatus_t *rs); 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, @@ -198,7 +198,7 @@ int hid_serv_responsible_for_desc_id(const char *id); void list_pending_microdesc_downloads(digestmap_t *result); void launch_descriptor_downloads(int purpose, smartlist_t *downloadable, - routerstatus_t *source, + const routerstatus_t *source, time_t now); #endif From 26e897420e07611e0b2c10b28202c388eea4bd6b Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 29 Sep 2010 15:00:41 -0400 Subject: [PATCH 04/15] Initial conversion to use node_t throughout our codebase. A node_t is an abstraction over routerstatus_t, routerinfo_t, and microdesc_t. It should try to present a consistent interface to all of them. There should be a node_t for a server whenever there is * A routerinfo_t for it in the routerlist * A routerstatus_t in the current_consensus. (note that a microdesc_t alone isn't enough to make a node_t exist, since microdescriptors aren't usable on their own.) There are three ways to get a node_t right now: looking it up by ID, looking it up by nickname, and iterating over the whole list of microdescriptors. All (or nearly all) functions that are supposed to return "a router" -- especially those used in building connections and circuits -- should return a node_t, not a routerinfo_t or a routerstatus_t. A node_t should hold all the *mutable* flags about a node. This patch moves the is_foo flags from routerinfo_t into node_t. The flags in routerstatus_t remain, but they get set from the consensus and should not change. Some other highlights of this patch are: * Looking up routerinfo and routerstatus by nickname is now unified and based on the "look up a node by nickname" function. This tries to look only at the values from current consensus, and not get confused by the routerinfo_t->is_named flag, which could get set for other weird reasons. This changes the behavior of how authorities (when acting as clients) deal with nodes that have been listed by nickname. * I tried not to artificially increase the size of the diff here by moving functions around. As a result, some functions that now operate on nodes are now in the wrong file -- they should get moved to nodelist.c once this refactoring settles down. This moving should happen as part of a patch that moves functions AND NOTHING ELSE. * Some old code is now left around inside #if 0/1 blocks, and should get removed once I've verified that I don't want it sitting around to see how we used to do things. There are still some unimplemented functions: these are flagged with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the implementation here, piece by piece. I wish this patch could have been smaller, but there did not seem to be any piece of it that was independent from the rest. Moving flags forces many functions that once returned routerinfo_t * to return node_t *, which forces their friends to change, and so on. --- changes/nodelist | 10 + src/or/circuitbuild.c | 437 +++++++++++++------------- src/or/circuitbuild.h | 5 +- src/or/circuitlist.c | 9 +- src/or/circuituse.c | 66 ++-- src/or/circuituse.h | 3 +- src/or/command.c | 7 +- src/or/connection_edge.c | 36 +-- src/or/connection_edge.h | 2 +- src/or/connection_or.c | 15 +- src/or/control.c | 46 +-- src/or/directory.c | 33 +- src/or/dirserv.c | 199 +++++++----- src/or/dirserv.h | 10 +- src/or/dirvote.h | 1 + src/or/microdesc.c | 1 + src/or/networkstatus.c | 126 +------- src/or/networkstatus.h | 5 +- src/or/nodelist.c | 418 +++++++++++++++++++++++-- src/or/nodelist.h | 39 ++- src/or/or.h | 100 ++++-- src/or/policies.c | 52 ++++ src/or/policies.h | 9 +- src/or/relay.c | 11 +- src/or/rendclient.c | 8 +- src/or/rendservice.c | 41 +-- src/or/rephist.c | 33 +- src/or/router.c | 39 ++- src/or/routerlist.c | 651 +++++++++++++++++++++------------------ src/or/routerlist.h | 53 ++-- src/or/routerparse.c | 3 - 31 files changed, 1512 insertions(+), 956 deletions(-) create mode 100644 changes/nodelist diff --git a/changes/nodelist b/changes/nodelist new file mode 100644 index 0000000000..033a6c10fb --- /dev/null +++ b/changes/nodelist @@ -0,0 +1,10 @@ + o Code refactorings + - Unified our node-listing and selecting logic. We had at least + two major ways to look at the question of "which Tor servers do + we know about": our list of router descriptors, and the current + consensus. We're adding a third in microdescriptors. Having + so many systems without an abstraction layer over them was + hurting the codebase. Now, we have a new "node_t" abstraction + that presents a consistent interface to a client's view of + a Tor node, and holds (nearly) all of the mutable state + formerly in routerinfo_t and routerstatus_t. diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 02f361ce38..58d4e60fa5 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 : ""); + node ? node_get_nickname(node) : ""); } 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 router can handle one or more of the ports in +/** Return 1 if node can handle one or more of the ports in * needed_ports, 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;inickname); - 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 state 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 node. May return NULL if there is not + * enough info about node 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 state. If @@ -3238,9 +3254,8 @@ build_state_get_exit_nickname(cpath_build_state_t *state) * * If it's not usable, set *reason 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 e, if e is +/** Return the node corresponding to e, if e 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 *msg 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 chosen 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 state 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 state 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 59e818d5f3..7c125e96b1 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 96a06c05f2..da6d32961b 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 a2a09bedff..ca156d43c9 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 purpose 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 617685e610..4e4cd1a4d9 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 6296c471eb..46713a5138 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 2b9ccc5968..4ab636a932 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 24ea327ec6..f54d7a44ec 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 ee17282e5e..ce285cd3ab 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 7161fea2d5..a46ce2c7ff 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 2e0eb00a09..27de0aecdf 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 0da12e41df..dec1577b30 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 msg is provided, set * *msg 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 node based on our opinion as a + * directory authority in authstatus, 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 a is more severe than 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 is_live 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 routers, 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 router. 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 f14aee6149..a779632430 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 e384dc53b3..33213a88c6 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 19970aa783..c3511cf324 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 e5dd4a9d9e..7374ced709 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) + const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed); + if (node) + return node->rs; + else 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)); - 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 61c475dee3..aa5496e2b1 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 b620b408ea..f2923a4eba 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 -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 identity_digest, 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 identity_digest, 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 * identity_digest. 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 node 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 + * warn_if_unnamed 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 node, 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 node 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 node 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 node 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 node. */ +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 node and store it + * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at + * verbose_nickname_out */ +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 node 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 node 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 node into *addr_out. */ +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 node, 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 node into the + * len-byte buffer at buf. + */ +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 node'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 node'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 node's platform string */ +const char * +node_get_platform(const node_t *node) +{ + (void)node; + UNIMPLEMENTED_NODELIST(); + return NULL; +} + +/** Return node's time of publication. */ +time_t +node_get_published_on(const node_t *node) +{ + (void)node; + UNIMPLEMENTED_NODELIST(); + return 0; +} + +/** Return true iff node 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 6a77ba6836..3dceb75731 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 e46237c365..d9be013332 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 b4d359599c..1404e20e50 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 + * node. */ +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 r 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 node 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 policy that * allows exiting to port. 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 + * node. 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 + * node. 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 4a34745709..acc254da3c 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 48948f0011..c645b729ad 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 67bd55a291..5c5e1bfa4e 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 f6769d5580..f67e9ab659 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 d998e87ca6..97a3c54546 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 dfb2f06d4c..507785eadb 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 0f1bfc0ebb..e456f4385b 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 (status->is_bad_directory) + + if (!node->is_running || !status->dir_port || !node->is_valid) continue; - if (requireother && router_digest_is_me(status->identity_digest)) + if (node->is_bad_directory) + continue; + 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 router. * Add each of them to sl. @@ -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 router to the smartlist sl. * 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 router, add every node_t in its family to sl. + * + * 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 lst. */ @@ -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 list name routers in our routerlist, and add - * the routerinfos for those routers to sl. If must_be_running, + * see which nicknames in list name nodes we know about, and add + * the nodes for those routers to sl. If must_be_running, * 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 * list is an acceptable nickname or hexdigest for router. 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 sl, so that +/** Add every suitable node from our nodelist to sl, 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 need_guard, 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 sl, weighted by + * choose a random element of smartlist sl of nodes, weighted by * the advertised bandwidth of each element using the consensus * bandwidth weights. * - * If statuses is zero, then sl is a list of - * routerinfo_t's. Otherwise it's a list of routerstatus_t's. - * * If rule==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 sl, weighted by + * choose a random node_t element of smartlist sl, weighted by * the advertised bandwidth of each element. * - * If statuses is zero, then sl is a list of - * routerinfo_t's. Otherwise it's a list of routerstatus_t's. - * * If rule==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 sl, 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 sl, 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 - * excludedsmartlist, or whose routerinfo matches excludedset, +/** Return a random running node from the nodelist. Never + * pick a node that is in + * excludedsmartlist, or which matches excludedset, * even if they are the only nodes available. * If CRN_NEED_UPTIME 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 CRN_WEIGHT_AS_EXIT 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 CRN_NEED_DESC 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 identity_digest and nickname - * combination of a router, encoded in hexadecimal, matches hexdigest - * (which is optionally prefixed with a single dollar sign). Return false if - * hexdigest 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 hexdigest try to decode it. + * Return 0 on success, -1 on failure. Store the result into the + * DIGEST_LEN-byte buffer at digest_out, the single character at + * nickname_qualifier_char_out, and the MAXNICKNAME_LEN+1-byte buffer + * at nickname_out. + * + * 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 identity_digest and nickname + * combination of a router, encoded in hexadecimal, matches hexdigest + * (which is optionally prefixed with a single dollar sign). Return false if + * hexdigest 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 router 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 router'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 router's nickname matches nickname @@ -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 digest. 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) - return NULL; - if (hexdigest[0]=='$') - ++hexdigest; - len = strlen(hexdigest); - if (hexdigest_to_digest(hexdigest, digest) < 0) + if (is_legal_nickname(hexdigest)) 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 source to target. */ @@ -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 ri is in set. */ +/** Return true iff ri is in set. If country is -1, 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 rs is in set. */ +/** Return true iff rs is in set. If country is -1, 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); } -/** Add every known routerinfo_t that is a member of routerset to +/** Return true iff node is in set. */ +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 node_t that is a member of routerset to * out. If running_only, 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 target every routerinfo_t from source except: +/** Add to target every node_t from source except: * * 1) Don't add it if include is non-empty and the relay isn't in * include; and @@ -5597,39 +5637,39 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, * 3) If running_only, 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 lst that is in routerset. */ +/** Remove every node_t from lst that is in routerset. */ 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 ri. 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 id (binary) and diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 90975e78e6..cda2d2ef5f 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 f7e645e8fd..b987d6f59c 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; From 45f1e4d5ee7b6e2308655628d18a67d330d9b624 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 30 Sep 2010 14:58:27 -0400 Subject: [PATCH 05/15] Rename routerstatus_t.is_running to is_flagged_running This was the only flag in routerstatus_t that we would previously change in a routerstatus_t in a consensus. We no longer have reason to do so -- and probably never did -- as you can now confirm more easily than you could have done by grepping for is_running before this patch. The name change is to emphasize that the routerstatus_t is_running flag is only there to tell you whether the consensus says it's running, not whether it *you* think it's running. --- src/or/dirserv.c | 8 ++++---- src/or/networkstatus.c | 4 ++-- src/or/nodelist.c | 2 +- src/or/or.h | 6 +++++- src/or/routerlist.c | 11 ++++++----- src/or/routerparse.c | 2 +- src/test/test_dir.c | 12 +++++++----- 7 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/or/dirserv.c b/src/or/dirserv.c index dec1577b30..24718a1e5f 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2035,7 +2035,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", rs->is_named?" Named":"", - rs->is_running?" Running":"", + rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", rs->is_unnamed?" Unnamed":"", rs->is_v2_dir?" V2Dir":"", @@ -2275,7 +2275,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_fast = node->is_fast = router_is_active(ri, node, now) && !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); - rs->is_running = node->is_running; /* computed above */ + rs->is_flagged_running = node->is_running; /* computed above */ if (naming) { uint32_t name_status = dirserv_get_name_status( @@ -2323,7 +2323,7 @@ static void clear_status_flags_on_sybil(routerstatus_t *rs) { rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast = - rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir = + rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir = rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit = rs->is_bad_directory = 0; /* FFFF we might want some mechanism to check later on if we @@ -2591,7 +2591,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, clear_status_flags_on_sybil(rs); if (!vote_on_reachability) - rs->is_running = 0; + rs->is_flagged_running = 0; vrs->version = version_from_platform(ri->platform); md = dirvote_create_microdescriptor(ri); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 7374ced709..2a3fb839f2 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1475,7 +1475,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b) a->is_exit != b->is_exit || a->is_stable != b->is_stable || a->is_fast != b->is_fast || - a->is_running != b->is_running || + a->is_flagged_running != b->is_flagged_running || a->is_named != b->is_named || a->is_unnamed != b->is_unnamed || a->is_valid != b->is_valid || @@ -2022,7 +2022,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, dirserv_should_launch_reachability_test(router, old_router); } } - if (rs->is_running && ds) { + if (rs->is_flagged_running && ds) { download_status_reset(&ds->v2_ns_dl_status); } if (reset_failures) { diff --git a/src/or/nodelist.c b/src/or/nodelist.c index f2923a4eba..dd83abf54e 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -193,7 +193,7 @@ nodelist_set_consensus(networkstatus_t *ns) /* If we're not an authdir, believe others. */ if (!authdir) { node->is_valid = rs->is_valid; - node->is_running = rs->is_running; + node->is_running = rs->is_flagged_running; node->is_fast = rs->is_fast; node->is_stable = rs->is_stable; node->is_possible_guard = rs->is_possible_guard; diff --git a/src/or/or.h b/src/or/or.h index d9be013332..670cf7dd40 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1586,7 +1586,11 @@ typedef struct routerstatus_t { unsigned int is_exit:1; /**< True iff this router is a good exit. */ unsigned int is_stable:1; /**< True iff this router stays up a long time. */ unsigned int is_fast:1; /**< True iff this router has good bandwidth. */ - unsigned int is_running:1; /**< True iff this router is up. */ + /** True iff this router is called 'running' in the consensus. We give it + * this funny name so that we don't accidentally use this bit as a view of + * whether we think the router is *currently* running. If that's what you + * want to know, look at is_running in node_t. */ + unsigned int is_flagged_running:1; unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */ unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another * router. */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index e456f4385b..a082ff410e 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1276,8 +1276,7 @@ mark_all_trusteddirservers_up(void) dir->is_running = 1; download_status_reset(&dir->v2_ns_dl_status); rs = router_get_mutable_consensus_status_by_id(dir->digest); - if (rs && !rs->is_running) { - rs->is_running = 1; + if (rs) { rs->last_dir_503_at = 0; control_event_networkstatus_changed_single(rs); } @@ -3186,7 +3185,6 @@ void router_set_status(const char *digest, int up) { node_t *node; - routerstatus_t *status; tor_assert(digest); SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d, @@ -3207,12 +3205,15 @@ router_set_status(const char *digest, int up) node->is_running = up; } - /*XXXX NM don't change routerstatus's is_running. */ +#if 0 + /* No, don't change routerstatus's is_running. I have confirmed that + * nothing uses it to ask "is the node running? */ status = router_get_mutable_consensus_status_by_id(digest); if (status && status->is_running != up) { status->is_running = up; control_event_networkstatus_changed_single(status); } +#endif router_dir_info_changed(); } @@ -4237,7 +4238,7 @@ initiate_descriptor_downloads(const routerstatus_t *source, static INLINE int client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) { - if (!rs->is_running && !options->FetchUselessDescriptors) { + if (!rs->is_flagged_running && !options->FetchUselessDescriptors) { /* If we had this router descriptor, we wouldn't even bother using it. * But, if we want to have a complete list, fetch it anyway. */ return 0; diff --git a/src/or/routerparse.c b/src/or/routerparse.c index b987d6f59c..665a718132 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -2027,7 +2027,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, else if (!strcmp(tok->args[i], "Fast")) rs->is_fast = 1; else if (!strcmp(tok->args[i], "Running")) - rs->is_running = 1; + rs->is_flagged_running = 1; else if (!strcmp(tok->args[i], "Named")) rs->is_named = 1; else if (!strcmp(tok->args[i], "Valid")) diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 80d2379de6..3c660a7575 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -801,7 +801,7 @@ test_dir_v3_networkstatus(void) rs->or_port = 443; rs->dir_port = 8000; /* all flags but running cleared */ - rs->is_running = 1; + rs->is_flagged_running = 1; smartlist_add(vote->routerstatus_list, vrs); test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); @@ -816,7 +816,7 @@ test_dir_v3_networkstatus(void) rs->addr = 0x99009901; rs->or_port = 443; rs->dir_port = 0; - rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running = + rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1; smartlist_add(vote->routerstatus_list, vrs); test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); @@ -833,7 +833,8 @@ test_dir_v3_networkstatus(void) rs->or_port = 400; rs->dir_port = 9999; rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast = - rs->is_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1; + rs->is_flagged_running = rs->is_valid = rs->is_v2_dir = + rs->is_possible_guard = 1; smartlist_add(vote->routerstatus_list, vrs); test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); @@ -1073,7 +1074,8 @@ test_dir_v3_networkstatus(void) test_assert(!rs->is_fast); test_assert(!rs->is_possible_guard); test_assert(!rs->is_stable); - test_assert(rs->is_running); /* If it wasn't running it wouldn't be here */ + /* (If it wasn't running it wouldn't be here) */ + test_assert(rs->is_flagged_running); test_assert(!rs->is_v2_dir); test_assert(!rs->is_valid); test_assert(!rs->is_named); @@ -1095,7 +1097,7 @@ test_dir_v3_networkstatus(void) test_assert(rs->is_fast); test_assert(rs->is_possible_guard); test_assert(rs->is_stable); - test_assert(rs->is_running); + test_assert(rs->is_flagged_running); test_assert(rs->is_v2_dir); test_assert(rs->is_valid); test_assert(!rs->is_named); From f9ea242acabcaec0ab0fbd0de5e9999dfcdb0193 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 30 Sep 2010 18:25:25 -0400 Subject: [PATCH 06/15] Implement node-based router family code Also, make the NodeFamily option into a list of routersets. This lets us git rid of router_in_nickname_list (or whatever it was called) without porting it to work with nodes, and also lets people specify country codes and IP ranges in NodeFamily --- doc/nodefamily_routerset | 4 + doc/tor.1.txt | 3 +- src/or/config.c | 23 ++++- src/or/nodelist.c | 13 +++ src/or/nodelist.h | 1 + src/or/or.h | 3 +- src/or/routerlist.c | 182 +++++++++++++++++++++++---------------- 7 files changed, 153 insertions(+), 76 deletions(-) create mode 100644 doc/nodefamily_routerset diff --git a/doc/nodefamily_routerset b/doc/nodefamily_routerset new file mode 100644 index 0000000000..0af62e11f6 --- /dev/null +++ b/doc/nodefamily_routerset @@ -0,0 +1,4 @@ + o Minor features + - The NodeFamily option -- which let you declare that you want to + consider nodes to be part of a family whether they list themselves + that way or not -- now allows IP address ranges and country codes. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 42eed6e3dd..90a52fe1ef 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -571,7 +571,8 @@ The following options are useful only for clients (that is, if constitute a "family" of similar or co-administered servers, so never use any two of them in the same circuit. Defining a NodeFamily is only needed when a server doesn't list the family itself (with MyFamily). This option - can be used multiple times. + can be used multiple times. In addition to nodes, you can also list + IP address and ranges and country codes in {curly braces}. **EnforceDistinctSubnets** **0**|**1**:: If 1, Tor will not put two servers whose IP addresses are "too close" on diff --git a/src/or/config.c b/src/or/config.c index 4f7077153d..b438626343 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -691,6 +691,11 @@ or_options_free(or_options_t *options) return; routerset_free(options->_ExcludeExitNodesUnion); + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *, + rs, routerset_free(rs)); + smartlist_free(options->NodeFamilySets); + } config_free(&options_format, options); } @@ -3084,6 +3089,18 @@ options_validate(or_options_t *old_options, or_options_t *options, routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes); } + if (options->NodeFamilies) { + options->NodeFamilySets = smartlist_create(); + for (cl = options->NodeFamilies; cl; cl = cl->next) { + routerset_t *rs = routerset_new(); + if (routerset_parse(rs, cl->value, cl->key) == 0) { + smartlist_add(options->NodeFamilySets, rs); + } else { + routerset_free(rs); + } + } + } + if (options->ExcludeNodes && options->StrictNodes) { COMPLAIN("You have asked to exclude certain relays from all positions " "in your circuits. Expect hidden services and other Tor " @@ -3549,8 +3566,12 @@ options_validate(or_options_t *old_options, or_options_t *options, if (check_nickname_list(options->MyFamily, "MyFamily", msg)) return -1; for (cl = options->NodeFamilies; cl; cl = cl->next) { - if (check_nickname_list(cl->value, "NodeFamily", msg)) + routerset_t *rs = routerset_new(); + if (routerset_parse(rs, cl->value, cl->key)) { + routerset_free(rs); return -1; + } + routerset_free(rs); } if (validate_addr_policies(options, msg) < 0) diff --git a/src/or/nodelist.c b/src/or/nodelist.c index dd83abf54e..7c036982d5 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -698,6 +698,19 @@ node_is_me(const node_t *node) return router_digest_is_me(node->identity); } +/** Return node declared family (as a list of names), or NULL if + * the node didn't declare a family. */ +const smartlist_t * +node_get_declared_family(const node_t *node) +{ + if (node->ri && node->ri->declared_family) + return node->ri->declared_family; + else if (node->md && node->md->family) + return node->md->family; + else + return NULL; +} + /* 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 3dceb75731..cb78366508 100644 --- a/src/or/nodelist.h +++ b/src/or/nodelist.h @@ -45,6 +45,7 @@ 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); +const smartlist_t *node_get_declared_family(const node_t *node); smartlist_t *nodelist_get_list(void); diff --git a/src/or/or.h b/src/or/or.h index 670cf7dd40..ac9634748e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2725,7 +2725,8 @@ typedef struct { char *MyFamily; /**< Declared family for this OR. */ config_line_t *NodeFamilies; /**< List of config lines for - * node families */ + * node families */ + smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */ config_line_t *AuthDirBadDir; /**< Address policy for descriptors to * mark as bad dir mirrors. */ config_line_t *AuthDirBadExit; /**< Address policy for descriptors to diff --git a/src/or/routerlist.c b/src/or/routerlist.c index a082ff410e..73657fca65 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -46,6 +46,8 @@ static const routerstatus_t *router_pick_trusteddirserver_impl( static void mark_all_trusteddirservers_up(void); static int router_nickname_matches(const routerinfo_t *router, const char *nickname); +static int node_nickname_matches(const node_t *router, + const char *nickname); static void trusted_dir_server_free(trusted_dir_server_t *ds); static int signed_desc_digest_is_recognized(signed_descriptor_t *desc); static void update_router_have_minimum_dir_info(void); @@ -1300,72 +1302,70 @@ router_reset_status_download_failures(void) mark_all_trusteddirservers_up(); } -/** Return true iff router1 and router2 have the same /16 network. */ +/** Return true iff router1 and router2 have similar enough network addresses + * that we should treat them as being in the same family */ static INLINE int -routers_in_same_network_family(const routerinfo_t *r1, const routerinfo_t *r2) +addrs_in_same_network_family(const tor_addr_t *a1, + const tor_addr_t *a2) { - return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000); + /* XXXX MOVE ? */ + return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC); } -#if 0 -/** Look through the routerlist and identify routers that - * advertise the same /16 network address as router. - * Add each of them to sl. - */ -static void -routerlist_add_network_family(smartlist_t *sl, const routerinfo_t *router) -{ - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r, - { - if (router != r && routers_in_same_network_family(router, r)) - smartlist_add(sl, r); - }); -} -#endif - /** Add all the family of router to the smartlist sl. * 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 -nodelist_add_node_family(smartlist_t *sl, const node_t *router) +nodelist_add_node_family(smartlist_t *sl, const node_t *node) { /* XXXX MOVE */ -#if 0 - const routerinfo_t *r; - config_line_t *cl; + const smartlist_t *all_nodes = nodelist_get_list(); + const smartlist_t *declared_family = node_get_declared_family(node); or_options_t *options = get_options(); - /* First, add any routers with similar network addresses. */ - if (options->EnforceDistinctSubnets) - routerlist_add_network_family(sl, router); + /* First, add any nodes with similar network addresses. */ + if (options->EnforceDistinctSubnets) { + tor_addr_t node_addr; + node_get_addr(node, &node_addr); - if (router->declared_family) { - /* Add every r such that router declares familyness with r, and r + SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) { + tor_addr_t a; + node_get_addr(node2, &a); + if (addrs_in_same_network_family(&a, &node_addr)) + smartlist_add(sl, (void*)node2); + } SMARTLIST_FOREACH_END(node); + } + + /* Now, add all nodes in the declared_family of this node, if they + * also declare this node to be in their family. */ + if (declared_family) { + /* Add every r such that router declares familyness with node, and node * declares familyhood with router. */ - SMARTLIST_FOREACH_BEGIN(router->declared_family, const char *, n) { - if (!(r = router_get_by_nickname(n, 0))) - continue; - if (!r->declared_family) - continue; - SMARTLIST_FOREACH(r->declared_family, const char *, n2, - { - if (router_nickname_matches(router, n2)) - smartlist_add(sl, (void*)r); - }); - } SMARTLIST_FOREACH_END(n); + SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) { + const node_t *node2; + const smartlist_t *family2; + if (!(node2 = node_get_by_nickname(name, 0))) + continue; + if (!(family2 = node_get_declared_family(node2))) + continue; + SMARTLIST_FOREACH(family2, const char *, name2, { + if (node_nickname_matches(node, name2)) { + smartlist_add(sl, (void*)node2); + break; + } + }); + } SMARTLIST_FOREACH_END(name); } /* If the user declared any families locally, honor those too. */ - for (cl = options->NodeFamilies; cl; cl = cl->next) { - if (router_nickname_is_in_list(router, cl->value)) { - add_nickname_list_to_smartlist(sl, cl->value, 0); - } + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { + if (routerset_contains_node(rs, node)) { + routerset_get_all_nodes(sl, rs, 0); + } + }); } -#endif - (void)sl; - (void)router; - UNIMPLEMENTED_NODELIST(); } /** Given a router, add every node_t in its family to sl. @@ -1376,19 +1376,28 @@ nodelist_add_node_family(smartlist_t *sl, const node_t *router) static void routerlist_add_nodes_in_family(smartlist_t *sl, const routerinfo_t *router) { - (void)router; - (void)sl; - UNIMPLEMENTED_NODELIST(); + /* XXXX MOVE ? */ + node_t fake_node; + const node_t *node = node_get_by_id(router->cache_info.identity_digest);; + if (node == NULL) { + memset(&fake_node, 0, sizeof(fake_node)); + fake_node.ri = (routerinfo_t *)router; + memcpy(fake_node.identity, router->cache_info.identity_digest, DIGEST_LEN); + node = &fake_node; + } + nodelist_add_node_family(sl, &fake_node); } -/** Return true iff r is named by some nickname in lst. */ +/** Return true iff node is named by some nickname in lst. */ static INLINE int -router_in_nickname_smartlist(smartlist_t *lst, const routerinfo_t *r) +node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node) { + /* XXXX MOVE */ if (!lst) return 0; - SMARTLIST_FOREACH(lst, const char *, name, - if (router_nickname_matches(r, name)) - return 1;); + SMARTLIST_FOREACH(lst, const char *, name, { + if (node_nickname_matches(node, name)) + return 1; + }); return 0; } @@ -1397,27 +1406,38 @@ router_in_nickname_smartlist(smartlist_t *lst, const routerinfo_t *r) int nodes_in_same_family(const node_t *node1, const node_t *node2) { -#if 0 + /* XXXX MOVE */ or_options_t *options = get_options(); - config_line_t *cl; - if (options->EnforceDistinctSubnets && - nodes_in_same_network_family(node1,node2)) - return 1; - - if (router_in_nickname_smartlist(r1->declared_family, r2) && - router_in_nickname_smartlist(r2->declared_family, r1)) - return 1; - - for (cl = options->NodeFamilies; cl; cl = cl->next) { - if (router_nickname_is_in_list(r1, cl->value) && - router_nickname_is_in_list(r2, cl->value)) + /* Are they in the same family because of their addresses? */ + if (options->EnforceDistinctSubnets) { + tor_addr_t a1, a2; + node_get_addr(node1, &a1); + node_get_addr(node2, &a2); + if (addrs_in_same_network_family(&a1, &a2)) return 1; } -#endif - (void)node1; - (void)node2; - UNIMPLEMENTED_NODELIST(); + + /* Are they in the same family because the agree they are? */ + { + const smartlist_t *f1, *f2; + f1 = node_get_declared_family(node1); + f2 = node_get_declared_family(node2); + if (f1 && f2 && + node_in_nickname_smartlist(f1, node2) && + node_in_nickname_smartlist(f2, node1)) + return 1; + } + + /* Are they in the same option because the user says they are? */ + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { + if (routerset_contains_node(rs, node1) && + routerset_contains_node(rs, node2)) + return 1; + }); + } + return 0; } @@ -1431,7 +1451,7 @@ nodes_in_same_family(const node_t *node1, const node_t *node2) static void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int must_be_running) -{ /*XXXX MOVE */ +{ /*XXXX MOVE or Kill. */ /*XXXX this is only used in one place. Can we kill it?*/ const node_t *node; const routerinfo_t *router; @@ -2301,6 +2321,22 @@ router_nickname_matches(const routerinfo_t *router, const char *nickname) return router_hex_digest_matches(router, nickname); } +/** Return true if node's nickname matches nickname + * (case-insensitive), or if node's identity key digest + * matches a hexadecimal value stored in nickname. Return + * false otherwise. */ +static int +node_nickname_matches(const node_t *node, const char *nickname) +{ + const char *n = node_get_nickname(node); + if (n && nickname[0]!='$' && !strcasecmp(n, nickname)) + return 1; + return hex_digest_nickname_matches(nickname, + node->identity, + n, + node_is_named(node)); +} + /** Return the router in our routerlist whose (case-insensitive) * nickname or (case-sensitive) hexadecimal key digest is * nickname. Return NULL if no such router is known. From b5341314c17573db15a7cc5999f36569c764c462 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 30 Sep 2010 18:37:53 -0400 Subject: [PATCH 07/15] Implement a few more node-based functions Some of these functions only work for routerinfo-based nodes, and as such are only usable for advisory purposes. Fortunately, our uses of them are compatible with this limitation. --- src/common/util.c | 2 +- src/or/command.c | 7 +++++-- src/or/nodelist.c | 28 +++++++++++++++++----------- src/or/rephist.c | 6 +++++- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/common/util.c b/src/common/util.c index b5a3ade2bd..32c3bb3f22 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -934,7 +934,7 @@ esc_for_log(const char *s) char *result, *outp; size_t len = 3; if (!s) { - return tor_strdup(""); + return tor_strdup("(null)"); } for (cp = s; *cp; ++cp) { diff --git a/src/or/command.c b/src/or/command.c index 46713a5138..3a5c6c01a2 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -273,10 +273,13 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) "Received CREATE cell (circID %d) for known circ. " "Dropping (age %d).", cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created)); - if (node) + if (node) { + char *p = esc_for_log(node_get_platform(node)); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Details: nickname \"%s\", platform %s.", - node_get_nickname(node), escaped(node_get_platform(node))); + node_get_nickname(node), p); + tor_free(p); + } return; } diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 7c036982d5..9518114479 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -656,9 +656,10 @@ node_get_address_string(const node_t *node, char *buf, size_t len) long node_get_declared_uptime(const node_t *node) { - (void)node; - UNIMPLEMENTED_NODELIST(); - return 0; + if (node->ri) + return node->ri->uptime; + else + return -1; } /** Return node's declared or_port */ @@ -673,22 +674,27 @@ node_get_orport(const node_t *node) return 0; } -/** Return node's platform string */ +/** Return node's platform string, or NULL if we don't know it. */ const char * node_get_platform(const node_t *node) { - (void)node; - UNIMPLEMENTED_NODELIST(); - return NULL; + /* If we wanted, we could record the version in the routerstatus_t, since + * the consensus lists it. We don't, though, so this function just won't + * work with microdescriptors. */ + if (node->ri) + return node->ri->platform; + else + return NULL; } -/** Return node's time of publication. */ +/** Return node's time of publication, or 0 if we don't have one. */ time_t node_get_published_on(const node_t *node) { - (void)node; - UNIMPLEMENTED_NODELIST(); - return 0; + if (node->ri) + return node->ri->cache_info.published_on; + else + return 0; } /** Return true iff node is one representing this router. */ diff --git a/src/or/rephist.c b/src/or/rephist.c index 97a3c54546..1b978d963d 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -881,8 +881,12 @@ rep_hist_get_router_stability_doc(time_t now) if (node) { char ip[INET_NTOA_BUF_LEN+1]; char tbuf[ISO_TIME_LEN+1]; + time_t published = node_get_published_on(node); node_get_address_string(node,ip,sizeof(ip)); - format_iso_time(tbuf, node_get_published_on(node)); + if (published > 0) + format_iso_time(tbuf, published); + else + strlcpy(tbuf, "???", sizeof(tbuf)); tor_snprintf(header_buf, sizeof(header_buf), "router %s %s %s\n" "published %s\n" From 42acef68ad6fbe462a00815fbccf94c817931e8f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 1 Oct 2010 17:22:04 -0400 Subject: [PATCH 08/15] Fix a bug in smartlist_choose_node_by_bandwidth --- src/or/routerlist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 73657fca65..05ecbe32b4 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1878,7 +1878,7 @@ static const node_t * smartlist_choose_node_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule) { - unsigned int i; + unsigned i; const routerstatus_t *status=NULL; int32_t *bandwidths; int is_exit; @@ -1925,6 +1925,7 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, int is_known = 1; int32_t flags = 0; uint32_t this_bw = 0; + i = node_sl_idx; if (router_digest_is_me(node->identity)) me_idx = node_sl_idx; From 1bb9734e3a745e2a16b58512f47a6db1229a2b75 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 1 Oct 2010 18:12:30 -0400 Subject: [PATCH 09/15] Implement policies for nodes (and for microdescriptors too) --- src/or/microdesc.c | 13 ++-- src/or/nodelist.c | 15 ++-- src/or/or.h | 19 +++-- src/or/policies.c | 166 +++++++++++++++++++++++++++++++++++++++++-- src/or/policies.h | 7 ++ src/or/routerparse.c | 2 +- src/test/test.c | 5 ++ 7 files changed, 206 insertions(+), 21 deletions(-) diff --git a/src/or/microdesc.c b/src/or/microdesc.c index c3511cf324..0a4c8ea4c7 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -4,12 +4,13 @@ #include "or.h" #include "config.h" #include "directory.h" -#include "microdesc.h" -#include "nodelist.h" -#include "routerparse.h" -#include "networkstatus.h" -#include "routerlist.h" #include "dirserv.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "nodelist.h" +#include "policies.h" +#include "routerlist.h" +#include "routerparse.h" /** A data structure to hold a bunch of cached microdescriptors. There are * two active files in the cache: a "cache file" that we mmap, and a "journal @@ -458,7 +459,7 @@ microdesc_free(microdesc_t *md) SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp)); smartlist_free(md->family); } - tor_free(md->exitsummary); + short_policy_free(md->exit_policy); tor_free(md); } diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 9518114479..d303fc67b4 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -10,6 +10,7 @@ #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" +#include "policies.h" #include "router.h" #include "routerlist.h" @@ -597,14 +598,18 @@ node_allows_single_hop_exits(const node_t *node) return 0; } -/** Return true iff it seems that node has an exit policy that - * doesn't actually permit anything to exit. */ +/** Return true iff it seems that node has an exit policy that doesn't + * actually permit anything to exit, or we don't know its exit policy */ int node_exit_policy_rejects_all(const node_t *node) { - (void)node; - UNIMPLEMENTED_NODELIST(); - return 0; + if (node->ri) + return node->ri->policy_is_reject_star; + else if (node->md) + return node->md->exit_policy == NULL || + short_policy_is_reject_star(node->md->exit_policy); + else + return 1; } /** Copy the address for node into *addr_out. */ diff --git a/src/or/or.h b/src/or/or.h index ac9634748e..c8616beba3 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1648,6 +1648,18 @@ typedef struct routerstatus_t { } routerstatus_t; +/** DOCDOC */ +typedef struct short_policy_entry_t { + uint16_t min_port, max_port; +} short_policy_entry_t; + +/** DOCDOC */ +typedef struct short_policy_t { + unsigned int is_accept : 1; + unsigned int n_entries : 31; + short_policy_entry_t entries[1]; +} short_policy_t; + /** A microdescriptor is the smallest amount of information needed to build a * circuit through a router. They are generated by the directory authorities, * using information from the uploaded routerinfo documents. They are not @@ -1689,9 +1701,8 @@ typedef struct microdesc_t { crypto_pk_env_t *onion_pkey; /** As routerinfo_t.family */ smartlist_t *family; - /** Encoded exit policy summary */ - char *exitsummary; /**< exit policy summary - - * XXX this probably should not stay a string. */ + /** Exit policy summary */ + short_policy_t *exit_policy; } microdesc_t; /** A node_t represents a Tor router. @@ -3444,7 +3455,7 @@ typedef enum { ADDR_POLICY_PROBABLY_ACCEPTED=1, /** Part of the address was unknown, but as far as we can tell, it was * rejected. */ - ADDR_POLICY_PROBABLY_REJECTED=2 + ADDR_POLICY_PROBABLY_REJECTED=2, } addr_policy_result_t; /********************************* rephist.c ***************************/ diff --git a/src/or/policies.c b/src/or/policies.c index 1404e20e50..a5b71c9e2f 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -1315,6 +1315,157 @@ policy_summarize(smartlist_t *policy) return result; } +/** DOCDOC */ +short_policy_t * +parse_short_policy(const char *summary) +{ + const char *orig_summary = summary; + short_policy_t *result; + int is_accept; + int n_entries; + short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */ + const char *next; + + if (!strcmpstart(summary, "accept ")) { + is_accept = 1; + summary += strlen("accept "); + } else if (!strcmpstart(summary, "reject ")) { + is_accept = 0; + summary += strlen("reject "); + } else { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword"); + return NULL; + } + + n_entries = 0; + for ( ; *summary; summary = next) { + const char *comma = strchr(summary, ','); + unsigned low, high; + char dummy; + char ent_buf[32]; + + next = comma ? comma+1 : strchr(summary, '\0'); + + if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s", + escaped(orig_summary)); + return NULL; + } + + if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) { + /* unrecognized entry format. skip it. */ + continue; + } + if (next-summary < 2) { + /* empty; skip it. */ + continue; + } + + memcpy(ent_buf, summary, next-summary-1); + ent_buf[next-summary-1] = '\0'; + + if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) { + if (low<1 || low>65535 || high<1 || high>65535) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s", + escaped(orig_summary)); + return NULL; + } + } else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) { + if (low<1 || low>65535) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s", + escaped(orig_summary)); + return NULL; + } + high = low; + } else { + log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s", + escaped(orig_summary)); + return NULL; + } + + entries[n_entries].min_port = low; + entries[n_entries].max_port = high; + n_entries++; + } + + if (n_entries == 0) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, + "Found no port-range entries in summary %s", escaped(orig_summary)); + return NULL; + } + + { + size_t size = sizeof(short_policy_t) + + sizeof(short_policy_entry_t)*(n_entries-1); + result = tor_malloc_zero(size); + + tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size); + } + + result->is_accept = is_accept; + result->n_entries = n_entries; + memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries); + return result; +} + +/** DOCDOC */ +void +short_policy_free(short_policy_t *policy) +{ + tor_free(policy); +} + +/** DOCDOC */ +addr_policy_result_t +compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, + const short_policy_t *policy) +{ + int i; + int found_match = 0; + int accept; + (void)addr; + + tor_assert(port != 0); + + if (addr && (tor_addr_is_internal(addr, 0) || + tor_addr_is_null(addr) || + tor_addr_is_loopback(addr))) + return ADDR_POLICY_REJECTED; + + for (i=0; i < policy->n_entries; ++i) { + const short_policy_entry_t *e = &policy->entries[i]; + if (e->min_port <= port && port <= e->max_port) { + found_match = 1; + break; + } + } + + if (found_match) + accept = policy->is_accept; + else + accept = ! policy->is_accept; + + /* ???? are these right? */ + if (accept) + return ADDR_POLICY_PROBABLY_ACCEPTED; + else + return ADDR_POLICY_REJECTED; +} + +/* DOCDOC */ +int +short_policy_is_reject_star(const short_policy_t *policy) +{ + /* This doesn't need to be as much on the lookout as policy_is_reject_star, + * since policy summaries are from the consensus or from consensus microdescs. + */ + tor_assert(policy); + /* Check for an exact match of "reject 1-65535". */ + return (policy->is_accept == 0 && policy->n_entries == 1 && + policy->entries[0].min_port == 1 && + policy->entries[0].max_port == 65535); +} + /** Decides whether addr:port is probably or definitely accepted or rejcted by * node. See compare_tor_addr_to_addr_policy for details on addr/port * interpretation. */ @@ -1333,11 +1484,16 @@ 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; + if (node->ri) + return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy); + else if (node->md && node->md) { + if (node->md->exit_policy == NULL) + return ADDR_POLICY_REJECTED; + else + return compare_tor_addr_to_short_policy(addr, port, + node->md->exit_policy); + } else + return ADDR_POLICY_PROBABLY_REJECTED; } /** Implementation for GETINFO control command: knows the answer for questions diff --git a/src/or/policies.h b/src/or/policies.h index acc254da3c..5c1113e75a 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -63,5 +63,12 @@ void policies_free_all(void); char *policy_summarize(smartlist_t *policy); +short_policy_t *parse_short_policy(const char *summary); +void short_policy_free(short_policy_t *policy); +int short_policy_is_reject_star(const short_policy_t *policy); +addr_policy_result_t compare_tor_addr_to_short_policy( + const tor_addr_t *addr, uint16_t port, + const short_policy_t *policy); + #endif diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 665a718132..2b82e9828f 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -4302,7 +4302,7 @@ microdescs_parse_from_string(const char *s, const char *eos, } if ((tok = find_opt_by_keyword(tokens, K_P))) { - md->exitsummary = tor_strdup(tok->args[0]); + md->exit_policy = parse_short_policy(tok->args[0]); } crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256); diff --git a/src/test/test.c b/src/test/test.c index 8d8c46fca2..a57b6b0444 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -560,6 +560,7 @@ test_policy_summary_helper(const char *policy_str, smartlist_t *policy = smartlist_create(); char *summary = NULL; int r; + short_policy_t *short_policy = NULL; line.key = (char*)"foo"; line.value = (char *)policy_str; @@ -572,10 +573,14 @@ test_policy_summary_helper(const char *policy_str, test_assert(summary != NULL); test_streq(summary, expected_summary); + short_policy = parse_short_policy(summary); + tt_assert(short_policy); + done: tor_free(summary); if (policy) addr_policy_list_free(policy); + short_policy_free(short_policy); } /** Run unit tests for generating summary lines of exit policies */ From b9f2ccbdcc222869b7561714c285db8b47e52e77 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 1 Oct 2010 19:52:05 -0400 Subject: [PATCH 10/15] More debugging code for node_t branch --- src/or/circuitbuild.c | 13 ++++++++++--- src/or/nodelist.c | 7 ++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 58d4e60fa5..f485574408 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2564,7 +2564,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) */ continue; } - if (!node->ri && !(node->rs && node->md)) + if (!node_has_descriptor(node)) continue; if (!node->is_running || node->is_bad_exit) { n_supported[i] = -1; @@ -2684,6 +2684,8 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) /* try once to pick only from routers that satisfy a needed port, * then if there are none, pick from any that support exiting. */ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) { + if (!node_has_descriptor(node)) + continue; 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.", @@ -2860,6 +2862,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) return -1; } exit = extend_info_from_node(node); + tor_assert(exit); } state->chosen_exit = exit; return 0; @@ -3100,13 +3103,17 @@ onion_extend_cpath(origin_circuit_t *circ) info = extend_info_dup(state->chosen_exit); } else if (cur_len == 0) { /* picking first node */ const node_t *r = choose_good_entry_server(purpose, state); - if (r) + if (r) { info = extend_info_from_node(r); + tor_assert(info); + } } else { const node_t *r = choose_good_middle_server(purpose, state, circ->cpath, cur_len); - if (r) + if (r) { info = extend_info_from_node(r); + tor_assert(info); + } } if (!info) { diff --git a/src/or/nodelist.c b/src/or/nodelist.c index d303fc67b4..a7946c9a2c 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -593,9 +593,10 @@ node_get_verbose_nickname(const node_t *node, int node_allows_single_hop_exits(const node_t *node) { - (void)node; - UNIMPLEMENTED_NODELIST(); - return 0; + if (node && node->ri) + return node->ri->allow_single_hop_exits; + else + return 0; } /** Return true iff it seems that node has an exit policy that doesn't From 9edd85aa4cb019499294b4c378961be8e42bcefe Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 4 Oct 2010 23:33:50 -0400 Subject: [PATCH 11/15] Switch an && to an ||, stop a *NULL. --- src/or/circuitbuild.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index f485574408..6e9e0e192a 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -3358,7 +3358,7 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, return NULL; } node = node_get_by_id(e->identity); - if (!node && !node_has_descriptor(node)) { + if (!node || !node_has_descriptor(node)) { *msg = "no descriptor"; return NULL; } From 4080d9b0fa9dd4cab903599d6f7f3ed0785e2420 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 4 Oct 2010 23:51:30 -0400 Subject: [PATCH 12/15] Fix a couple more node_t-related nullpointer bugs --- src/or/circuituse.c | 2 +- src/or/nodelist.c | 1 + src/or/routerlist.c | 12 ++++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index ca156d43c9..399fc28904 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1313,7 +1313,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, const node_t *r; int opt = conn->chosen_exit_optional; r = node_get_by_nickname(conn->chosen_exit_name, 1); - if (r) { + if (r && node_has_descriptor(r)) { extend_info = extend_info_from_node(r); } else { log_debug(LD_DIR, "considering %d, %s", diff --git a/src/or/nodelist.c b/src/or/nodelist.c index a7946c9a2c..8145217c2f 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -514,6 +514,7 @@ node_get_by_nickname(const char *nickname, int warn_if_unnamed) const char * node_get_nickname(const node_t *node) { + tor_assert(node); if (node->rs) return node->rs->nickname; else if (node->ri) diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 05ecbe32b4..2849f17ea7 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1321,9 +1321,13 @@ nodelist_add_node_family(smartlist_t *sl, const node_t *node) { /* XXXX MOVE */ const smartlist_t *all_nodes = nodelist_get_list(); - const smartlist_t *declared_family = node_get_declared_family(node); + const smartlist_t *declared_family; or_options_t *options = get_options(); + tor_assert(node); + + declared_family = node_get_declared_family(node); + /* First, add any nodes with similar network addresses. */ if (options->EnforceDistinctSubnets) { tor_addr_t node_addr; @@ -1334,7 +1338,7 @@ nodelist_add_node_family(smartlist_t *sl, const node_t *node) node_get_addr(node2, &a); if (addrs_in_same_network_family(&a, &node_addr)) smartlist_add(sl, (void*)node2); - } SMARTLIST_FOREACH_END(node); + } SMARTLIST_FOREACH_END(node2); } /* Now, add all nodes in the declared_family of this node, if they @@ -1349,12 +1353,12 @@ nodelist_add_node_family(smartlist_t *sl, const node_t *node) continue; if (!(family2 = node_get_declared_family(node2))) continue; - SMARTLIST_FOREACH(family2, const char *, name2, { + SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) { if (node_nickname_matches(node, name2)) { smartlist_add(sl, (void*)node2); break; } - }); + } SMARTLIST_FOREACH_END(name2); } SMARTLIST_FOREACH_END(name); } From 99062c4003ad9ec35fe84842f692047cc12477df Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 5 Oct 2010 00:39:01 -0400 Subject: [PATCH 13/15] Spotted another missing check --- src/or/directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/directory.c b/src/or/directory.c index 27de0aecdf..9362a27b26 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -222,7 +222,7 @@ router_supports_extrainfo(const char *identity_digest, int is_authority) { const node_t *node = node_get_by_id(identity_digest); - if (node->ri) { + if (node && node->ri) { if (node->ri->caches_extra_info) return 1; if (is_authority && node->ri->platform && From 34546e2573d4eea02f3622d3d8d27ef0b545974d Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Thu, 7 Oct 2010 06:31:08 +0200 Subject: [PATCH 14/15] Fix a compile warning on OSX 10.6 --- src/common/address.c | 2 +- src/common/address.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index c35f04c18b..dcc32f1aed 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -311,7 +311,7 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening) * brackets. */ const char * -tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate) +tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate) { const char *ptr; tor_assert(addr && dest); diff --git a/src/common/address.h b/src/common/address.h index 6116bb4b1c..457532d0df 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -144,7 +144,7 @@ int tor_addr_port_parse(const char *s, tor_addr_t *addr_out, int tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out, maskbits_t *mask_out, uint16_t *port_min_out, uint16_t *port_max_out); -const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, +const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate); int tor_addr_from_str(tor_addr_t *addr, const char *src); void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src); From c9dece14ae7d9c14c17df6685f7504c23eb65899 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 7 Oct 2010 17:10:06 -0400 Subject: [PATCH 15/15] Add some missing documentation for things added in nodes branch --- src/or/or.h | 11 +++++++++-- src/or/policies.c | 12 ++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/or/or.h b/src/or/or.h index c8616beba3..96d0d79e1a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1648,15 +1648,22 @@ typedef struct routerstatus_t { } routerstatus_t; -/** DOCDOC */ +/** A single entry in a parsed policy summary, describing a range of ports. */ typedef struct short_policy_entry_t { uint16_t min_port, max_port; } short_policy_entry_t; -/** DOCDOC */ +/** A short_poliy_t is the parsed version of a policy summary. */ typedef struct short_policy_t { + /** True if the members of 'entries' are port ranges to accept; false if + * they are port ranges to reject */ unsigned int is_accept : 1; + /** The actual number of values in 'entries'. */ unsigned int n_entries : 31; + /** An array of (probably more than 1!) short_policy_entry_t values, + * each descriping a range of ports that this policy accepts or rejects + * (depending on the value of is_accept). + */ short_policy_entry_t entries[1]; } short_policy_t; diff --git a/src/or/policies.c b/src/or/policies.c index a5b71c9e2f..2ae66df5e9 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -1315,7 +1315,8 @@ policy_summarize(smartlist_t *policy) return result; } -/** DOCDOC */ +/** Convert a summarized policy string into a short_policy_t. Return NULL + * if the string is not well-formed. */ short_policy_t * parse_short_policy(const char *summary) { @@ -1408,14 +1409,17 @@ parse_short_policy(const char *summary) return result; } -/** DOCDOC */ +/** Release all storage held in policy. */ void short_policy_free(short_policy_t *policy) { tor_free(policy); } -/** DOCDOC */ +/** See whether the addr:port address is likely to be accepted + * or rejected by the summarized policy policy. Return values are as + * for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy + * functions, requires the port be specified. */ addr_policy_result_t compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, const short_policy_t *policy) @@ -1452,7 +1456,7 @@ compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, return ADDR_POLICY_REJECTED; } -/* DOCDOC */ +/** Return true iff policy seems reject all ports */ int short_policy_is_reject_star(const short_policy_t *policy) {