diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-12-16 11:20:59 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-12-16 11:20:59 -0500 |
commit | 2cee38f76a46860e2fb29fbd95ba36b332aa38c6 (patch) | |
tree | 3b2cbaeff1472c8d23c18f3e88bc4735bbb22bcc /src/or/directory.c | |
parent | b310929ee36f0a88389dca53124506115c850c3b (diff) | |
parent | 20292ec4974b777d430e7962cc38349c5f82b220 (diff) | |
download | tor-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.c | 101 |
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 |