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

View File

@ -1,4 +1,9 @@
Changes in version 0.2.0.9-alpha - 2007-10-??
o Major features (v3 directory system):
- Clients now download v3 consensus networkstatus documents instead
of v2 networkstatus documents. Clients and caches now their opinions
about routers on these consensus documents. Clients only download
router descriptors listed in the consensus.
o Major bugfixes:
- Stop publishing a new server descriptor just because we HUP or

View File

@ -69,8 +69,29 @@ Things we'd like to do in 0.2.0.x:
- Enable for non-caches
- Code to use v3 networkstatus documents once clients are
fetching them
- Implement
- Enable
o Make everybody download v3 networkstatus docs.
o Make clients not download v2 networkstatus docs.
o Make everybody download routerdescs based on v3 networkstatus
docs.
o Change definition of "have enough information to build circuits"
o Base version sanity check on v3 ns.
o Change routerstatus_get_by_* to use v3 networkstatus docs.
o Make download_status_get_by_descriptor_digest() use v2
networkstatus docs too.
o Eliminate routerstatus_list.
o Make routers_update_all_from_networkstatus() [or equivalent]
get called at the right time.
o Make routersstatus_list_update_from_consensus_networkstatus()
get renamed and called.
o When setting a new consensus, copy the extra fields out of the
old consensus (if any).
o Update named-server-map as appropriate.
- Fix all XXXX020s.
- Sort out need_to_mirror
- Work hard to make sure clients never look at v2 networkstatus docs.
- Check in old_routers before fetching a router status. You never
know if we'll flap...
- Controller support
- GETINFO to get consensus
- Event when new consensus arrives

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 {

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;

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;
}

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);

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

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);

File diff suppressed because it is too large Load Diff

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);

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,10 +507,8 @@ 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_FOREACH(routerlist->routers, routerinfo_t *, ri,
if (router_get_store(routerlist, ri) == store)
smartlist_add(signed_descriptors, &ri->cache_info));
}
@ -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,
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 (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_find_entry(ns, desc->identity_digest)))
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,82 +3481,6 @@ 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.
*/
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
@ -3637,32 +3501,6 @@ update_router_descriptor_client_downloads(time_t now)
/** 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;

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));