diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/compat.c | 4 | ||||
-rw-r--r-- | src/common/compat_libevent.c | 2 | ||||
-rw-r--r-- | src/common/tortls.c | 11 | ||||
-rw-r--r-- | src/or/circuituse.c | 53 | ||||
-rw-r--r-- | src/or/dirserv.c | 36 | ||||
-rw-r--r-- | src/or/dirvote.c | 8 | ||||
-rw-r--r-- | src/or/geoip.c | 4 | ||||
-rw-r--r-- | src/or/main.c | 116 | ||||
-rw-r--r-- | src/or/or.h | 15 | ||||
-rw-r--r-- | src/or/router.c | 24 | ||||
-rw-r--r-- | src/or/routerlist.c | 75 | ||||
-rw-r--r-- | src/win32/orconfig.h | 2 |
12 files changed, 212 insertions, 138 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index 26038c109..0fb169b73 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -355,12 +355,12 @@ tor_vasprintf(char **strp, const char *fmt, va_list args) else *strp = strp_tmp; return r; -#elif defined(MS_WINDOWS) +#elif defined(_MSC_VER) /* On Windows, _vsnprintf won't tell us the length of the string if it * overflows, so we need to use _vcsprintf to tell how much to allocate */ int len, r; char *res; - len = _vcsprintf(fmt, args); + len = _vscprintf(fmt, args); if (len < 0) { *strp = NULL; return -1; diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 18e057f95..56ba3235b 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -11,9 +11,9 @@ **/ #include "orconfig.h" +#include "compat.h" #include "compat_libevent.h" -#include "compat.h" #include "util.h" #include "log.h" diff --git a/src/common/tortls.c b/src/common/tortls.c index df77fb066..218f110d8 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -746,11 +746,11 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) /* If we reached this point, we just got a client hello. See if there is * a cipher list. */ if (!(session = SSL_get_session((SSL *)ssl))) { - log_warn(LD_NET, "No session on TLS?"); + log_info(LD_NET, "No session on TLS?"); return 0; } if (!session->ciphers) { - log_warn(LD_NET, "No ciphers on session"); + log_info(LD_NET, "No ciphers on session"); return 0; } /* Now we need to see if there are any ciphers whose presence means we're @@ -762,8 +762,7 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) && strcmp(ciphername, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) && strcmp(ciphername, "(NONE)")) { - /* XXXX should be ld_debug */ - log_info(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername); + log_debug(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername); // return 1; goto dump_list; } @@ -779,8 +778,8 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) smartlist_add(elts, (char*)ciphername); } s = smartlist_join_strings(elts, ":", 0, NULL); - log_info(LD_NET, "Got a non-version-1 cipher list from %s. It is: '%s'", - address, s); + log_debug(LD_NET, "Got a non-version-1 cipher list from %s. It is: '%s'", + address, s); tor_free(s); smartlist_free(elts); } diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 9eda9e248..7e47e6055 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -17,7 +17,7 @@ extern circuit_t *global_circuitlist; /* from circuitlist.c */ /********* END VARIABLES ************/ -static void circuit_expire_old_circuits(time_t now); +static void circuit_expire_old_circuits_clientside(time_t now); static void circuit_increment_failure_count(void); long int lround(double x); @@ -567,7 +567,7 @@ circuit_build_needed_circs(time_t now) time_to_new_circuit = now + options->NewCircuitPeriod; if (proxy_mode(get_options())) addressmap_clean(now); - circuit_expire_old_circuits(now); + circuit_expire_old_circuits_clientside(now); #if 0 /* disable for now, until predict-and-launch-new can cull leftovers */ circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL); @@ -656,7 +656,7 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) * for too long and has no streams on it: mark it for close. */ static void -circuit_expire_old_circuits(time_t now) +circuit_expire_old_circuits_clientside(time_t now) { circuit_t *circ; time_t cutoff; @@ -696,6 +696,53 @@ circuit_expire_old_circuits(time_t now) } } +/** How long do we wait before killing circuits with the properties + * described below? + * + * Probably we could choose a number here as low as 5 to 10 seconds, + * since these circs are used for begindir, and a) generally you either + * ask another begindir question right after or you don't for a long time, + * b) clients at least through 0.2.1.x choose from the whole set of + * directory mirrors at each choice, and c) re-establishing a one-hop + * circuit via create-fast is a light operation assuming the TLS conn is + * still there. + * + * I expect "b" to go away one day when we move to using directory + * guards, but I think "a" and "c" are good enough reasons that a low + * number is safe even then. + */ +#define IDLE_ONE_HOP_CIRC_TIMEOUT 60 + +/** Find each non-origin circuit that has been unused for too long, + * has no streams on it, used a create_fast, and ends here: mark it + * for close. + */ +void +circuit_expire_old_circuits_serverside(time_t now) +{ + circuit_t *circ; + or_circuit_t *or_circ; + time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT; + + for (circ = global_circuitlist; circ; circ = circ->next) { + if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ)) + continue; + or_circ = TO_OR_CIRCUIT(circ); + /* If the circuit has been idle for too long, and there are no streams + * on it, and it ends here, and it used a create_fast, mark it for close. + */ + if (or_circ->is_first_hop && !circ->n_conn && + !or_circ->n_streams && !or_circ->resolving_streams && + or_circ->p_conn && + or_circ->p_conn->timestamp_last_added_nonpadding <= cutoff) { + log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)", + or_circ->p_circ_id, + (int)(now - or_circ->p_conn->timestamp_last_added_nonpadding)); + circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + } + } +} + /** Number of testing circuits we want open before testing our bandwidth. */ #define NUM_PARALLEL_TESTING_CIRCS 4 diff --git a/src/or/dirserv.c b/src/or/dirserv.c index b5c4c7b50..8b215011f 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -3091,8 +3091,24 @@ dirserv_orconn_tls_done(const char *address, * skip testing. */ } -/** Auth dir server only: if <b>try_all</b> is 1, launch connections to - * all known routers; else we want to load balance such that we only +/** Helper function for dirserv_test_reachability(). Start a TLS + * connection to <b>router</b>, and annotate it with when we started + * the test. */ +void +dirserv_single_reachability_test(time_t now, routerinfo_t *router) +{ + tor_addr_t router_addr; + log_debug(LD_OR,"Testing reachability of %s at %s:%u.", + router->nickname, router->address, router->or_port); + /* Remember when we started trying to determine reachability */ + if (!router->testing_since) + router->testing_since = now; + tor_addr_from_ipv4h(&router_addr, router->addr); + connection_or_connect(&router_addr, router->or_port, + router->cache_info.identity_digest); +} + +/** Auth dir server only: load balance such that we only * try a few connections per call. * * The load balancing is such that if we get called once every ten @@ -3100,7 +3116,7 @@ dirserv_orconn_tls_done(const char *address, * bit over 20 minutes). */ void -dirserv_test_reachability(time_t now, int try_all) +dirserv_test_reachability(time_t now) { /* XXX decide what to do here; see or-talk thread "purging old router * information, revocation." -NM @@ -3117,25 +3133,17 @@ dirserv_test_reachability(time_t now, int try_all) SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, router) { const char *id_digest = router->cache_info.identity_digest; - tor_addr_t router_addr; if (router_is_me(router)) continue; if (bridge_auth && router->purpose != ROUTER_PURPOSE_BRIDGE) continue; /* bridge authorities only test reachability on bridges */ // if (router->cache_info.published_on > cutoff) // continue; - if (try_all || (((uint8_t)id_digest[0]) % 128) == ctr) { - log_debug(LD_OR,"Testing reachability of %s at %s:%u.", - router->nickname, router->address, router->or_port); - /* Remember when we started trying to determine reachability */ - if (!router->testing_since) - router->testing_since = now; - tor_addr_from_ipv4h(&router_addr, router->addr); - connection_or_connect(&router_addr, router->or_port, id_digest); + if ((((uint8_t)id_digest[0]) % 128) == ctr) { + dirserv_single_reachability_test(now, router); } } SMARTLIST_FOREACH_END(router); - if (!try_all) /* increment ctr */ - ctr = (ctr + 1) % 128; + ctr = (ctr + 1) % 128; /* increment ctr */ } /** Given a fingerprint <b>fp</b> which is either set if we're looking for a diff --git a/src/or/dirvote.c b/src/or/dirvote.c index bae222a19..d5610131a 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -2685,6 +2685,9 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) goto err; } + /* Fetch any new router descriptors we just learned about */ + update_consensus_router_descriptor_downloads(time(NULL), 1, vote); + /* Now see whether we already have a vote from this authority. */ SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { if (! memcmp(v->vote->cert->cache_info.identity_digest, @@ -2693,7 +2696,8 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) networkstatus_voter_info_t *vi_old = get_voter(v->vote); if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { /* Ah, it's the same vote. Not a problem. */ - log_info(LD_DIR, "Discarding a vote we already have."); + log_info(LD_DIR, "Discarding a vote we already have (from %s).", + vi->address); if (*status_out < 200) *status_out = 200; goto discard; @@ -2720,7 +2724,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) goto err; } } - }); + }); pending_vote = tor_malloc_zero(sizeof(pending_vote_t)); pending_vote->vote_body = new_cached_dir(tor_strndup(vote_body, diff --git a/src/or/geoip.c b/src/or/geoip.c index b5a0374c4..ea11dc323 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -945,8 +945,8 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) strings = smartlist_create(); SMARTLIST_FOREACH(entries, c_hist_t *, ent, { - char buf[32]; - tor_snprintf(buf, sizeof(buf), "%s=%u", ent->country, ent->total); + char *buf = NULL; + tor_asprintf(&buf, "%s=%u", ent->country, ent->total); smartlist_add(strings, buf); }); result = smartlist_join_strings(strings, ",", 0, NULL); diff --git a/src/or/main.c b/src/or/main.c index 74075b625..0ddb65a74 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -686,6 +686,15 @@ directory_info_has_arrived(time_t now, int from_cache) consider_testing_reachability(1, 1); } +/** How long do we wait before killing OR connections with no circuits? + * In Tor versions up to 0.2.1.25 and 0.2.2.12-alpha, we waited 15 minutes + * before cancelling these connections, which caused fast relays to accrue + * many many idle connections. Hopefully 3 minutes is low enough that + * it kills most idle connections, without being so low that we cause + * clients to bounce on and off. + */ +#define IDLE_OR_CONN_TIMEOUT 180 + /** Perform regular maintenance tasks for a single connection. This * function gets run once per second per connection by run_scheduled_events. */ @@ -696,6 +705,8 @@ run_connection_housekeeping(int i, time_t now) connection_t *conn = smartlist_get(connection_array, i); or_options_t *options = get_options(); or_connection_t *or_conn; + int past_keepalive = + now >= conn->timestamp_lastwritten + options->KeepalivePeriod; if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR) TO_OR_CONN(conn)->timestamp_lastempty = now; @@ -730,6 +741,9 @@ run_connection_housekeeping(int i, time_t now) if (!connection_speaks_cells(conn)) return; /* we're all done here, the rest is just for OR conns */ + /* If we haven't written to an OR connection for a while, then either nuke + the connection or send a keepalive, depending. */ + or_conn = TO_OR_CONN(conn); tor_assert(conn->outbuf); @@ -745,56 +759,45 @@ run_connection_housekeeping(int i, time_t now) "Tor gave up on the connection"); connection_mark_for_close(conn); conn->hold_open_until_flushed = 1; - return; - } - - /* If we haven't written to an OR connection for a while, then either nuke - the connection or send a keepalive, depending. */ - if (now >= conn->timestamp_lastwritten + options->KeepalivePeriod) { - routerinfo_t *router = router_get_by_digest(or_conn->identity_digest); - int maxCircuitlessPeriod = options->MaxCircuitDirtiness*3/2; - if (!connection_state_is_open(conn)) { - /* We never managed to actually get this connection open and happy. */ - log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).", - conn->s,conn->address, conn->port); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; - } else if (we_are_hibernating() && !or_conn->n_circuits && - !buf_datalen(conn->outbuf)) { - /* We're hibernating, there's no circuits, and nothing to flush.*/ - log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " - "[Hibernating or exiting].", - conn->s,conn->address, conn->port); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; - } else if (!clique_mode(options) && !or_conn->n_circuits && - now >= or_conn->timestamp_last_added_nonpadding + - maxCircuitlessPeriod && - (!router || !server_mode(options) || - !router_is_clique_mode(router))) { - log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " - "[Not in clique mode].", - conn->s,conn->address, conn->port); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; - } else if ( - now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 && - now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) { - log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL, - "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to " - "flush; %d seconds since last write)", - conn->s, conn->address, conn->port, - (int)buf_datalen(conn->outbuf), - (int)(now-conn->timestamp_lastwritten)); - connection_mark_for_close(conn); - } else if (!buf_datalen(conn->outbuf)) { - /* either in clique mode, or we've got a circuit. send a padding cell. */ - log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)", - conn->address, conn->port); - memset(&cell,0,sizeof(cell_t)); - cell.command = CELL_PADDING; - connection_or_write_cell_to_buf(&cell, or_conn); - } + } else if (past_keepalive && !connection_state_is_open(conn)) { + /* We never managed to actually get this connection open and happy. */ + log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).", + conn->s,conn->address, conn->port); + connection_mark_for_close(conn); + conn->hold_open_until_flushed = 1; + } else if (we_are_hibernating() && !or_conn->n_circuits && + !buf_datalen(conn->outbuf)) { + /* We're hibernating, there's no circuits, and nothing to flush.*/ + log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " + "[Hibernating or exiting].", + conn->s,conn->address, conn->port); + connection_mark_for_close(conn); + conn->hold_open_until_flushed = 1; + } else if (!or_conn->n_circuits && + now >= or_conn->timestamp_last_added_nonpadding + + IDLE_OR_CONN_TIMEOUT) { + log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " + "[idle %d].", conn->s,conn->address, conn->port, + (int)(now - or_conn->timestamp_last_added_nonpadding)); + connection_mark_for_close(conn); + conn->hold_open_until_flushed = 1; + } else if ( + now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 && + now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) { + log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL, + "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to " + "flush; %d seconds since last write)", + conn->s, conn->address, conn->port, + (int)buf_datalen(conn->outbuf), + (int)(now-conn->timestamp_lastwritten)); + connection_mark_for_close(conn); + } else if (past_keepalive && !buf_datalen(conn->outbuf)) { + /* send a padding cell */ + log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)", + conn->address, conn->port); + memset(&cell,0,sizeof(cell_t)); + cell.command = CELL_PADDING; + connection_or_write_cell_to_buf(&cell, or_conn); } } @@ -918,7 +921,7 @@ run_scheduled_events(time_t now) if (now % 10 == 0 && (authdir_mode_tests_reachability(options)) && !we_are_hibernating()) { /* try to determine reachability of the other Tor relays */ - dirserv_test_reachability(now, 0); + dirserv_test_reachability(now); } /** 1d. Periodically, we discount older stability information so that new @@ -1138,6 +1141,10 @@ run_scheduled_events(time_t now) if (have_dir_info && !we_are_hibernating()) circuit_build_needed_circs(now); + /* every 10 seconds, but not at the same second as other such events */ + if (now % 10 == 5) + circuit_expire_old_circuits_serverside(now); + /** 5. We do housekeeping for each connection... */ connection_or_set_bad_connections(); for (i=0;i<smartlist_len(connection_array);i++) { @@ -1479,11 +1486,6 @@ do_main_loop(void) now = time(NULL); directory_info_has_arrived(now, 1); - if (authdir_mode_tests_reachability(get_options())) { - /* the directory is already here, run startup things */ - dirserv_test_reachability(now, 1); - } - if (server_mode(get_options())) { /* launch cpuworkers. Need to do this *after* we've read the onion key. */ cpu_init(); @@ -1666,7 +1668,7 @@ dumpmemusage(int severity) tor_log_mallinfo(severity); } -/** Write all statistics to the log, with log level 'severity'. Called +/** Write all statistics to the log, with log level <b>severity</b>. Called * in response to a SIGUSR1. */ static void dumpstats(int severity) diff --git a/src/or/or.h b/src/or/or.h index 7c1e5a7a0..9c613d28d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3230,6 +3230,8 @@ int circuit_conforms_to_options(const origin_circuit_t *circ, void circuit_build_needed_circs(time_t now); void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn); +void circuit_expire_old_circuits_serverside(time_t now); + void reset_bandwidth_test(void); int circuit_enough_testing_circs(void); @@ -3913,7 +3915,8 @@ void dirserv_orconn_tls_done(const char *address, uint16_t or_port, const char *digest_rcvd, int as_advertised); -void dirserv_test_reachability(time_t now, int try_all); +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); @@ -4493,9 +4496,6 @@ const char *circuit_end_reason_to_control_string(int reason); const char *socks4_response_code_to_string(uint8_t code); const char *socks5_response_code_to_string(uint8_t code); -enum bandwidth_weight_rule_t; -const char *bandwidth_weight_rule_to_string(enum bandwidth_weight_rule_t rule); - /********************************* relay.c ***************************/ extern uint64_t stats_n_relay_cells_relayed; @@ -4815,13 +4815,11 @@ int authdir_mode_publishes_statuses(or_options_t *options); int authdir_mode_tests_reachability(or_options_t *options); int authdir_mode_bridge(or_options_t *options); -int clique_mode(or_options_t *options); int server_mode(or_options_t *options); int advertised_server_mode(void); int proxy_mode(or_options_t *options); void consider_publishable_server(int force); -int router_is_clique_mode(routerinfo_t *router); void router_upload_dir_desc_to_dirservers(int force); void mark_my_descriptor_dirty_if_older_than(time_t when); void mark_my_descriptor_dirty(void); @@ -4975,6 +4973,9 @@ routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl, routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule); +/* XXXX actually declared in reasons.c */ +const char *bandwidth_weight_rule_to_string(enum bandwidth_weight_rule_t rule); + /** Flags to be passed to control router_choose_random_node() to indicate what * kind of nodes to pick according to what algorithm. */ typedef enum { @@ -5086,6 +5087,8 @@ trusted_dir_server_t *add_trusted_dir_server(const char *nickname, void authority_cert_free(authority_cert_t *cert); void clear_trusted_dir_servers(void); int any_trusted_dir_is_v1_authority(void); +void update_consensus_router_descriptor_downloads(time_t now, int is_vote, + networkstatus_t *consensus); void update_router_descriptor_downloads(time_t now); void update_extrainfo_downloads(time_t now); int router_have_minimum_dir_info(void); diff --git a/src/or/router.c b/src/or/router.c index 347d7f9ef..d105aeffa 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -948,16 +948,6 @@ authdir_mode_bridge(or_options_t *options) { return authdir_mode(options) && options->BridgeAuthoritativeDir != 0; } -/** Return true iff we once tried to stay connected to all ORs at once. - * FFFF this function, and the notion of staying connected to ORs, is - * nearly obsolete. One day there will be a proposal for getting rid of - * it. - */ -int -clique_mode(or_options_t *options) -{ - return authdir_mode_tests_reachability(options); -} /** Return true iff we are trying to be a server. */ @@ -1052,20 +1042,6 @@ consider_publishable_server(int force) } /* - * Clique maintenance -- to be phased out. - */ - -/** Return true iff we believe this OR tries to keep connections open - * to all other ORs. */ -int -router_is_clique_mode(routerinfo_t *router) -{ - if (router_digest_is_trusted_dir(router->cache_info.identity_digest)) - return 1; - return 0; -} - -/* * OR descriptor generation. */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 13123e441..f4db40d25 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -26,8 +26,8 @@ static void mark_all_trusteddirservers_up(void); static int router_nickname_matches(routerinfo_t *router, const char *nickname); static void trusted_dir_server_free(trusted_dir_server_t *ds); static void launch_router_descriptor_downloads(smartlist_t *downloadable, + routerstatus_t *source, time_t now); -static void update_consensus_router_descriptor_downloads(time_t now); 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, @@ -184,15 +184,15 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, log_info(LD_DIR, "Skipping %s certificate for %s that we " "already have.", from_store ? "cached" : "downloaded", - ds ? ds->nickname : "??"); + ds ? ds->nickname : "an old or new authority"); /* a duplicate on a download should be treated as a failure, since it * probably means we wanted a different secret key or we are trying to * replace an expired cert that has not in fact been updated. */ if (!from_store) { - log_warn(LD_DIR, "Got a certificate for %s that we already have. " - "Maybe they haven't updated it. Waiting for a while.", - ds ? ds->nickname : "??"); + log_warn(LD_DIR, "Got a certificate for %s, but we already have it. " + "Maybe they haven't updated it. Waiting for a while.", + ds ? ds->nickname : "an old or new authority"); authority_cert_dl_failed(cert->cache_info.identity_digest, 404); } @@ -973,8 +973,9 @@ router_get_trusteddirserver_by_digest(const char *digest) return NULL; } -/** Return the trusted_dir_server_t for the directory authority whose identity - * key hashes to <b>digest</b>, or NULL if no such authority is known. +/** Return the trusted_dir_server_t for the directory authority whose + * v3 identity key hashes to <b>digest</b>, or NULL if no such authority + * is known. */ trusted_dir_server_t * trusteddirserver_get_by_v3_auth_digest(const char *digest) @@ -3203,7 +3204,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, if (!in_consensus && (router->cache_info.published_on <= old_router->cache_info.published_on)) { /* Same key, but old. This one is not listed in the consensus. */ - log_debug(LD_DIR, "Skipping not-new descriptor for router '%s'", + log_debug(LD_DIR, "Not-new descriptor for router '%s'", router->nickname); /* Only journal this desc if we'll be serving it. */ if (!from_cache && should_cache_old_descriptors()) @@ -3246,9 +3247,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, /* We haven't seen a router with this identity before. Add it to the end of * the list. */ routerlist_insert(routerlist, router); - if (!from_cache) + if (!from_cache) { + if (authdir) { + /* launch an immediate reachability test, so we will have an opinion + * soon in case we're generating a consensus soon */ + dirserv_single_reachability_test(time(NULL), router); + } signed_desc_append_to_journal(&router->cache_info, &routerlist->desc_store); + } directory_set_dirty(); return ROUTER_ADDED_SUCCESSFULLY; } @@ -4102,7 +4109,8 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) * whether to delay fetching until we have more. If we don't want to delay, * launch one or more requests to the appropriate directory authorities. */ static void -launch_router_descriptor_downloads(smartlist_t *downloadable, time_t now) +launch_router_descriptor_downloads(smartlist_t *downloadable, + routerstatus_t *source, time_t now) { int should_delay = 0, n_downloadable; or_options_t *options = get_options(); @@ -4172,7 +4180,7 @@ launch_router_descriptor_downloads(smartlist_t *downloadable, time_t now) req_plural, n_downloadable, rtr_plural, n_per_request); smartlist_sort_digests(downloadable); for (i=0; i < n_downloadable; i += n_per_request) { - initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_SERVERDESC, + initiate_descriptor_downloads(source, DIR_PURPOSE_FETCH_SERVERDESC, downloadable, i, i+n_per_request, pds_flags); } @@ -4328,18 +4336,18 @@ update_router_descriptor_cache_downloads_v2(time_t now) digestmap_free(map,NULL); } -/** For any descriptor that we want that's currently listed in the live - * consensus, download it as appropriate. */ -static void -update_consensus_router_descriptor_downloads(time_t now) +/** For any descriptor that we want that's currently listed in + * <b>consensus</b>, download it as appropriate. */ +void +update_consensus_router_descriptor_downloads(time_t now, int is_vote, + networkstatus_t *consensus) { or_options_t *options = get_options(); digestmap_t *map = NULL; smartlist_t *no_longer_old = smartlist_create(); smartlist_t *downloadable = smartlist_create(); + routerstatus_t *source = NULL; int authdir = authdir_mode(options); - networkstatus_t *consensus = - networkstatus_get_reasonably_live_consensus(now); int n_delayed=0, n_have=0, n_would_reject=0, n_wouldnt_use=0, n_inprogress=0, n_in_oldrouters=0; @@ -4348,10 +4356,24 @@ update_consensus_router_descriptor_downloads(time_t now) if (!consensus) goto done; + if (is_vote) { + /* where's it from, so we know whom to ask for descriptors */ + trusted_dir_server_t *ds; + networkstatus_voter_info_t *voter = smartlist_get(consensus->voters, 0); + tor_assert(voter); + ds = trusteddirserver_get_by_v3_auth_digest(voter->identity_digest); + if (ds) + source = &(ds->fake_status); + else + log_warn(LD_DIR, "couldn't lookup source from vote?"); + } + map = digestmap_new(); list_pending_descriptor_downloads(map, 0); - SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, + SMARTLIST_FOREACH(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; @@ -4386,6 +4408,18 @@ update_consensus_router_descriptor_downloads(time_t now) ++n_wouldnt_use; continue; /* We would never use it ourself. */ } + 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); + format_iso_time(time_bufnew, rs->published_on); + if (oldrouter) + format_iso_time(time_bufold, oldrouter->cache_info.published_on); + log_info(LD_DIR, "Learned about %s (%s vs %s) from %s's vote (%s)", + rs->nickname, time_bufnew, + oldrouter ? time_bufold : "none", + source->nickname, oldrouter ? "known" : "unknown"); + } smartlist_add(downloadable, rs->descriptor_digest); }); @@ -4419,7 +4453,7 @@ update_consensus_router_descriptor_downloads(time_t now) smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters, n_would_reject, n_wouldnt_use, n_inprogress); - launch_router_descriptor_downloads(downloadable, now); + launch_router_descriptor_downloads(downloadable, source, now); digestmap_free(map, NULL); done: @@ -4444,7 +4478,8 @@ update_router_descriptor_downloads(time_t now) if (directory_fetches_dir_info_early(options)) { update_router_descriptor_cache_downloads_v2(now); } - update_consensus_router_descriptor_downloads(now); + update_consensus_router_descriptor_downloads(now, 0, + networkstatus_get_reasonably_live_consensus(now)); /* XXXX021 we could be smarter here; see notes on bug 652. */ /* If we're a server that doesn't have a configured address, we rely on diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index ce6d854b4..9ebe2abc4 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -226,5 +226,5 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.2.10-alpha-dev" +#define VERSION "0.2.2.13-alpha" |