summaryrefslogtreecommitdiff
path: root/src/or/directory.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-12-16 11:20:59 -0500
committerNick Mathewson <nickm@torproject.org>2016-12-16 11:20:59 -0500
commit2cee38f76a46860e2fb29fbd95ba36b332aa38c6 (patch)
tree3b2cbaeff1472c8d23c18f3e88bc4735bbb22bcc /src/or/directory.c
parentb310929ee36f0a88389dca53124506115c850c3b (diff)
parent20292ec4974b777d430e7962cc38349c5f82b220 (diff)
downloadtor-2cee38f76a46860e2fb29fbd95ba36b332aa38c6.tar.gz
tor-2cee38f76a46860e2fb29fbd95ba36b332aa38c6.zip
Merge branch 'prop271_030_v1_squashed'
Diffstat (limited to 'src/or/directory.c')
-rw-r--r--src/or/directory.c101
1 files changed, 78 insertions, 23 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index 84623593ab..1c9ee96c43 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -7,6 +7,7 @@
#include "or.h"
#include "backtrace.h"
+#include "bridges.h"
#include "buffers.h"
#include "circuitbuild.h"
#include "config.h"
@@ -127,7 +128,8 @@ static void directory_initiate_command_rend(
const char *payload,
size_t payload_len,
time_t if_modified_since,
- const rend_data_t *rend_query);
+ const rend_data_t *rend_query,
+ circuit_guard_state_t *guard_state);
static void connection_dir_close_consensus_fetches(
dir_connection_t *except_this_one, const char *resource);
@@ -421,7 +423,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
directory_initiate_command_routerstatus(rs, dir_purpose,
router_purpose,
indirection,
- NULL, payload, upload_len, 0);
+ NULL, payload, upload_len, 0,
+ NULL);
} SMARTLIST_FOREACH_END(ds);
if (!found) {
char *s = authdir_type_to_string(type);
@@ -457,7 +460,8 @@ should_use_directory_guards(const or_options_t *options)
* information of type <b>type</b>, and return its routerstatus. */
static const routerstatus_t *
directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
- uint8_t dir_purpose)
+ uint8_t dir_purpose,
+ circuit_guard_state_t **guard_state_out)
{
const routerstatus_t *rs = NULL;
const or_options_t *options = get_options();
@@ -466,7 +470,7 @@ directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
log_warn(LD_BUG, "Called when we have UseBridges set.");
if (should_use_directory_guards(options)) {
- const node_t *node = choose_random_dirguard(type);
+ const node_t *node = guards_choose_dirguard(type, guard_state_out);
if (node)
rs = node->rs;
} else {
@@ -547,6 +551,7 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
if (!options->FetchServerDescriptors)
return;
+ circuit_guard_state_t *guard_state = NULL;
if (!get_via_tor) {
if (options->UseBridges && !(type & BRIDGE_DIRINFO)) {
/* We want to ask a running bridge for which we have a descriptor.
@@ -555,25 +560,35 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
* sort of dir fetch we'll be doing, so it won't return a bridge
* that can't answer our question.
*/
- const node_t *node = choose_random_dirguard(type);
+ const node_t *node = guards_choose_dirguard(type,
+ &guard_state);
if (node && node->ri) {
/* every bridge has a routerinfo. */
routerinfo_t *ri = node->ri;
/* clients always make OR connections to bridges */
tor_addr_port_t or_ap;
+ tor_addr_port_t nil_dir_ap;
/* we are willing to use a non-preferred address if we need to */
fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
&or_ap);
- directory_initiate_command(&or_ap.addr, or_ap.port,
- NULL, 0, /*no dirport*/
- ri->cache_info.identity_digest,
- dir_purpose,
- router_purpose,
- DIRIND_ONEHOP,
- resource, NULL, 0, if_modified_since);
- } else
+ tor_addr_make_null(&nil_dir_ap.addr, AF_INET);
+ nil_dir_ap.port = 0;
+ directory_initiate_command_rend(&or_ap,
+ &nil_dir_ap,
+ ri->cache_info.identity_digest,
+ dir_purpose,
+ router_purpose,
+ DIRIND_ONEHOP,
+ resource, NULL, 0, if_modified_since,
+ NULL, guard_state);
+ } else {
+ if (guard_state) {
+ entry_guard_cancel(&guard_state);
+ }
log_notice(LD_DIR, "Ignoring directory request, since no bridge "
"nodes are available yet.");
+ }
+
return;
} else {
if (prefer_authority || (type & BRIDGE_DIRINFO)) {
@@ -604,9 +619,9 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
}
}
if (!rs && !(type & BRIDGE_DIRINFO)) {
- /* */
rs = directory_pick_generic_dirserver(type, pds_flags,
- dir_purpose);
+ dir_purpose,
+ &guard_state);
if (!rs)
get_via_tor = 1; /* last resort: try routing it via Tor */
}
@@ -629,7 +644,8 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
router_purpose,
indirection,
resource, NULL, 0,
- if_modified_since);
+ if_modified_since,
+ guard_state);
} else {
log_notice(LD_DIR,
"While fetching directory info, "
@@ -663,7 +679,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
rs = &ds->fake_status;
directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
DIRIND_ONEHOP, resource, NULL,
- 0, 0);
+ 0, 0, NULL);
} SMARTLIST_FOREACH_END(ds);
}
@@ -774,7 +790,8 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
const char *payload,
size_t payload_len,
time_t if_modified_since,
- const rend_data_t *rend_query)
+ const rend_data_t *rend_query,
+ circuit_guard_state_t *guard_state)
{
const or_options_t *options = get_options();
const node_t *node;
@@ -829,7 +846,8 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
dir_purpose, router_purpose,
indirection, resource,
payload, payload_len, if_modified_since,
- rend_query);
+ rend_query,
+ guard_state);
}
/** Launch a new connection to the directory server <b>status</b> to
@@ -854,13 +872,15 @@ MOCK_IMPL(void, directory_initiate_command_routerstatus,
const char *resource,
const char *payload,
size_t payload_len,
- time_t if_modified_since))
+ time_t if_modified_since,
+ circuit_guard_state_t *guard_state))
{
directory_initiate_command_routerstatus_rend(status, dir_purpose,
router_purpose,
indirection, resource,
payload, payload_len,
- if_modified_since, NULL);
+ if_modified_since, NULL,
+ guard_state);
}
/** Return true iff <b>conn</b> is the client side of a directory connection
@@ -888,6 +908,11 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
static void
connection_dir_request_failed(dir_connection_t *conn)
{
+ if (conn->guard_state) {
+ /* We haven't seen a success on this guard state, so consider it to have
+ * failed. */
+ entry_guard_failed(&conn->guard_state);
+ }
if (directory_conn_is_self_reachability_test(conn)) {
return; /* this was a test fetch. don't retry. */
}
@@ -1135,7 +1160,7 @@ directory_initiate_command(const tor_addr_t *or_addr, uint16_t or_port,
digest, dir_purpose,
router_purpose, indirection,
resource, payload, payload_len,
- if_modified_since, NULL);
+ if_modified_since, NULL, NULL);
}
/** Same as directory_initiate_command(), but accepts rendezvous data to
@@ -1150,7 +1175,8 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
const char *resource,
const char *payload, size_t payload_len,
time_t if_modified_since,
- const rend_data_t *rend_query)
+ const rend_data_t *rend_query,
+ circuit_guard_state_t *guard_state)
{
tor_assert(or_addr_port);
tor_assert(dir_addr_port);
@@ -1245,12 +1271,18 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
if (!anonymized_connection && !use_begindir) {
/* then we want to connect to dirport directly */
+ // XXXX prop271 I think that we never use guards in this case.
if (options->HTTPProxy) {
tor_addr_copy(&addr, &options->HTTPProxyAddr);
port = options->HTTPProxyPort;
}
+ // In this case we should not have picked a directory guard.
+ if (BUG(guard_state)) {
+ entry_guard_cancel(&guard_state);
+ }
+
switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
port, &socket_error)) {
case -1:
@@ -1287,6 +1319,14 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
else if (anonymized_connection && !use_begindir)
rep_hist_note_used_port(time(NULL), conn->base_.port);
+ // In this case we should not have a directory guard; we'll
+ // get a regular guard later when we build the circuit.
+ if (BUG(anonymized_connection && guard_state)) {
+ entry_guard_cancel(&guard_state);
+ }
+
+ conn->guard_state = guard_state;
+
/* make an AP connection
* populate it and add it at the right state
* hook up both sides
@@ -2539,6 +2579,21 @@ connection_dir_process_inbuf(dir_connection_t *conn)
tor_assert(conn);
tor_assert(conn->base_.type == CONN_TYPE_DIR);
+ if (conn->guard_state) {
+ /* we count the connection as successful once we can read from it. We do
+ * not, however, delay use of the circuit here, since it's just for a
+ * one-hop directory request. */
+ /* XXXXprop271 note that this will not do the right thing for other
+ * waiting circuits that would be triggered by this circuit becoming
+ * complete/usable. But that's ok, I think.
+ */
+ /* XXXXprop271 should we count this as only a partial success somehow?
+ */
+ entry_guard_succeeded(&conn->guard_state);
+ circuit_guard_state_free(conn->guard_state);
+ conn->guard_state = NULL;
+ }
+
/* Directory clients write, then read data until they receive EOF;
* directory servers read data until they get an HTTP command, then
* write their response (when it's finished flushing, they mark for