commit 8b686d98c47226dfc4d7c87d6a472b592135ae07
Merge: 3256627 99621bc
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Apr 27 14:36:30 2011 -0400
Merge maint-0.2.2 for the bug1090-part1-squashed branch
Resolved conflicts in:
doc/tor.1.txt
src/or/circuitbuild.c
src/or/circuituse.c
src/or/connection_edge.c
src/or/connection_edge.h
src/or/directory.c
src/or/rendclient.c
src/or/routerlist.c
src/or/routerlist.h
These were mostly releated to the routerinfo_t->node_t conversion.
changes/bug1090-general | 73 ++++++++++++++++
changes/bug1090-launch-warning | 5 +
changes/exitnodes_reliable | 7 ++
doc/tor.1.txt | 75 ++++++++++++----
src/or/circuitbuild.c | 187 +++++++++++++++++++++++-----------------
src/or/circuitlist.c | 70 +++++++++++++++
src/or/circuitlist.h | 1 +
src/or/circuituse.c | 76 ++++++++++------
src/or/circuituse.h | 2 +
src/or/config.c | 24 +++--
src/or/connection_edge.c | 117 +++++++++++++++++++------
src/or/connection_edge.h | 4 +-
src/or/directory.c | 31 ++++++-
src/or/or.h | 11 ++-
src/or/rendclient.c | 85 ++++++++++++++++---
src/or/rendclient.h | 1 +
src/or/rendcommon.c | 2 +-
src/or/rendservice.c | 40 +++++++--
src/or/router.c | 20 ++++
src/or/routerlist.c | 73 ++++++++++++++--
src/or/routerlist.h | 8 ++-
21 files changed, 712 insertions(+), 200 deletions(-)
diff --cc doc/tor.1.txt
index 5a70cd2,866a702..f24eaba
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@@ -512,27 -508,55 +526,54 @@@ The following options are useful only f
**ExcludeExitNodes** __node__,__node__,__...__::
A list of identity fingerprints, nicknames, country codes and address
- patterns of nodes to never use when picking an exit node. Note that any
+ patterns of nodes to never use when picking an exit node---that is, a
+ node that delivers traffic for you outside the Tor network. Note that any
node listed in ExcludeNodes is automatically considered to be part of this
- list.
-
- **EntryNodes** __node__,__node__,__...__::
- A list of identity fingerprints, nicknames, country codes and address
- patterns of nodes to use for the first hop in normal circuits. These are
- treated only as preferences unless StrictNodes (see below) is also set.
+ list too. See also the caveats on the "ExitNodes" option below
-
**ExitNodes** __node__,__node__,__...__::
A list of identity fingerprints, nicknames, country codes and address
- patterns of nodes to use for the last hop in normal exit circuits. These
- are treated only as preferences unless StrictNodes (see below) is also set.
+ patterns of nodes to use as exit node---that is, a
+ node that delivers traffic for you outside the Tor network. +
+ +
+ Note that if you list too few nodes here, or if you exclude too many exit
+ nodes with ExcludeExitNodes, you can degrade functionality. For example,
+ if none of the exits you list allows traffic on port 80 or 443, you won't
+ be able to browse the web. +
+ +
+ Note also that not every circuit is used to deliver traffic outside of
+ the Tor network. It is normal to see non-exit circuits (such as those
+ used to connect to hidden services, those that do directory fetches,
+ those used for self-tests, and so on) that end at a non-exit node. To
+ keep a node from being used entirely, see ExcludeNodes and StrictNodes. +
+ +
+ The ExcludeNodes option overrides this option: any node listed in both
+ ExitNodes and ExcludeNodes is treated as excluded. +
+ +
+ The .exit address notation, if enabled, overrides this option.
+
+ **EntryNodes** __node__,__node__,__...__::
- A list of identity fingerprints and nicknames of nodes
- to use for the first hop in your normal circuits. (Country codes and
- address patterns are not yet supported.) This includes all
++ A list of identity fingerprints, nicknames, and country codes of nodes
++ to use for the first hop in your normal circuits.
++ This includes all
+ circuits except for direct connections to directory servers. The Bridge
+ option overrides this option; if you have configured bridges and
+ UseBridges is 1, the Bridges are used as your entry nodes. +
+ +
+ The ExcludeNodes option overrides this option: any node listed in both
+ EntryNodes and ExcludeNodes is treated as excluded.
**StrictNodes** **0**|**1**::
- If 1 and EntryNodes config option is set, Tor will never use any nodes
- besides those listed in EntryNodes for the first hop of a normal circuit.
- If 1 and ExitNodes config option is set, Tor will never use any nodes
- besides those listed in ExitNodes for the last hop of a normal exit
- circuit. Note that Tor might still use these nodes for non-exit circuits
- such as one-hop directory fetches or hidden service support circuits.
+ If StrictNodes is set to 1, Tor will treat the ExcludeNodes option as a
+ requirement to follow for all the circuits you generate, even if doing so
+ will break functionality for you. If StrictNodes is set to 0, Tor will
+ still try to avoid nodes in the ExcludeNodes list, but it will err on the
+ side of avoiding unexpected errors. Specifically, StrictNodes 0 tells
+ Tor that it is okay to use an excluded node when it is *necessary* to
+ perform self-tests, connect to
+ a hidden service, provide a hidden service to a client, fulfill a .exit
+ request, upload directory information, or download directory information.
+ (Default: 0)
**FascistFirewall** **0**|**1**::
If 1, Tor will only create outgoing connections to ORs running on ports
diff --cc src/or/circuitbuild.c
index ff656fd,90572d5..cc78d99
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@@ -2673,18 -2686,26 +2674,25 @@@ choose_good_exit_server_general(int nee
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
- if (node_is_unreliable(node, need_uptime, need_capacity, 0) &&
- (!options->ExitNodes ||
- !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
- * they ask for is rare. Or something. */
-
+ if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, router)) {
++ routerset_contains_node(options->_ExcludeExitNodesUnion, node)) {
n_supported[i] = -1;
- continue; /* skip routers that are not suitable, unless we have
- * ExitNodes set, in which case we asked for it */
+ continue; /* user asked us not to use it, no matter what */
+ }
+ if (options->ExitNodes &&
- !routerset_contains_router(options->ExitNodes, router)) {
++ !routerset_contains_node(options->ExitNodes, node)) {
+ n_supported[i] = -1;
+ continue; /* not one of our chosen exit nodes */
+ }
+
- if (router_is_unreliable(router, need_uptime, need_capacity, 0)) {
++ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
+ n_supported[i] = -1;
+ continue; /* skip routers that are not suitable. Don't worry if
+ * this makes us reject all the possible routers: if so,
+ * we'll retry later in this function with need_update and
+ * need_capacity set to 0. */
}
- 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.",
@@@ -2704,10 -2724,11 +2712,10 @@@
}
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), node, 1)) {
- if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) {
++ if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), node)) {
++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]);
@@@ -2741,22 -2762,13 +2749,14 @@@
/* If any routers definitely support any pending connections, choose one
* at random. */
if (best_support > 0) {
- smartlist_t *supporting = smartlist_create(), *use = smartlist_create();
+ smartlist_t *supporting = 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_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_node_disjunction(use, supporting, NULL,
- options->_ExcludeExitNodesUnion, 1);
- }
- node = node_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
- smartlist_free(use);
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
++ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
smartlist_free(supporting);
} else {
/* Either there are no pending connections, or no routers even seem to
@@@ -2786,32 -2797,20 +2785,21 @@@
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 (!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.",
// try, router->nickname);
- smartlist_add(supporting, router);
+ smartlist_add(supporting, (void*)node);
}
- }
+ } SMARTLIST_FOREACH_END(node);
- 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_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. */
- node = node_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
- if (router)
++ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ if (node)
break;
smartlist_clear(supporting);
- smartlist_clear(use);
}
SMARTLIST_FOREACH(needed_ports, uint16_t *, cp, tor_free(cp));
smartlist_free(needed_ports);
@@@ -2820,14 -2818,15 +2807,15 @@@
}
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) {
+ if (options->ExitNodes) {
log_warn(LD_CIRC,
- "No specified exit routers seem to be running, and "
- "StrictNodes is set: can't choose an exit.");
+ "No specified %sexit routers seem to be running: "
+ "can't choose an exit.",
+ options->_ExcludeExitNodesUnion ? "non-excluded " : "");
}
return NULL;
}
@@@ -3990,15 -3974,16 +3990,17 @@@ entry_guards_prepend_from_config(or_opt
/* Split entry guards into those on the list and those not. */
- /* Now that we allow countries and IP ranges in EntryNodes, this is
- * potentially an enormous list. It's not so bad though because we
- * only call this function when a) we're making a new circuit, and b)
- * we've called directory_info_has_arrived() or changed our EntryNodes
- * since the last time we made a circuit. */
- routerset_get_all_nodes(entry_nodes, options->EntryNodes, 0);
+ /* XXXX023 Now that we allow countries and IP ranges in EntryNodes, this is
+ * potentially an enormous list. For now, we disable such values for
+ * EntryNodes in options_validate(); really, this wants a better solution.
+ * 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,
- options->ExcludeNodes, 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,
++ options->ExcludeNodes, 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);
@@@ -4018,19 -4003,15 +4020,15 @@@
/* 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 */
- if (options->StrictNodes) {
- SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
- entry_guard_free(e));
- } else {
- smartlist_add_all(entry_guards, old_entry_guards_not_on_list);
- }
+ /* Finally, free the remaining previously configured guards that are not in
+ * EntryNodes. */
+ SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
+ entry_guard_free(e));
- 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);
@@@ -4098,17 -4066,19 +4084,18 @@@ choose_random_entry(cpath_build_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)
+ node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
+ if (!node)
continue; /* down, no point */
- if (r == chosen_exit)
+ if (node == chosen_exit)
continue; /* don't pick the same node for entry and exit */
- 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 0 /* since EntryNodes is always strict now, this clause is moot */
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 */
@@@ -4121,7 -4091,8 +4108,8 @@@
"No relays from EntryNodes available. Using others.");
}
}
+ #endif
- smartlist_add(live_entry_guards, 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
@@@ -4171,10 -4142,14 +4159,14 @@@
need_capacity = 0;
goto retry;
}
+ #if 0
+ /* Removing this retry logic: if we only allow one exit, and it is in the
+ same family as all our entries, then we are just plain not going to win
+ here. */
- if (!r && entry_list_is_constrained(options) && consider_exit_family) {
- /* still no? if we're using bridges,
- * and our chosen exit is in the same family as all our
- * bridges, then be flexible about families. */
+ 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. */
consider_exit_family = 0;
goto retry;
}
diff --cc src/or/circuituse.c
index e58d5e0,fd1cf6b..30fd818
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@@ -128,7 -127,7 +128,7 @@@ circuit_is_acceptable(circuit_t *circ,
return 0;
}
}
- if (exitnode && !connection_ap_can_use_exit(conn, exitnode, 0)) {
- if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) {
++ if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
/* can't exit from this router */
return 0;
}
@@@ -505,14 -511,14 +512,14 @@@ circuit_stream_is_being_handled(edge_co
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, exitnode, 0);
- ok = connection_ap_can_use_exit(conn, exitrouter);
++ ok = connection_ap_can_use_exit(conn, exitnode);
} 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) {
@@@ -1279,11 -1293,12 +1286,12 @@@ circuit_get_open_circ_or_launch(edge_co
} else {
/* XXXX023 Duplicates checks in connection_ap_handshake_attach_circuit:
* refactor into a single function? */
- 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 (node && !connection_ap_can_use_exit(conn, node, 0)) {
- if (router && !connection_ap_can_use_exit(conn, router)) {
++ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
- "Requested exit point '%s' would refuse request. %s.",
+ "Requested exit point '%s' is excluded or "
+ "would refuse request. %s.",
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
if (opt) {
conn->chosen_exit_optional = 0;
@@@ -1601,9 -1627,10 +1620,10 @@@ connection_ap_handshake_attach_circuit(
}
return -1;
}
- if (node && !connection_ap_can_use_exit(conn, node, 0)) {
- if (router && !connection_ap_can_use_exit(conn, router)) {
++ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
- "Requested exit point '%s' would refuse request. %s.",
+ "Requested exit point '%s' is excluded or "
+ "would refuse request. %s.",
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
if (opt) {
conn->chosen_exit_optional = 0;
diff --cc src/or/connection_edge.c
index 508b06b,082cd5f..29ab6c5
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@@ -808,6 -809,56 +809,56 @@@ clear_trackexithost_mappings(const cha
tor_free(suffix);
}
+ /** Remove all TRACKEXIT mappings from the addressmap for which the target
+ * host is unknown or no longer allowed. */
+ void
+ addressmap_clear_excluded_trackexithosts(or_options_t *options)
+ {
+ const routerset_t *allow_nodes = options->ExitNodes;
+ const routerset_t *exclude_nodes = options->_ExcludeExitNodesUnion;
+
+ if (!addressmap)
+ return;
+ if (routerset_is_empty(allow_nodes))
+ allow_nodes = NULL;
+ if (allow_nodes == NULL && routerset_is_empty(exclude_nodes))
+ return;
+
+ STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) {
+ size_t len;
+ const char *target = ent->new_address, *dot;
+ char *nodename;
- routerinfo_t *ri; /* XXX023 Use node_t. */
++ const node_t *node;
+
+ if (strcmpend(target, ".exit")) {
+ /* Not a .exit mapping */
+ continue;
+ } else if (ent->source != ADDRMAPSRC_TRACKEXIT) {
+ /* Not a trackexit mapping. */
+ continue;
+ }
+ len = strlen(target);
+ if (len < 6)
+ continue; /* malformed. */
+ dot = target + len - 6; /* dot now points to just before .exit */
+ dot = strrchr(dot, '.'); /* dot now points to the . before .exit or NULL */
+ if (!dot) {
+ nodename = tor_strndup(target, len-5);
+ } else {
+ nodename = tor_strndup(dot+1, strlen(dot+1)-5);
+ }
- ri = router_get_by_nickname(nodename, 0);
++ node = node_get_by_nickname(nodename, 0);
+ tor_free(nodename);
- if (!ri ||
- (allow_nodes && !routerset_contains_router(allow_nodes, ri)) ||
- routerset_contains_router(exclude_nodes, ri)) {
++ if (!node ||
++ (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||
++ routerset_contains_node(exclude_nodes, node)) {
+ /* We don't know this one, or we want to be rid of it. */
+ addressmap_ent_remove(address, ent);
+ MAP_DEL_CURRENT(address);
+ }
+ } STRMAP_FOREACH_END;
+ }
+
/** Remove all entries from the addressmap that were set via the
* configuration file or the command line. */
void
@@@ -1607,10 -1662,19 +1662,18 @@@ connection_ap_handshake_rewrite_and_att
/* foo.exit -- modify conn->chosen_exit_node to specify the exit
* node, and conn->address to hold only the address portion. */
char *s = strrchr(socks->address,'.');
+
+ /* If StrictNodes is not set, then .exit overrides ExcludeNodes. */
+ routerset_t *excludeset = options->StrictNodes ?
+ options->_ExcludeExitNodesUnion : options->ExcludeExitNodes;
- /*XXX023 make this a node_t. */
- routerinfo_t *router;
++ const node_t *node;
+
tor_assert(!automap);
if (s) {
+ /* The address was of the form "(stuff).(name).exit */
if (s[1] != '\0') {
conn->chosen_exit_name = tor_strdup(s+1);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
++ node = node_get_by_nickname(conn->chosen_exit_name, 1);
if (remapped_to_exit) /* 5 tries before it expires the addressmap */
conn->chosen_exit_retries = TRACKHOSTEXITS_RETRIES;
*s = 0;
@@@ -1623,20 -1688,33 +1687,34 @@@
return -1;
}
} else {
- const node_t *r;
+ /* It looks like they just asked for "foo.exit". */
++
conn->chosen_exit_name = tor_strdup(socks->address);
- r = node_get_by_nickname(conn->chosen_exit_name, 1);
- *socks->address = 0;
- if (r) {
- node_get_address_string(r, socks->address, sizeof(socks->address));
- } else {
- log_warn(LD_APP,
- "Unrecognized server in exit address '%s.exit'. Refusing.",
- safe_str_client(socks->address));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
- return -1;
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (router) {
++ node = node_get_by_nickname(conn->chosen_exit_name, 1);
++ if (node) {
+ *socks->address = 0;
- strlcpy(socks->address, router->address, sizeof(socks->address));
++ node_get_address_string(node, socks->address, sizeof(socks->address));
}
}
+ /* Now make sure that the chosen exit exists... */
- if (!router) {
++ if (!node) {
+ log_warn(LD_APP,
+ "Unrecognized relay in exit address '%s.exit'. Refusing.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+ /* ...and make sure that it isn't excluded. */
- if (routerset_contains_router(excludeset, router)) {
++ if (routerset_contains_node(excludeset, node)) {
+ log_warn(LD_APP,
+ "Excluded relay in exit address '%s.exit'. Refusing.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+ /* XXXX022-1090 Should we also allow foo.bar.exit if ExitNodes is set and
+ Bar is not listed in it? I say yes, but our revised manpage branch
+ implies no. */
}
if (addresstype != ONION_HOSTNAME) {
@@@ -2977,13 -3044,9 +3055,9 @@@ connection_edge_is_rendezvous_stream(ed
* to exit from it, or 0 if it probably will not allow it.
* (We might be uncertain if conn's destination address has not yet been
* resolved.)
- *
- * If <b>excluded_means_no</b> is 1 and Exclude*Nodes is set and excludes
- * this relay, return 0.
*/
int
- connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit,
- int excluded_means_no)
-connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
++connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit)
{
or_options_t *options = get_options();
@@@ -3027,17 -3096,8 +3101,8 @@@
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.
- *
- * If we don't have StrictNodes set, then this function gets called in
- * two contexts. First, we've got a circuit open and we want to know
- * whether we can use it. In that case, we somehow built this circuit
- * despite having the last hop in ExcludeExitNodes, so we should be
- * willing to use it. Second, we are evaluating whether this is an
- * acceptable exit for a new circuit. In that case, skip it. */
+ /* Not a suitable exit. Refuse it. */
return 0;
}
diff --cc src/or/connection_edge.h
index 62a79db,70d0dd2..562db5b
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@@ -48,9 -47,7 +48,8 @@@ int connection_exit_begin_conn(cell_t *
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 node_t *exit,
- int excluded_means_no);
++ const node_t *exit);
void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
void connection_ap_fail_onehop(const char *failed_digest,
diff --cc src/or/directory.c
index 6bef581,0c095fe..33ebf52
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@@ -296,6 -291,16 +300,16 @@@ directory_post_to_dirservers(uint8_t di
if ((type & ds->type) == 0)
continue;
+ if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, rs)) {
++ routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
+ log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
+ "it's in our ExcludedNodes list and StrictNodes is set. "
+ "Skipping.",
+ ds->nickname,
+ dir_conn_purpose_to_string(dir_purpose));
+ continue;
+ }
+
found = 1; /* at least one authority of this type was listed */
if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
ds->has_accepted_serverdesc = 0;
@@@ -527,13 -510,15 +541,15 @@@ directory_initiate_command_routerstatus
time_t if_modified_since,
const rend_data_t *rend_query)
{
+ or_options_t *options = get_options();
- 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);
+ node = node_get_by_id(status->identity_digest);
+
- if (!router && anonymized_connection) {
+ 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;
@@@ -546,6 -530,17 +562,17 @@@
address = address_buf;
}
tor_addr_from_ipv4h(&addr, status->addr);
+
+ if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
++ routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
+ log_warn(LD_DIR, "Wanted to contact directory mirror '%s' for %s, but "
+ "it's in our ExcludedNodes list and StrictNodes is set. "
+ "Skipping. This choice might make your Tor not work.",
+ status->nickname,
+ dir_conn_purpose_to_string(dir_purpose));
+ return;
+ }
+
directory_initiate_command_rend(address, &addr,
status->or_port, status->dir_port,
status->version_supports_conditional_consensus,
diff --cc src/or/rendclient.c
index 47161eb,65e632f..da6cfa3
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@@ -753,29 -753,78 +756,78 @@@ rend_client_get_random_intro(const rend
return NULL;
}
+ /* See if we can get a node that complies with ExcludeNodes */
+ if ((result = rend_client_get_random_intro_impl(entry, 1, 1)))
+ return result;
+ /* If not, and StrictNodes is not set, see if we can return any old node
+ */
+ if (!get_options()->StrictNodes)
+ return rend_client_get_random_intro_impl(entry, 0, 1);
+ return NULL;
+ }
+
+ /** As rend_client_get_random_intro, except assume that StrictNodes is set
+ * iff <b>strict</b> is true. If <b>warnings</b> is false, don't complain
+ * to the user when we're out of nodes, even if StrictNodes is true.
+ */
+ static extend_info_t *
+ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
+ const int strict,
+ const int warnings)
+ {
+ int i;
+
+ rend_intro_point_t *intro;
- routerinfo_t *router;
+ or_options_t *options = get_options();
+ smartlist_t *usable_nodes;
+ int n_excluded = 0;
+
+ /* We'll keep a separate list of the usable nodes. If this becomes empty,
+ * no nodes are usable. */
+ usable_nodes = smartlist_create();
+ smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
+
again:
- if (smartlist_len(entry->parsed->intro_nodes) == 0)
+ if (smartlist_len(usable_nodes) == 0) {
+ if (n_excluded && get_options()->StrictNodes && warnings) {
+ /* We only want to warn if StrictNodes is really set. Otherwise
+ * we're just about to retry anyways.
+ */
+ log_warn(LD_REND, "All introduction points for hidden service are "
+ "at excluded relays, and StrictNodes is set. Skipping.");
+ }
+ smartlist_free(usable_nodes);
return NULL;
+ }
- i = crypto_rand_int(smartlist_len(entry->parsed->intro_nodes));
- intro = smartlist_get(entry->parsed->intro_nodes, i);
+ i = crypto_rand_int(smartlist_len(usable_nodes));
+ intro = smartlist_get(usable_nodes, i);
/* Do we need to look up the router or is the extend info complete? */
if (!intro->extend_info->onion_key) {
+ const node_t *node;
if (tor_digest_is_zero(intro->extend_info->identity_digest))
- router = router_get_by_hexdigest(intro->extend_info->nickname);
+ node = node_get_by_hex_id(intro->extend_info->nickname);
else
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node) {
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
intro->extend_info->nickname);
- rend_intro_point_free(intro);
- smartlist_del(entry->parsed->intro_nodes, i);
+ smartlist_del(usable_nodes, i);
goto again;
}
extend_info_free(intro->extend_info);
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
}
+ /* Check if we should refuse to talk to this router. */
+ if (options->ExcludeNodes && strict &&
+ routerset_contains_extendinfo(options->ExcludeNodes,
+ intro->extend_info)) {
+ n_excluded++;
+ smartlist_del(usable_nodes, i);
+ goto again;
+ }
+
+ smartlist_free(usable_nodes);
return extend_info_dup(intro->extend_info);
}
diff --cc src/or/router.c
index eb4d6b5,0ef4728..8edbb47
--- a/src/or/router.c
+++ b/src/or/router.c
@@@ -849,14 -847,33 +849,34 @@@ decide_to_advertise_dirport(or_options_
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;
+ or_options_t *options = get_options();
if (!me)
return;
- if (routerset_contains_router(options->ExcludeNodes, me) &&
++ if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
+ options->StrictNodes) {
+ /* If we've excluded ourself, and StrictNodes is set, we can't test
+ * ourself. */
+ if (test_or || test_dir) {
+ #define SELF_EXCLUDED_WARN_INTERVAL 3600
+ static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL);
+ char *msg;
+ if ((msg = rate_limit_log(&warning_limit, approx_time()))) {
+ log_warn(LD_CIRC, "Can't peform self-tests for this relay: we have "
+ "listed ourself in ExcludeNodes, and StrictNodes is set. "
+ "We cannot learn whether we are usable, and will not "
+ "be able to advertise ourself.%s", msg);
+ tor_free(msg);
+ }
+ }
+ 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);
diff --cc src/or/routerlist.c
index 8c68a34,d9f099b..d5dc478
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@@ -1072,10 -1067,11 +1072,11 @@@ router_pick_trusteddirserver(authority_
* 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)
{
+ or_options_t *options = get_options();
- routerstatus_t *result;
+ const node_t *result;
smartlist_t *direct, *tunnel;
smartlist_t *trusted_direct, *trusted_tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
@@@ -1096,19 -1095,16 +1100,20 @@@
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;
++ const country_t country = node->country;
+ if (!status)
continue;
- if (status->is_bad_directory)
+
+ if (!node->is_running || !status->dir_port || !node->is_valid)
+ continue;
+ if (node->is_bad_directory)
continue;
- if (requireother && router_digest_is_me(status->identity_digest))
+ if (requireother && router_digest_is_me(node->identity))
continue;
if (type & V3_AUTHORITY) {
if (!(status->version_supports_v3_dir ||
@@@ -1116,17 -1112,20 +1121,23 @@@
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;
+ if (try_excluding && options->ExcludeNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
++ routerset_contains_routerstatus(options->ExcludeNodes, status,
++ country)) {
+ ++n_excluded;
+ 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 &&
@@@ -1165,7 -1164,16 +1176,16 @@@
smartlist_free(trusted_tunnel);
smartlist_free(overloaded_direct);
smartlist_free(overloaded_tunnel);
+
+ if (result == NULL && try_excluding && !options->StrictNodes && n_excluded) {
+ /* If we got no result, and we are excluding nodes, and StrictNodes is
+ * not set, try again without excluding nodes. */
+ try_excluding = 0;
+ n_excluded = 0;
+ goto retry_without_exclude;
+ }
+
- return result;
+ return result ? result->rs : NULL;
}
/** Choose randomly from among the trusted dirservers that are up. Flags
@@@ -1175,17 -1183,18 +1195,19 @@@ static const routerstatus_t
router_pick_trusteddirserver_impl(authority_type_t type, int flags,
int *n_busy_out)
{
+ or_options_t *options = get_options();
smartlist_t *direct, *tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *result;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *result;
time_t now = time(NULL);
const int requireother = ! (flags & PDS_ALLOW_SELF);
const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
const int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS);
const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH);
+ const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH);
int n_busy = 0;
+ int try_excluding = 1, n_excluded = 0;
if (!trusted_dir_servers)
return NULL;
@@@ -1208,6 -1219,12 +1232,12 @@@
continue;
if (requireother && me && router_digest_is_me(d->digest))
continue;
+ if (try_excluding && options->ExcludeNodes &&
+ routerset_contains_routerstatus(options->ExcludeNodes,
- &d->fake_status)) {
++ &d->fake_status, -1)) {
+ ++n_excluded;
+ continue;
+ }
/* XXXX IP6 proposal 118 */
tor_addr_from_ipv4h(&addr, d->addr);
@@@ -1364,45 -1380,21 +1403,45 @@@ nodelist_add_node_family(smartlist_t *s
}
/* 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);
++ routerset_get_all_nodes(sl, rs, NULL, 0);
+ }
+ });
+ }
+}
+
+/** Given a <b>router</b>, add every node_t in its family to <b>sl</b>.
+ *
+ * Note the type mismatch: This function takes a routerinfo, but adds nodes
+ * to the smartlist!
+ */
+static void
+routerlist_add_nodes_in_family(smartlist_t *sl, const routerinfo_t *router)
+{
+ /* 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, node);
}
-/** Return true iff r is named by some nickname in <b>lst</b>. */
+/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */
static INLINE int
-router_in_nickname_smartlist(smartlist_t *lst, 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;
}
@@@ -1512,10 -1538,12 +1551,12 @@@ routerlist_find_my_routerinfo(void
/** Find a router that's up, that has this IP address, and
* that allows exit to this address:port, or return NULL if there
* isn't a good one.
+ * Don't exit enclave to excluded relays -- it wouldn't actually
+ * hurt anything, but this way there are fewer confused users.
*/
-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;
@@@ -1526,12 -1555,14 +1568,13 @@@
tor_addr_from_ipv4h(&a, addr);
- SMARTLIST_FOREACH(routerlist->routers, 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)
+ ADDR_POLICY_ACCEPTED &&
- !routerset_contains_router(options->_ExcludeExitNodesUnion, router))
- return router;
++ !routerset_contains_node(options->_ExcludeExitNodesUnion, node))
+ return node;
});
return NULL;
}
@@@ -5564,55 -5552,50 +5607,59 @@@ routerset_contains_routerstatus(const r
rs->or_port,
rs->nickname,
rs->identity_digest,
- rs->is_named,
- -1);
+ country);
+}
+
+/** Return true iff <b>node</b> is in <b>set</b>. */
+int
+routerset_contains_node(const routerset_t *set, const node_t *node)
+{
+ if (node->rs)
+ return routerset_contains_routerstatus(set, node->rs, node->country);
+ else if (node->ri)
+ return routerset_contains_router(set, node->ri, node->country);
+ else
+ return 0;
}
-/** Add every known routerinfo_t that is a member of <b>routerset</b> to
+/** Add every known node_t that is a member of <b>routerset</b> to
- * <b>out</b>. If <b>running_only</b>, only add the running ones. */
+ * <b>out</b>, but never add any that are part of <b>excludeset</b>.
+ * If <b>running_only</b>, only add the running ones. */
void
-routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset, int running_only)
-{
+routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
- int running_only)
++ const routerset_t *excludeset, 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)). */
+ * we can do a lookup in O(len(routerset)). */
SMARTLIST_FOREACH(routerset->list, const char *, name, {
- routerinfo_t *router = router_get_by_nickname(name, 1);
- if (router) {
- if (!running_only || router->is_running)
- if (!routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ const node_t *node = node_get_by_nickname(name, 1);
+ if (node) {
+ if (!running_only || node->is_running)
- smartlist_add(out, (void*)node);
++ if (!routerset_contains_node(excludeset, node))
++ 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_node(routerset, node))
- if (routerset_contains_router(routerset, router) &&
- !routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
++ if (routerset_contains_node(routerset, node) &&
++ !routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
});
}
}
+ #if 0
-/** Add to <b>target</b> every routerinfo_t from <b>source</b> except:
+/** Add to <b>target</b> every node_t from <b>source</b> except:
*
* 1) Don't add it if <b>include</b> is non-empty and the relay isn't in
* <b>include</b>; and
@@@ -5642,11 -5625,12 +5689,12 @@@ routersets_get_node_disjunction(smartli
}
});
}
+ #endif
-/** Remove every routerinfo_t from <b>lst</b> that is in <b>routerset</b>. */
+/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */
void
-routerset_subtract_routers(smartlist_t *lst, const routerset_t *routerset)
-{
+routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset)
+{ /*XXXX MOVE ? */
tor_assert(lst);
if (!routerset)
return;
diff --cc src/or/routerlist.h
index bb7a098,fec1870..794fc0c
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@@ -169,25 -167,28 +169,31 @@@ int routerset_parse(routerset_t *target
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_is_empty(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,
+ country_t country);
int routerset_contains_routerstatus(const routerset_t *set,
- 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,
- const routerset_t *excludeset,
- int running_only);
++
+int routerset_contains_node(const routerset_t *set, const node_t *node);
+void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
++ const routerset_t *excludeset,
+ int running_only);
+ #if 0
-void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
+void routersets_get_node_disjunction(smartlist_t *target,
+ const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only);
+ #endif
-void routerset_subtract_routers(smartlist_t *out,
+void routerset_subtract_nodes(smartlist_t *out,
- const routerset_t *routerset);
+ 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,