summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2015-02-11 15:06:04 -0500
committerNick Mathewson <nickm@torproject.org>2015-02-11 15:06:04 -0500
commitcaf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc (patch)
treedb5e6003cc8cec5f27ba0e91449348518ea98455 /src/or
parent0c81dfa848da160b02818771626a425cd27b86bc (diff)
parent0899f51bc6abf535c6c55b81b98b959235b0f7c7 (diff)
downloadtor-caf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc.tar.gz
tor-caf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc.zip
Merge branch 'bug12844'
Conflicts: src/or/circuituse.c src/test/include.am src/test/test_entrynodes.c
Diffstat (limited to 'src/or')
-rw-r--r--src/or/circuitbuild.c87
-rw-r--r--src/or/circuitbuild.h3
-rw-r--r--src/or/circuituse.c12
-rw-r--r--src/or/config.c13
-rw-r--r--src/or/or.h3
-rw-r--r--src/or/routerlist.c2
-rw-r--r--src/or/routerlist.h4
7 files changed, 117 insertions, 7 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index fa5a2f5242..57056b2a66 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1737,6 +1737,83 @@ choose_good_exit_server_general(int need_uptime, int need_capacity)
return NULL;
}
+#if defined(ENABLE_TOR2WEB_MODE) || defined(TOR_UNIT_TESTS)
+/* The config option Tor2webRendezvousPoints has been set and we need
+ * to pick an RP out of that set. Make sure that the RP we choose is
+ * alive, and return it. Return NULL if no usable RP could be found in
+ * Tor2webRendezvousPoints. */
+STATIC const node_t *
+pick_tor2web_rendezvous_node(router_crn_flags_t flags,
+ const or_options_t *options)
+{
+ const node_t *rp_node = NULL;
+ const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
+ const int need_desc = (flags & CRN_NEED_DESC) != 0;
+
+ smartlist_t *whitelisted_live_rps = smartlist_new();
+ smartlist_t *all_live_nodes = smartlist_new();
+
+ tor_assert(options->Tor2webRendezvousPoints);
+
+ /* Add all running nodes to all_live_nodes */
+ router_add_running_nodes_to_smartlist(all_live_nodes,
+ allow_invalid,
+ 0, 0, 0,
+ need_desc);
+
+ /* Filter all_live_nodes to only add live *and* whitelisted RPs to
+ * the list whitelisted_live_rps. */
+ SMARTLIST_FOREACH_BEGIN(all_live_nodes, node_t *, live_node) {
+ if (routerset_contains_node(options->Tor2webRendezvousPoints, live_node)) {
+ smartlist_add(whitelisted_live_rps, live_node);
+ }
+ } SMARTLIST_FOREACH_END(live_node);
+
+ /* Honor ExcludeNodes */
+ if (options->ExcludeNodes) {
+ routerset_subtract_nodes(whitelisted_live_rps, options->ExcludeNodes);
+ }
+
+ /* Now pick randomly amongst the whitelisted RPs. No need to waste time
+ doing bandwidth load balancing, for most use cases
+ 'whitelisted_live_rps' contains a single OR anyway. */
+ rp_node = smartlist_choose(whitelisted_live_rps);
+
+ if (!rp_node) {
+ log_warn(LD_REND, "Could not find a Rendezvous Point that suits "
+ "the purposes of Tor2webRendezvousPoints. Choosing random one.");
+ }
+
+ smartlist_free(whitelisted_live_rps);
+ smartlist_free(all_live_nodes);
+
+ return rp_node;
+}
+#endif
+
+/* Pick a Rendezvous Point for our HS circuits according to <b>flags</b>. */
+static const node_t *
+pick_rendezvous_node(router_crn_flags_t flags)
+{
+ const or_options_t *options = get_options();
+
+ if (options->AllowInvalid_ & ALLOW_INVALID_RENDEZVOUS)
+ flags |= CRN_ALLOW_INVALID;
+
+#ifdef ENABLE_TOR2WEB_MODE
+ /* The user wants us to pick specific RPs. */
+ if (options->Tor2webRendezvousPoints) {
+ const node_t *tor2web_rp = pick_tor2web_rendezvous_node(flags, options);
+ if (tor2web_rp) {
+ return tor2web_rp;
+ }
+ /* Else, if no tor2web RP was found, fall back to choosing a random node */
+ }
+#endif
+
+ return router_choose_random_node(NULL, options->ExcludeNodes, flags);
+}
+
/** Return a pointer to a suitable router to be the exit node for the
* circuit of purpose <b>purpose</b> that we're about to build (or NULL
* if no router is suitable).
@@ -1767,9 +1844,13 @@ choose_good_exit_server(uint8_t purpose,
else
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;
- return router_choose_random_node(NULL, options->ExcludeNodes, flags);
+ {
+ /* Pick a new RP */
+ const node_t *rendezvous_node = pick_rendezvous_node(flags);
+ log_info(LD_REND, "Picked new RP: %s",
+ safe_str_client(node_describe(rendezvous_node)));
+ return rendezvous_node;
+ }
}
log_warn(LD_BUG,"Unhandled purpose %d", purpose);
tor_fragile_assert();
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index c72016d530..ddf86416fc 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -61,6 +61,9 @@ const node_t *choose_good_entry_server(uint8_t purpose,
#ifdef CIRCUITBUILD_PRIVATE
STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan);
+STATIC const node_t *pick_tor2web_rendezvous_node(router_crn_flags_t flags,
+ const or_options_t *options);
+
#endif
#endif
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 612b536bad..c463b0a40f 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -1677,6 +1677,7 @@ circuit_launch_by_extend_info(uint8_t purpose,
origin_circuit_t *circ;
int onehop_tunnel = (flags & CIRCLAUNCH_ONEHOP_TUNNEL) != 0;
int have_path = have_enough_path_info(! (flags & CIRCLAUNCH_IS_INTERNAL) );
+ int need_specific_rp = 0;
if (!onehop_tunnel && (!router_have_minimum_dir_info() || !have_path)) {
log_debug(LD_CIRC,"Haven't %s yet; canceling "
@@ -1687,8 +1688,17 @@ circuit_launch_by_extend_info(uint8_t purpose,
return NULL;
}
+ /* If Tor2webRendezvousPoints is enabled and we are dealing with an
+ RP circuit, we want a specific RP node so we shouldn't canibalize
+ an already existing circuit. */
+ if (get_options()->Tor2webRendezvousPoints &&
+ purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
+ need_specific_rp = 1;
+ }
+
if ((extend_info || purpose != CIRCUIT_PURPOSE_C_GENERAL) &&
- purpose != CIRCUIT_PURPOSE_TESTING && !onehop_tunnel) {
+ purpose != CIRCUIT_PURPOSE_TESTING &&
+ !onehop_tunnel && !need_specific_rp) {
/* see if there are appropriate circs available to cannibalize. */
/* XXX if we're planning to add a hop, perhaps we want to look for
* internal circs rather than exit circs? -RD */
diff --git a/src/or/config.c b/src/or/config.c
index de0baa40d9..ad4fd45846 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -80,6 +80,7 @@ static config_abbrev_t option_abbrevs_[] = {
PLURAL(AuthDirRejectCC),
PLURAL(EntryNode),
PLURAL(ExcludeNode),
+ PLURAL(Tor2webRendezvousPoint),
PLURAL(FirewallPort),
PLURAL(LongLivedPort),
PLURAL(HiddenServiceNode),
@@ -404,6 +405,7 @@ static config_var_t option_vars_[] = {
V(TestSocks, BOOL, "0"),
V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
V(Tor2webMode, BOOL, "0"),
+ V(Tor2webRendezvousPoints, ROUTERSET, NULL),
V(TLSECGroup, STRING, NULL),
V(TrackHostExits, CSV, NULL),
V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
@@ -1262,7 +1264,8 @@ options_need_geoip_info(const or_options_t *options, const char **reason_out)
routerset_needs_geoip(options->EntryNodes) ||
routerset_needs_geoip(options->ExitNodes) ||
routerset_needs_geoip(options->ExcludeExitNodes) ||
- routerset_needs_geoip(options->ExcludeNodes);
+ routerset_needs_geoip(options->ExcludeNodes) ||
+ routerset_needs_geoip(options->Tor2webRendezvousPoints);
if (routerset_usage && reason_out) {
*reason_out = "We've been configured to use (or avoid) nodes in certain "
@@ -1395,7 +1398,7 @@ options_act(const or_options_t *old_options)
log_err(LD_CONFIG, "This copy of Tor was not compiled to run in "
"'tor2web mode'. It cannot be run with the Tor2webMode torrc "
"option enabled. To enable Tor2webMode recompile with the "
- "--enable-tor2webmode option.");
+ "--enable-tor2web-mode option.");
return -1;
}
#endif
@@ -1651,6 +1654,8 @@ options_act(const or_options_t *old_options)
options->ExcludeExitNodes) ||
!routerset_equal(old_options->EntryNodes, options->EntryNodes) ||
!routerset_equal(old_options->ExitNodes, options->ExitNodes) ||
+ !routerset_equal(old_options->Tor2webRendezvousPoints,
+ options->Tor2webRendezvousPoints) ||
options->StrictNodes != old_options->StrictNodes) {
log_info(LD_CIRC,
"Changed to using entry guards or bridges, or changed "
@@ -3057,6 +3062,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->UseEntryGuards = 0;
}
+ if (options->Tor2webRendezvousPoints && !options->Tor2webMode) {
+ REJECT("Tor2webRendezvousPoints cannot be set without Tor2webMode.");
+ }
+
if (!(options->UseEntryGuards) &&
(options->RendConfigLines != NULL)) {
log_warn(LD_CONFIG,
diff --git a/src/or/or.h b/src/or/or.h
index 5d70798d8e..560f5ff5b7 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3567,6 +3567,9 @@ typedef struct {
* circuits.) */
int Tor2webMode;
+ /** A routerset that should be used when picking RPs for HS circuits. */
+ routerset_t *Tor2webRendezvousPoints;
+
/** Close hidden service client circuits immediately when they reach
* the normal circuit-build timeout, even if they have already sent
* an INTRODUCE1 cell on its way to the service. */
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index fe92ac0050..64c43c298b 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -1775,7 +1775,7 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
-static void
+void
router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
int need_uptime, int need_capacity,
int need_guard, int need_desc)
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index f106ca2316..78c3fbb880 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -58,6 +58,10 @@ const routerstatus_t *router_pick_fallback_dirserver(dirinfo_type_t type,
int router_get_my_share_of_directory_requests(double *v3_share_out);
void router_reset_status_download_failures(void);
int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
+void router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
+ int need_uptime, int need_capacity,
+ int need_guard, int need_desc);
+
const routerinfo_t *routerlist_find_my_routerinfo(void);
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);