r15806@catbus: nickm | 2007-10-15 19:14:57 -0400

Implement v3 networkstatus client code.  Remove v2 networkstatus client code, except as needed for caches to fetch and serve v2 networkstatues and the routers they list.


svn:r11957
This commit is contained in:
Nick Mathewson
2007-10-15 23:15:24 +00:00
parent 95f6265a79
commit 3ad6dc0e2e
12 changed files with 517 additions and 1283 deletions
+18 -13
View File
@@ -1609,33 +1609,38 @@ getinfo_helper_events(control_connection_t *control_conn,
check_whether_orport_reachable() ? 1 : 0,
check_whether_dirport_reachable() ? 1 : 0);
} else if (!strcmpstart(question, "status/version/")) {
combined_version_status_t st;
int is_server = server_mode(get_options());
char *recommended;
recommended = compute_recommended_versions(time(NULL),
!is_server, VERSION, &st);
networkstatus_vote_t *c = networkstatus_get_latest_consensus();
version_status_t status;
const char *recommended;
if (c) {
recommended = is_server ? c->server_versions : c->client_versions;
status = tor_version_is_obsolete(VERSION, recommended);
} else {
recommended = "?";
status = VS_UNKNOWN;
}
if (!strcmp(question, "status/version/recommended")) {
*answer = recommended;
*answer = tor_strdup(recommended);
return 0;
}
tor_free(recommended);
if (!strcmp(question, "status/version/current")) {
switch (st.consensus)
switch (status)
{
case VS_RECOMMENDED: *answer = tor_strdup("recommended"); break;
case VS_OLD: *answer = tor_strdup("obsolete"); break;
case VS_NEW: *answer = tor_strdup("new"); break;
case VS_NEW_IN_SERIES: *answer = tor_strdup("new in series"); break;
case VS_UNRECOMMENDED: *answer = tor_strdup("unrecommended"); break;
case VS_UNKNOWN: *answer = tor_strdup("unknown"); break;
default: tor_fragile_assert();
}
} else if (!strcmp(question, "status/version/num-versioning")) {
} else if (!strcmp(question, "status/version/num-versioning") ||
!strcmp(question, "status/version/num-concurring")) {
/*XXXX020 deprecate.*/
char s[33];
tor_snprintf(s, sizeof(s), "%d", st.n_versioning);
*answer = tor_strdup(s);
} else if (!strcmp(question, "status/version/num-concurring")) {
char s[33];
tor_snprintf(s, sizeof(s), "%d", st.n_concurring);
tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
*answer = tor_strdup(s);
}
} else {
+6 -7
View File
@@ -178,7 +178,7 @@ router_supports_extrainfo(const char *identity_digest, int is_authority)
return 1;
}
if (is_authority) {
routerstatus_t *rs = router_get_combined_status_by_digest(identity_digest);
routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
if (rs && rs->version_supports_extrainfo_upload)
return 1;
}
@@ -1232,7 +1232,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
"'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
rs->last_dir_503_at = now;
if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
ds->fake_status.last_dir_503_at = now;
@@ -1387,7 +1387,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (next)
next[1] = '\0';
/* learn from it, and then remove it from 'which' */
if (router_set_networkstatus(cp, now, source, which)<0)
if (router_set_networkstatus_v2(cp, now, source, which)<0)
break;
if (next) {
next[1] = 'n';
@@ -1426,6 +1426,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
networkstatus_consensus_download_failed(0);
return -1;
}
routers_update_all_from_networkstatus(now); /*launches router downloads*/
directory_info_has_arrived(now, 0);
log_info(LD_DIR, "Successfully loaded consensus.");
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
@@ -2790,10 +2792,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
if (sd)
dls = &sd->ei_dl_status;
} else {
routerstatus_t *rs =
router_get_combined_status_by_descriptor_digest(digest);
if (rs)
dls = &rs->dl_status;
dls = router_get_dl_status_by_descriptor_digest(digest);
}
if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
continue;
+4 -4
View File
@@ -2380,12 +2380,12 @@ generate_networkstatus_opinion(int v2)
}
{
networkstatus_t *ns;
if (!(ns = networkstatus_parse_from_string(status))) {
networkstatus_v2_t *ns;
if (!(ns = networkstatus_v2_parse_from_string(status))) {
log_err(LD_BUG,"Generated a networkstatus we couldn't parse.");
goto done;
}
networkstatus_free(ns);
networkstatus_v2_free(ns);
}
{
@@ -2395,7 +2395,7 @@ generate_networkstatus_opinion(int v2)
*ns_ptr = new_cached_dir(status, now);
status = NULL; /* So it doesn't get double-freed. */
the_v2_networkstatus_is_dirty = 0;
router_set_networkstatus((*ns_ptr)->dir, now, NS_GENERATED, NULL);
router_set_networkstatus_v2((*ns_ptr)->dir, now, NS_GENERATED, NULL);
r = *ns_ptr;
}
+2
View File
@@ -67,6 +67,8 @@ networkstatus_vote_free(networkstatus_vote_t *ns)
smartlist_free(ns->routerstatus_list);
}
if (ns->desc_digest_map)
digestmap_free(ns->desc_digest_map, NULL);
memset(ns, 11, sizeof(*ns));
tor_free(ns);
-1
View File
@@ -547,7 +547,6 @@ accounting_set_wakeup_time(void)
/* This rounds 0 up to 1000, but that's actually a feature. */
#define ROUND_UP(x) (((x) + 0x3ff) & ~0x3ff)
#define BW_ACCOUNTING_VERSION 1
/** Save all our bandwidth tracking information to disk. Return 0 on
* success, -1 on failure. */
int
+12 -9
View File
@@ -995,9 +995,10 @@ run_scheduled_events(time_t now)
* update all the descriptors' running status. */
/* purge obsolete entries */
routerlist_remove_old_routers();
networkstatus_list_clean(now);
networkstatus_list_update_recent(now);
routers_update_all_from_networkstatus(now);
networkstatus_v2_list_clean(now);
#if 0
networkstatus_v2_list_update_recent(now);
#endif
/* Also, once per minute, check whether we want to download any
* networkstatus documents.
@@ -1339,6 +1340,14 @@ do_main_loop(void)
stats_prev_global_read_bucket = global_read_bucket;
stats_prev_global_write_bucket = global_write_bucket;
if (trusted_dirs_reload_certs())
return -1;
if (router_reload_v2_networkstatus()) {
return -1;
}
if (router_reload_consensus_networkstatus()) {
return -1;
}
/* load the routers file, or assign the defaults. */
if (router_reload_router_list()) {
return -1;
@@ -1346,12 +1355,6 @@ do_main_loop(void)
/* load the networkstatuses. (This launches a download for new routers as
* appropriate.)
*/
if (router_reload_networkstatus()) {
return -1;
}
if (router_reload_consensus_networkstatus()) {
return -1;
}
now = time(NULL);
directory_info_has_arrived(now, 1);
+282 -826
View File
File diff suppressed because it is too large Load Diff
+30 -51
View File
@@ -120,12 +120,6 @@
#define cell_t tor_cell_t
#endif
/** Undefine this when it's time to stop generating v1 directories. */
// #define FULL_V1_DIRECTORIES
/** Undefine this when it's time to stop includeing bandwidth info in router
* descriptors. */
#define INCLUDE_BW_INFO_IN_ROUTERDESCS
/** Length of longest allowable configured nickname. */
#define MAX_NICKNAME_LEN 19
/** Length of a router identity encoded as a hexadecimal digest, plus
@@ -172,8 +166,6 @@
#define ROUTER_MAX_AGE_TO_PUBLISH (60*60*20)
/** How old do we let a saved descriptor get before force-removing it? */
#define OLD_ROUTER_DESC_MAX_AGE (60*60*24*5)
/** How old do we let a networkstatus get before ignoring it? */
#define NETWORKSTATUS_MAX_AGE (60*60*24)
/** Possible rules for generating circuit IDs on an OR connection. */
typedef enum {
@@ -342,26 +334,24 @@ typedef enum {
#define DIR_PURPOSE_UPLOAD_RENDDESC 9
/** A connection to a directory server: upload a v3 networkstatus vote. */
#define DIR_PURPOSE_UPLOAD_VOTE 10
/** A connection to a directory server: fetch a v3 networkstatus vote. */
#define DIR_PURPOSE_FETCH_VOTE 11
/** A connection to a directory server: upload a v3 consensus signature */
#define DIR_PURPOSE_UPLOAD_SIGNATURES 12
#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
/** A connection to a directory server: download one or more network-status
* objects */
#define DIR_PURPOSE_FETCH_STATUS_VOTE 13
#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
/** A connection to a directory server: download one or more network-status
* objects */
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 14
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
/** A connection to a directory server: download one or more network-status
* objects */
#define DIR_PURPOSE_FETCH_CONSENSUS 15
#define DIR_PURPOSE_FETCH_CONSENSUS 14
/** A connection to a directory server: download one or more network-status
* objects */
#define DIR_PURPOSE_FETCH_CERTIFICATE 16
#define DIR_PURPOSE_FETCH_CERTIFICATE 15
/** Purpose for connection at a directory server. */
#define DIR_PURPOSE_SERVER 17
#define _DIR_PURPOSE_MAX 17
#define DIR_PURPOSE_SERVER 16
#define _DIR_PURPOSE_MAX 16
#define _EXIT_PURPOSE_MIN 1
/** This exit stream wants to do an ordinary connect. */
@@ -1274,7 +1264,7 @@ typedef struct routerstatus_t {
#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
/** Contents of a v2 (non-consensus, non-vote) network status object. */
typedef struct networkstatus_t {
typedef struct networkstatus_v2_t {
/** When did we receive the network-status document? */
time_t received_on;
@@ -1312,7 +1302,7 @@ typedef struct networkstatus_t {
smartlist_t *entries; /**< List of routerstatus_t*. This list is kept
* sorted by identity_digest. */
} networkstatus_t;
} networkstatus_v2_t;
/** The claim about a single router, make in a vote. */
typedef struct vote_routerstatus_t {
@@ -1385,6 +1375,10 @@ typedef struct networkstatus_vote_t {
* the elements are vote_routerstatus_t; for a consensus, the elements
* are routerstatus_t. */
smartlist_t *routerstatus_list;
/** If present, a map from descriptor digest to elements of
* routerstatus_list. */
digestmap_t *desc_digest_map;
} networkstatus_vote_t;
/** A set of signatures for a networkstatus consensus. All fields are as for
@@ -1466,7 +1460,6 @@ typedef struct extend_info_t {
* display. */
char identity_digest[DIGEST_LEN]; /**< Hash of this router's identity key. */
uint16_t port; /**< OR port. */
// uint8_t router_purpose; /**< General, controller, or bridge. */
uint32_t addr; /**< IP address in host order. */
crypto_pk_env_t *onion_key; /**< Current onionskin key. */
} extend_info_t;
@@ -2310,7 +2303,6 @@ extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
crypto_pk_env_t *onion_key,
uint32_t addr, uint16_t port);
extend_info_t *extend_info_from_router(routerinfo_t *r);
//extend_info_t *extend_info_from_routerstatus(routerstatus_t *s);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
@@ -3058,52 +3050,43 @@ typedef enum version_status_t {
VS_NEW_IN_SERIES=3, /**< This version is newer than any recommended version
* in its series, but later recommended versions exist.
*/
VS_UNRECOMMENDED=4 /**< This version is not recommended (general case). */
VS_UNRECOMMENDED=4, /**< This version is not recommended (general case). */
VS_UNKNOWN, /**< We have no idea. */
} version_status_t;
typedef struct combined_version_status_t {
/** How many networkstatuses claim to know about versions? */
int n_versioning;
/** What do the majority of networkstatuses believe about this version? */
enum version_status_t consensus;
/** How many networkstatuses constitute the majority? */
int n_concurring;
} combined_version_status_t;
void networkstatus_reset_warnings(void);
int router_reload_networkstatus(void);
void networkstatus_reset_download_failures(void);
int router_reload_v2_networkstatus(void);
int router_reload_consensus_networkstatus(void);
void routerstatus_free(routerstatus_t *rs);
void networkstatus_free(networkstatus_t *ns);
void networkstatus_v2_free(networkstatus_v2_t *ns);
char *networkstatus_get_cache_filename(const char *identity_digest);
int router_set_networkstatus(const char *s, time_t arrived_at,
int router_set_networkstatus_v2(const char *s, time_t arrived_at,
networkstatus_source_t source,
smartlist_t *requested_fingerprints);
void networkstatus_list_clean(time_t now);
routerstatus_t *networkstatus_find_entry(networkstatus_t *ns,
void networkstatus_v2_list_clean(time_t now);
routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
const char *digest);
routerstatus_t *networkstatus_vote_find_entry(networkstatus_vote_t *ns,
const char *digest);
const smartlist_t *networkstatus_get_v2_list(void);
const smartlist_t *networkstatus_get_all_statuses(void);
routerstatus_t *router_get_combined_status_by_digest(const char *digest);
routerstatus_t *router_get_combined_status_by_descriptor_digest(const char *d);
routerstatus_t *router_get_combined_status_by_nickname(const char *nickname,
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
routerstatus_t *router_get_consensus_status_by_id(const char *digest);
routerstatus_t *router_get_consensus_status_by_descriptor_digest(
const char *digest);
routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
int warn_if_unnamed);
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest);
void networkstatus_consensus_download_failed(int status_code);
int should_delay_dir_fetches(or_options_t *options);
void update_networkstatus_downloads(time_t now);
networkstatus_t *networkstatus_get_by_digest(const char *digest);
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_vote_t *networkstatus_get_latest_consensus(void);
networkstatus_vote_t *networkstatus_get_live_consensus(time_t now);
int networkstatus_set_current_consensus(const char *consensus, int from_cache,
int was_waiting_for_certs);
void networkstatus_note_certs_arrived(void);
void routers_update_all_from_networkstatus(time_t now);
void networkstatus_list_update_recent(time_t now);
void routerstatus_list_update_from_networkstatus(time_t now);
void routers_update_status_from_networkstatus(smartlist_t *routers,
int reset_failures);
void routerstatus_list_update_from_consensus_networkstatus(time_t now);
void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures);
@@ -3628,9 +3611,6 @@ void add_trusted_dir_server(const char *nickname, const char *address,
authority_type_t type);
void clear_trusted_dir_servers(void);
int any_trusted_dir_is_v1_authority(void);
char *compute_recommended_versions(time_t now, int client,
const char *my_version,
combined_version_status_t *status_out);
void update_router_descriptor_downloads(time_t now);
void update_extrainfo_downloads(time_t now);
int router_have_minimum_dir_info(void);
@@ -3695,7 +3675,6 @@ addr_policy_t *router_parse_addr_policy_from_string(const char *s,
int assume_action);
version_status_t tor_version_is_obsolete(const char *myversion,
const char *versionlist);
version_status_t version_status_join(version_status_t a, version_status_t b);
int tor_version_parse(const char *s, tor_version_t *out);
int tor_version_as_new_as(const char *platform, const char *cutoff);
int tor_version_compare(tor_version_t *a, tor_version_t *b);
@@ -3703,7 +3682,7 @@ void sort_version_list(smartlist_t *lst, int remove_duplicates);
void assert_addr_policy_ok(addr_policy_t *t);
void dump_distinct_digest_count(int severity);
networkstatus_t *networkstatus_parse_from_string(const char *s);
networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s);
networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s,
const char **eos_out,
int is_vote);
+130 -335
View File
@@ -468,6 +468,7 @@ router_rebuild_store(int force, desc_store_t *store)
int r = -1;
off_t offset = 0;
smartlist_t *signed_descriptors = NULL;
int nocache=0;
if (!force && !router_should_rebuild_store(store))
return 0;
@@ -506,11 +507,9 @@ router_rebuild_store(int force, desc_store_t *store)
}
} else {
SMARTLIST_FOREACH(routerlist->old_routers, signed_descriptor_t *, sd,
if (desc_get_store(routerlist, sd) == store)
smartlist_add(signed_descriptors, sd));
smartlist_add(signed_descriptors, sd));
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
if (router_get_store(routerlist, ri) == store)
smartlist_add(signed_descriptors, &ri->cache_info));
smartlist_add(signed_descriptors, &ri->cache_info));
}
smartlist_sort(signed_descriptors, _compare_signed_descriptors_by_age);
@@ -524,8 +523,10 @@ router_rebuild_store(int force, desc_store_t *store)
log_warn(LD_BUG, "No descriptor available for router.");
goto done;
}
if (sd->do_not_cache)
if (sd->do_not_cache) {
++nocache;
continue;
}
c = tor_malloc(sizeof(sized_chunk_t));
c->bytes = body;
c->len = sd->signed_descriptor_len + sd->annotations_len;
@@ -549,8 +550,10 @@ router_rebuild_store(int force, desc_store_t *store)
}
store->mmap = tor_mmap_file(fname);
if (! store->mmap)
if (! store->mmap) {
log_warn(LD_FS, "Unable to mmap new descriptor file at '%s'.",fname);
//tor_assert(0);
}
log_info(LD_DIR, "Reconstructing pointers into cache");
@@ -688,8 +691,6 @@ router_reload_router_list(void)
return -1;
if (router_reload_router_list_impl(&rl->extrainfo_store))
return -1;
if (trusted_dirs_reload_certs())
return -1;
return 0;
}
@@ -844,7 +845,10 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
smartlist_t *trusted_direct, *trusted_tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
time_t now = time(NULL);
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
const networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
if (!consensus)
return NULL;
direct = smartlist_create();
tunnel = smartlist_create();
@@ -854,7 +858,7 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
overloaded_tunnel = smartlist_create();
/* Find all the running dirservers we know about. */
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, status,
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, status,
{
int is_trusted;
int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
@@ -997,7 +1001,7 @@ mark_all_trusteddirservers_up(void)
routerstatus_t *rs;
dir->is_running = 1;
download_status_reset(&dir->v2_ns_dl_status);
rs = router_get_combined_status_by_digest(dir->digest);
rs = router_get_consensus_status_by_id(dir->digest);
if (rs && !rs->is_running) {
rs->is_running = 1;
rs->last_dir_503_at = 0;
@@ -1147,7 +1151,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
if (!must_be_running || router->is_running) {
smartlist_add(sl,router);
}
} else if (!router_get_combined_status_by_nickname(nick,1)) {
} else if (!router_get_consensus_status_by_nickname(nick,1)) {
if (!warned) {
log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG,
"Nickname list includes '%s' which isn't a known router.",nick);
@@ -1714,6 +1718,8 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
return rimap_get(routerlist->identity_map, named_digest);
}
/* If we reach this point, there's no canonical value for the nickname. */
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
{
if (!strcasecmp(router->nickname, nickname)) {
@@ -1742,7 +1748,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
char fp[HEX_DIGEST_LEN+1];
if (strcasecmp(router->nickname, nickname))
continue;
rs = router_get_combined_status_by_digest(
rs = router_get_consensus_status_by_id(
router->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
rs->name_lookup_warned = 1;
@@ -1768,7 +1774,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
smartlist_free(fps);
} else if (warn_if_unnamed) {
routerstatus_t *rs = router_get_combined_status_by_digest(
routerstatus_t *rs = router_get_consensus_status_by_id(
best_match->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
char fp[HEX_DIGEST_LEN+1];
@@ -2134,15 +2140,6 @@ dump_routerlist_mem_usage(int severity)
smartlist_len(routerlist->old_routers), U64_PRINTF_ARG(olddescs));
}
/** Return the greatest number of routerdescs we'll hold for any given router.
*/
static int
max_descriptors_per_router(void)
{
int n_authorities = get_n_v2_authorities();
return (n_authorities < 5) ? 5 : n_authorities;
}
/** Return non-zero if we have a lot of extra descriptors in our
* routerlist, and should get rid of some of them. Else return 0.
*
@@ -2154,8 +2151,12 @@ max_descriptors_per_router(void)
static INLINE int
routerlist_is_overfull(routerlist_t *rl)
{
return smartlist_len(rl->old_routers) >
smartlist_len(rl->routers)*(max_descriptors_per_router()+1);
/*XXXX020 no longer wholly logical.*/
if (dirserver_mode(get_options())) {
return smartlist_len(rl->old_routers) > smartlist_len(rl->routers)*5;
} else {
return smartlist_len(rl->old_routers) > smartlist_len(rl->routers)*2;
}
}
static INLINE int
@@ -2541,7 +2542,7 @@ router_set_status(const char *digest, int up)
"addresses reachable?");
router->is_running = up;
}
status = router_get_combined_status_by_digest(digest);
status = router_get_consensus_status_by_id(digest);
if (status && status->is_running != up) {
status->is_running = up;
control_event_networkstatus_changed_single(status);
@@ -2574,8 +2575,8 @@ router_set_status(const char *digest, int up)
* server or via the controller.)
*
* This function should be called *after*
* routers_update_status_from_networkstatus; subsequently, you should call
* router_rebuild_store and routerlist_descriptors_added.
* routers_update_status_from_consensus_networkstatus; subsequently, you
* should call router_rebuild_store and routerlist_descriptors_added.
*/
int
router_add_to_routerlist(routerinfo_t *router, const char **msg,
@@ -2590,7 +2591,9 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
int authdir_may_warn_about_unreachable_server =
authdir && !from_cache && !from_fetch &&
router_have_minimum_dir_info();
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
int in_consensus = 0;
tor_assert(msg);
@@ -2644,15 +2647,37 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
}
/* We no longer need a router with this descriptor digest. */
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
routerstatus_t *rs =
networkstatus_find_entry(ns, router->cache_info.identity_digest);
networkstatus_v2_find_entry(ns, router->cache_info.identity_digest);
if (rs && !memcmp(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN))
rs->need_to_mirror = 0;
});
if (consensus) {
routerstatus_t *rs = networkstatus_vote_find_entry(consensus,
router->cache_info.identity_digest);
if (rs && !memcmp(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN)) {
in_consensus = 1;
rs->need_to_mirror = 0;
}
}
/*XXXX020 I had suspicions about whether this was correct, but now I
* can't remember why. :( -NM */
if (consensus && !in_consensus && !authdir_mode(get_options())) {
/* If it's not listed in the consensus, then don't consider replacing
* the latest router with it. */
if (!from_cache && should_cache_old_descriptors())
signed_desc_append_to_journal(&router->cache_info,
router_get_store(routerlist, router));
routerlist_insert_old(routerlist, router);
return -1;
}
/* If we have a router with the same identity key, choose the newer one. */
old_router = rimap_get(routerlist->identity_map,
@@ -2802,7 +2827,7 @@ routerlist_remove_old_cached_routers_with_id(time_t cutoff, int lo, int hi,
/* Check whether we need to do anything at all. */
{
int mdpr = max_descriptors_per_router();
int mdpr = dirserver_mode(get_options()) ? 5 : 2;
if (n <= mdpr)
return;
n_extra = n - mdpr;
@@ -2874,11 +2899,13 @@ routerlist_remove_old_routers(void)
routerinfo_t *router;
signed_descriptor_t *sd;
digestmap_t *retain;
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
int dirserv = dirserver_mode(get_options());
const networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
trusted_dirs_remove_old_certs();
if (!routerlist || !networkstatus_list)
if (!routerlist || !consensus)
return;
routerlist_assert_ok(routerlist);
@@ -2886,7 +2913,8 @@ routerlist_remove_old_routers(void)
retain = digestmap_new();
cutoff = now - OLD_ROUTER_DESC_MAX_AGE;
/* Build a list of all the descriptors that _anybody_ lists. */
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
if (dirserv) {
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
/* XXXX The inner loop here gets pretty expensive, and actually shows up
* on some profiles. It may be the reason digestmap_set shows up in
@@ -2900,22 +2928,21 @@ routerlist_remove_old_routers(void)
if (rs->published_on >= cutoff)
digestmap_set(retain, rs->descriptor_digest, (void*)1));
});
}
{
/* Retain anything listed in the consensus. */
networkstatus_vote_t *ns = networkstatus_get_latest_consensus();
if (ns) {
SMARTLIST_FOREACH(ns->routerstatus_list, routerstatus_t *, rs,
/* Retain anything listed in the consensus. */
if (consensus) {
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
if (rs->published_on >= cutoff)
digestmap_set(retain, rs->descriptor_digest, (void*)1));
}
}
/* If we have a bunch of networkstatuses, we should consider pruning current
* routers that are too old and that nobody recommends. (If we don't have
* enough networkstatuses, then we should get more before we decide to kill
* routers.) */
if (smartlist_len(networkstatus_list) > get_n_v2_authorities() / 2) {
if (!dirserv ||
smartlist_len(networkstatus_v2_list) > get_n_v2_authorities() / 2) {
cutoff = now - ROUTER_MAX_AGE;
/* Remove too-old unrecommended members of routerlist->routers. */
for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
@@ -2955,7 +2982,7 @@ routerlist_remove_old_routers(void)
* total number doesn't approach max_descriptors_per_router()*len(router).
*/
if (smartlist_len(routerlist->old_routers) <
smartlist_len(routerlist->routers) * (max_descriptors_per_router() - 1))
smartlist_len(routerlist->routers) * (dirserver_mode(get_options())?4:2))
goto done;
smartlist_sort(routerlist->old_routers, _compare_old_routers_by_identity);
@@ -3040,7 +3067,7 @@ router_load_single_router(const char *s, uint8_t purpose, int cache,
lst = smartlist_create();
smartlist_add(lst, ri);
routers_update_status_from_networkstatus(lst, 0);
routers_update_status_from_consensus_networkstatus(lst, 0);
if ((r=router_add_to_routerlist(ri, msg, 0, 0))<0) {
/* we've already assigned to *msg now, and ri is already freed */
@@ -3086,7 +3113,7 @@ router_load_routers_from_string(const char *s, const char *eos,
router_parse_list_from_string(&s, eos, routers, saved_location, 0,
allow_annotations, prepend_annotations);
routers_update_status_from_networkstatus(routers, !from_cache);
routers_update_status_from_consensus_networkstatus(routers, !from_cache);
log_info(LD_DIR, "%d elements to add", smartlist_len(routers));
@@ -3171,16 +3198,26 @@ static int
signed_desc_digest_is_recognized(signed_descriptor_t *desc)
{
routerstatus_t *rs;
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
int dirserv = dirserver_mode(get_options());
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
{
if (!(rs = networkstatus_find_entry(ns, desc->identity_digest)))
continue;
if (!memcmp(rs->descriptor_digest,
desc->signed_descriptor_digest, DIGEST_LEN))
if (consensus) {
rs = networkstatus_vote_find_entry(consensus, desc->identity_digest);
if (rs && !memcmp(rs->descriptor_digest,
desc->signed_descriptor_digest, DIGEST_LEN))
return 1;
});
}
if (dirserv && networkstatus_v2_list) {
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
if (!(rs = networkstatus_v2_find_entry(ns, desc->identity_digest)))
continue;
if (!memcmp(rs->descriptor_digest,
desc->signed_descriptor_digest, DIGEST_LEN))
return 1;
});
}
return 0;
}
@@ -3336,103 +3373,6 @@ any_trusted_dir_is_v1_authority(void)
return 0;
}
/** Return a newly allocated string naming the versions of Tor recommended by
* more than half the versioning networkstatuses. */
char *
compute_recommended_versions(time_t now, int client,
const char *my_version,
combined_version_status_t *status_out)
{
int n_seen;
char *current;
smartlist_t *combined, *recommended;
int n_versioning, n_recommending;
char *result;
/** holds the compromise status taken among all non-recommending
* authorities */
version_status_t consensus = VS_RECOMMENDED;
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
(void) now; /* right now, we consider *all* statuses, regardless of age. */
tor_assert(my_version);
tor_assert(status_out);
memset(status_out, 0, sizeof(combined_version_status_t));
if (!networkstatus_list)
return tor_strdup("<none>");
combined = smartlist_create();
n_versioning = n_recommending = 0;
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
{
const char *vers;
smartlist_t *versions;
version_status_t status;
if (! ns->recommends_versions)
continue;
n_versioning++;
vers = client ? ns->client_versions : ns->server_versions;
if (!vers)
continue;
versions = smartlist_create();
smartlist_split_string(versions, vers, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
sort_version_list(versions, 1);
smartlist_add_all(combined, versions);
smartlist_free(versions);
/* now, check _our_ version */
status = tor_version_is_obsolete(my_version, vers);
if (status == VS_RECOMMENDED)
n_recommending++;
consensus = version_status_join(status, consensus);
});
sort_version_list(combined, 0);
current = NULL;
n_seen = 0;
recommended = smartlist_create();
SMARTLIST_FOREACH(combined, char *, cp,
{
if (current && !strcmp(cp, current)) {
++n_seen;
} else {
if (current)
log_info(LD_DIR,"version %s is recommended by %d authorities",
current, n_seen);
if (n_seen > n_versioning/2 && current) {
smartlist_add(recommended, current);
}
n_seen = 1;
current = cp;
}
});
if (current)
log_info(LD_DIR,"version %s is recommended by %d authorities",
current, n_seen);
if (n_seen > n_versioning/2 && current)
smartlist_add(recommended, current);
result = smartlist_join_strings(recommended, ", ", 0, NULL);
SMARTLIST_FOREACH(combined, char *, cp, tor_free(cp));
smartlist_free(combined);
smartlist_free(recommended);
status_out->n_versioning = n_versioning;
if (n_recommending > n_versioning/2) {
status_out->consensus = VS_RECOMMENDED;
status_out->n_concurring = n_recommending;
} else {
status_out->consensus = consensus;
status_out->n_concurring = n_versioning - n_recommending;
}
return result;
}
/** DOCDOC */
static void
list_pending_downloads(digestmap_t *result,
@@ -3541,128 +3481,26 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
return 1;
}
/** Return new list of ID fingerprints for routers that we (as a client) would
* like to download.
/** Max amount of hashes to download per request.
* Since squid does not like URLs >= 4096 bytes we limit it to 96.
* 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
* 4058/41 (40 for the hash and 1 for the + that separates them) => 98
* So use 96 because it's a nice number.
*/
static smartlist_t *
router_list_client_downloadable(void)
{
int n_downloadable = 0;
smartlist_t *downloadable = smartlist_create();
digestmap_t *downloading;
time_t now = time(NULL);
/* these are just used for logging */
int n_not_ready = 0, n_in_progress = 0, n_uptodate = 0, n_wouldnt_use = 0;
or_options_t *options = get_options();
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
if (!smartlist_len(routerstatus_list))
return downloadable;
downloading = digestmap_new();
list_pending_descriptor_downloads(downloading, 0);
routerstatus_list_update_from_networkstatus(now);
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
{
routerinfo_t *ri;
if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
/* We have the 'best' descriptor for this router. */
++n_uptodate;
} else if (!client_would_use_router(rs, now, options)) {
/* We wouldn't want this descriptor even if we got it. */
++n_wouldnt_use;
} else if (digestmap_get(downloading, rs->descriptor_digest)) {
/* We're downloading this one now. */
++n_in_progress;
} else if ((ri = router_get_by_digest(rs->identity_digest)) &&
ri->cache_info.published_on > rs->published_on) {
/* Oddly, we have a descriptor more recent than the 'best' one, but it
was once best. So that's okay. */
++n_uptodate;
} else if (!download_status_is_ready(&rs->dl_status, now,
MAX_ROUTERDESC_DOWNLOAD_FAILURES)) {
/* We failed too recently to try again. */
++n_not_ready;
} else {
/* Okay, time to try it. */
smartlist_add(downloadable, rs->descriptor_digest);
++n_downloadable;
}
});
#if 0
log_info(LD_DIR,
"%d router descriptors are downloadable. "
"%d are in progress. %d are up-to-date. "
"%d are non-useful. %d failed too recently to retry.",
n_downloadable, n_in_progress, n_uptodate,
n_wouldnt_use, n_not_ready);
#endif
digestmap_free(downloading, NULL);
return downloadable;
}
/** Initiate new router downloads as needed, using the strategy for
* non-directory-servers.
*
* We don't launch any downloads if there are fewer than MAX_DL_TO_DELAY
* descriptors to get and less than MAX_CLIENT_INTERVAL_WITHOUT_REQUEST
* seconds have passed.
*
* Otherwise, we ask for all descriptors that we think are different from what
* we have, and that we don't currently have an in-progress download attempt
* for. */
static void
update_router_descriptor_client_downloads(time_t now)
{
/** Max amount of hashes to download per request.
* Since squid does not like URLs >= 4096 bytes we limit it to 96.
* 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
* 4058/41 (40 for the hash and 1 for the + that separates them) => 98
* So use 96 because it's a nice number.
*/
#define MAX_DL_PER_REQUEST 96
/** Don't split our requests so finely that we are requesting fewer than
* this number per server. */
/** Don't split our requests so finely that we are requesting fewer than
* this number per server. */
#define MIN_DL_PER_REQUEST 4
/** To prevent a single screwy cache from confusing us by selective reply,
* try to split our requests into at least this this many requests. */
/** To prevent a single screwy cache from confusing us by selective reply,
* try to split our requests into at least this this many requests. */
#define MIN_REQUESTS 3
/** If we want fewer than this many descriptors, wait until we
* want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
* passed. */
/** If we want fewer than this many descriptors, wait until we
* want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
* passed. */
#define MAX_DL_TO_DELAY 16
/** When directory clients have only a few servers to request, they batch
* them until they have more, or until this amount of time has passed. */
/** When directory clients have only a few servers to request, they batch
* them until they have more, or until this amount of time has passed. */
#define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
smartlist_t *downloadable = NULL;
or_options_t *options = get_options();
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
if (dirserver_mode(options)) {
log_warn(LD_BUG,
"Called router_descriptor_client_downloads() on a dir mirror?");
}
if (rep_hist_circbuilding_dormant(now)) {
// log_info(LD_CIRC, "Skipping descriptor downloads: we haven't needed "
// "any circuits lately.");
return;
}
if (networkstatus_list &&
smartlist_len(networkstatus_list) <= get_n_v2_authorities()/2) {
log_info(LD_DIR,
"Not enough networkstatus documents to launch requests.");
return;
}
downloadable = router_list_client_downloadable();
launch_router_descriptor_downloads(downloadable, now);
smartlist_free(downloadable);
}
/** DOCDOC */
static void
@@ -3734,18 +3572,18 @@ update_router_descriptor_cache_downloads(time_t now)
int i, j, n;
int n_download;
or_options_t *options = get_options();
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
if (! dirserver_mode(options)) {
log_warn(LD_BUG, "Called update_router_descriptor_cache_downloads() "
"on a non-dir-mirror?");
}
if (!networkstatus_list || !smartlist_len(networkstatus_list))
if (!networkstatus_v2_list || !smartlist_len(networkstatus_v2_list))
return;
map = digestmap_new();
n = smartlist_len(networkstatus_list);
n = smartlist_len(networkstatus_v2_list);
downloadable = tor_malloc_zero(sizeof(smartlist_t*) * n);
download_from = tor_malloc_zero(sizeof(smartlist_t*) * n);
@@ -3760,7 +3598,7 @@ update_router_descriptor_cache_downloads(time_t now)
* descriptor from the corresponding authority.
*/
n_download = 0;
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
trusted_dir_server_t *ds;
smartlist_t *dl;
@@ -3837,7 +3675,7 @@ update_router_descriptor_cache_downloads(time_t now)
/* Now, we can actually launch our requests. */
for (i=0; i<n; ++i) {
networkstatus_t *ns = smartlist_get(networkstatus_list, i);
networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i);
trusted_dir_server_t *ds =
router_get_trusteddirserver_by_digest(ns->identity_digest);
smartlist_t *dl = download_from[i];
@@ -3874,7 +3712,7 @@ update_consensus_router_descriptor_downloads(time_t now)
smartlist_t *downloadable = smartlist_create();
int authdir = authdir_mode(options);
int dirserver = dirserver_mode(options);
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
networkstatus_vote_t *consensus = networkstatus_get_live_consensus(now);
if (!dirserver) {
if (rep_hist_circbuilding_dormant(now))
@@ -3887,17 +3725,9 @@ update_consensus_router_descriptor_downloads(time_t now)
list_pending_descriptor_downloads(map, 0);
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
{
routerstatus_t *lrs;
if (router_get_by_descriptor_digest(rs->descriptor_digest))
continue; /* We have it already. */
/* XXXX020 change this once the real consensus is the canonical place
* to go for router information. */
lrs = router_get_combined_status_by_digest(rs->identity_digest);
if (!lrs ||
memcmp(lrs->descriptor_digest, rs->descriptor_digest, DIGEST_LEN))
lrs = rs;
if (!download_status_is_ready(&lrs->dl_status, now,
if (!download_status_is_ready(&rs->dl_status, now,
MAX_ROUTERDESC_DOWNLOAD_FAILURES))
continue;
@@ -3925,10 +3755,8 @@ update_router_descriptor_downloads(time_t now)
return;
if (dirserver_mode(options)) {
update_router_descriptor_cache_downloads(now);
update_consensus_router_descriptor_downloads(now); /*XXXX020 clients too*/
} else {
update_router_descriptor_client_downloads(now);
}
update_consensus_router_descriptor_downloads(now);
}
/** Return true iff <b>sd</b> is the descriptor for a router descriptor that
@@ -3990,19 +3818,6 @@ update_extrainfo_downloads(time_t now)
smartlist_free(wanted);
}
/** Return the number of routerstatus_t in <b>entries</b> that we'd actually
* use. */
static int
routerstatus_count_usable_entries(smartlist_t *entries)
{
int count = 0;
time_t now = time(NULL);
or_options_t *options = get_options();
SMARTLIST_FOREACH(entries, routerstatus_t *, rs,
if (client_would_use_router(rs, now, options)) count++);
return count;
}
/** True iff, the last time we checked whether we had enough directory info
* to build circuits, the answer was "yes". */
static int have_min_dir_info = 0;
@@ -4041,20 +3856,18 @@ router_dir_info_changed(void)
static void
update_router_have_minimum_dir_info(void)
{
int tot = 0, num_running = 0;
int n_ns, n_authorities, res, avg;
/*XXX020 call when dirserver_mode() changes. */
int num_present = 0, num_usable=0;
time_t now = time(NULL);
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
int res;
or_options_t *options = get_options();
const networkstatus_vote_t *consensus =
networkstatus_get_live_consensus(now);
if (!routerlist) {
if (!consensus) {
res = 0;
goto done;
}
/*XXXX020 remove this call. routerlist_remove_old_routers shows up in some
* profiles, and this is the biggest caller of that function. */
routerlist_remove_old_routers();
networkstatus_list_clean(now);
if (should_delay_dir_fetches(get_options())) {
log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
@@ -4062,24 +3875,17 @@ update_router_have_minimum_dir_info(void)
goto done;
}
n_authorities = get_n_v2_authorities();
n_ns = smartlist_len(networkstatus_list);
if (n_ns<=n_authorities/2) {
log_info(LD_DIR,
"We have %d of %d network statuses, and we want "
"more than %d.", n_ns, n_authorities, n_authorities/2);
res = 0;
goto done;
}
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
tot += routerstatus_count_usable_entries(ns->entries));
avg = tot / n_ns;
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
{
if (rs->is_running)
num_running++;
if (client_would_use_router(rs, now, options)) {
++num_usable;
if (router_get_by_digest(rs->identity_digest)) {
++num_present;
}
}
});
res = smartlist_len(routerlist->routers) >= (avg/4) && num_running > 2;
res = num_present >= num_usable/4 && num_usable > 2;
done:
if (res && !have_min_dir_info) {
log(LOG_NOTICE, LD_DIR,
@@ -4089,7 +3895,7 @@ update_router_have_minimum_dir_info(void)
if (!res && have_min_dir_info) {
log(LOG_NOTICE, LD_DIR,"Our directory information is no longer up-to-date "
"enough to build circuits.%s",
num_running > 2 ? "" : " (Not enough servers seem reachable -- "
num_usable > 2 ? "" : " (Not enough servers seem reachable -- "
"is your network connection down?)");
control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO");
}
@@ -4102,18 +3908,7 @@ update_router_have_minimum_dir_info(void)
void
router_reset_descriptor_download_failures(void)
{
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
{
download_status_reset(&rs->dl_status);
});
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
{
if (!router_get_by_descriptor_digest(rs->descriptor_digest))
rs->need_to_mirror = 1;
}));
networkstatus_reset_download_failures();
last_routerdesc_download_attempted = 0;
if (!routerlist)
return;
+5 -35
View File
@@ -564,36 +564,6 @@ tor_version_is_obsolete(const char *myversion, const char *versionlist)
return ret;
}
/** Return the combined status of the current version, given that we know of
* one set of networkstatuses that give us status <b>a</b>, and another that
* gives us status <b>b</b>.
*
* For example, if one authority thinks that we're NEW, and another thinks
* we're OLD, we're simply UNRECOMMENDED.
*
* This function does not handle calculating whether we're RECOMMENDED; that
* follows a simple majority rule. This function simply calculates *why*
* we're not recommended (if we're not).
*/
version_status_t
version_status_join(version_status_t a, version_status_t b)
{
if (a == b)
return a;
else if (a == VS_UNRECOMMENDED || b == VS_UNRECOMMENDED)
return VS_UNRECOMMENDED;
else if (a == VS_RECOMMENDED)
return b;
else if (b == VS_RECOMMENDED)
return a;
/* Okay. Neither is 'recommended' or 'unrecommended', and they differ. */
else if (a == VS_OLD || b == VS_OLD)
return VS_UNRECOMMENDED;
/* One is VS_NEW, the other is VS_NEW_IN_SERIES */
else
return VS_NEW_IN_SERIES;
}
/** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
* Otherwise, return -1. If we're a directory cache, cache it.
*/
@@ -1722,13 +1692,13 @@ _free_duplicate_routerstatus_entry(void *e)
* signature of the network status, but do not (yet) check the signing key for
* authority.
*/
networkstatus_t *
networkstatus_parse_from_string(const char *s)
networkstatus_v2_t *
networkstatus_v2_parse_from_string(const char *s)
{
const char *eos;
smartlist_t *tokens = smartlist_create();
smartlist_t *footer_tokens = smartlist_create();
networkstatus_t *ns = NULL;
networkstatus_v2_t *ns = NULL;
char ns_digest[DIGEST_LEN];
char tmp_digest[DIGEST_LEN];
struct in_addr in;
@@ -1745,7 +1715,7 @@ networkstatus_parse_from_string(const char *s)
log_warn(LD_DIR, "Error tokenizing network-status header.");
goto err;
}
ns = tor_malloc_zero(sizeof(networkstatus_t));
ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
tok = find_first_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
@@ -1876,7 +1846,7 @@ networkstatus_parse_from_string(const char *s)
goto done;
err:
if (ns)
networkstatus_free(ns);
networkstatus_v2_free(ns);
ns = NULL;
done:
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));