diff options
Diffstat (limited to 'src/or/networkstatus.c')
-rw-r--r-- | src/or/networkstatus.c | 116 |
1 files changed, 103 insertions, 13 deletions
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 991cf80121..1fd0772f3e 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -6,12 +6,39 @@ /** * \file networkstatus.c - * \brief Functions and structures for handling network status documents as a - * client or cache. + * \brief Functions and structures for handling networkstatus documents as a + * client or as a directory cache. + * + * A consensus networkstatus object is created by the directory + * authorities. It authenticates a set of network parameters--most + * importantly, the list of all the relays in the network. This list + * of relays is represented as an array of routerstatus_t objects. + * + * There are currently two flavors of consensus. With the older "NS" + * flavor, each relay is associated with a digest of its router + * descriptor. Tor instances that use this consensus keep the list of + * router descriptors as routerinfo_t objects stored and managed in + * routerlist.c. With the newer "microdesc" flavor, each relay is + * associated with a digest of the microdescriptor that the authorities + * made for it. These are stored and managed in microdesc.c. Information + * about the router is divided between the the networkstatus and the + * microdescriptor according to the general rule that microdescriptors + * should hold information that changes much less frequently than the + * information in the networkstatus. + * + * Modern clients use microdescriptor networkstatuses. Directory caches + * need to keep both kinds of networkstatus document, so they can serve them. + * + * This module manages fetching, holding, storing, updating, and + * validating networkstatus objects. The download-and-validate process + * is slightly complicated by the fact that the keys you need to + * validate a consensus are stored in the authority certificates, which + * you might not have yet when you download the consensus. */ #define NETWORKSTATUS_PRIVATE #include "or.h" +#include "bridges.h" #include "channel.h" #include "circuitmux.h" #include "circuitmux_ewma.h" @@ -216,7 +243,7 @@ router_reload_consensus_networkstatus(void) } /** Free all storage held by the vote_routerstatus object <b>rs</b>. */ -STATIC void +void vote_routerstatus_free(vote_routerstatus_t *rs) { vote_microdesc_hash_t *h, *next; @@ -788,8 +815,11 @@ networkstatus_nickname_is_unnamed(const char *nickname) #define NONAUTHORITY_NS_CACHE_INTERVAL (60*60) /** Return true iff, given the options listed in <b>options</b>, <b>flavor</b> - * is the flavor of a consensus networkstatus that we would like to fetch. */ -static int + * is the flavor of a consensus networkstatus that we would like to fetch. + * + * For certificate fetches, use we_want_to_fetch_unknown_auth_certs, and + * for serving fetched documents, use directory_caches_dir_info. */ +int we_want_to_fetch_flavor(const or_options_t *options, int flavor) { if (flavor < 0 || flavor > N_CONSENSUS_FLAVORS) { @@ -811,6 +841,29 @@ we_want_to_fetch_flavor(const or_options_t *options, int flavor) return flavor == usable_consensus_flavor(); } +/** Return true iff, given the options listed in <b>options</b>, we would like + * to fetch and store unknown authority certificates. + * + * For consensus and descriptor fetches, use we_want_to_fetch_flavor, and + * for serving fetched certificates, use directory_caches_unknown_auth_certs. + */ +int +we_want_to_fetch_unknown_auth_certs(const or_options_t *options) +{ + if (authdir_mode_v3(options) || + directory_caches_unknown_auth_certs((options))) { + /* We want to serve all certs to others, regardless if we would use + * them ourselves. */ + return 1; + } + if (options->FetchUselessDescriptors) { + /* Unknown certificates are definitely useless. */ + return 1; + } + /* Otherwise, don't fetch unknown certificates. */ + return 0; +} + /** How long will we hang onto a possibly live consensus for which we're * fetching certs before we check whether there is a better one? */ #define DELAY_WHILE_FETCHING_CERTS (20*60) @@ -1325,6 +1378,24 @@ networkstatus_get_live_consensus,(time_t now)) return NULL; } +/** Determine if <b>consensus</b> is valid or expired recently enough that + * we can still use it. + * + * Return 1 if the consensus is reasonably live, or 0 if it is too old. + */ +int +networkstatus_consensus_reasonably_live(networkstatus_t *consensus, time_t now) +{ +#define REASONABLY_LIVE_TIME (24*60*60) + if (BUG(!consensus)) + return 0; + + if (now <= consensus->valid_until + REASONABLY_LIVE_TIME) + return 1; + + return 0; +} + /* XXXX remove this in favor of get_live_consensus. But actually, * leave something like it for bridge users, who need to not totally * lose if they spend a while fetching a new consensus. */ @@ -1333,12 +1404,11 @@ networkstatus_get_live_consensus,(time_t now)) networkstatus_t * networkstatus_get_reasonably_live_consensus(time_t now, int flavor) { -#define REASONABLY_LIVE_TIME (24*60*60) networkstatus_t *consensus = networkstatus_get_latest_consensus_by_flavor(flavor); if (consensus && consensus->valid_after <= now && - now <= consensus->valid_until+REASONABLY_LIVE_TIME) + networkstatus_consensus_reasonably_live(consensus, now)) return consensus; else return NULL; @@ -1702,9 +1772,9 @@ networkstatus_set_current_consensus(const char *consensus, } if (flav != usable_consensus_flavor() && - !directory_caches_dir_info(options)) { - /* This consensus is totally boring to us: we won't use it, and we won't - * serve it. Drop it. */ + !we_want_to_fetch_flavor(options, flav)) { + /* This consensus is totally boring to us: we won't use it, we didn't want + * it, and we won't serve it. Drop it. */ goto done; } @@ -1906,7 +1976,7 @@ networkstatus_set_current_consensus(const char *consensus, download_status_failed(&consensus_dl_status[flav], 0); } - if (directory_caches_dir_info(options)) { + if (we_want_to_fetch_flavor(options, flav)) { dirserv_set_cached_consensus_networkstatus(consensus, flavor, &c->digests, @@ -2277,6 +2347,25 @@ networkstatus_get_param(const networkstatus_t *ns, const char *param_name, } /** + * As networkstatus_get_param(), but check torrc_value before checking the + * consensus. If torrc_value is in-range, then return it instead of the + * value from the consensus. + */ +int32_t +networkstatus_get_overridable_param(const networkstatus_t *ns, + int32_t torrc_value, + const char *param_name, + int32_t default_val, + int32_t min_val, int32_t max_val) +{ + if (torrc_value >= min_val && torrc_value <= max_val) + return torrc_value; + else + return networkstatus_get_param( + ns, param_name, default_val, min_val, max_val); +} + +/** * Retrieve the consensus parameter that governs the * fixed-point precision of our network balancing 'bandwidth-weights' * (which are themselves integer consensus values). We divide them @@ -2355,9 +2444,10 @@ int client_would_use_router(const routerstatus_t *rs, time_t now, const or_options_t *options) { - if (!rs->is_flagged_running && !options->FetchUselessDescriptors) { + (void) options; /* unused */ + if (!rs->is_flagged_running) { /* If we had this router descriptor, we wouldn't even bother using it. - * But, if we want to have a complete list, fetch it anyway. */ + * (Fetching and storing depends on by we_want_to_fetch_flavor().) */ return 0; } if (rs->published_on + OLD_ROUTER_DESC_MAX_AGE < now) { |