Add unit test for router_pick_directory_server_impl

This commit is contained in:
Matthew Finkel
2015-01-26 19:49:48 +00:00
committed by Nick Mathewson
parent 0a7d22a664
commit e0bd6cdef2
10 changed files with 817 additions and 276 deletions
+32
View File
@@ -1457,6 +1457,38 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
}
#ifdef TOR_UNIT_TESTS
/**Accept a <b>flavor</b> consensus <b>c</b> without any additional
* validation. This is exclusively for unit tests.
* We copy any ancillary information from a pre-existing consensus
* and then free the current one and replace it with the newly
* provided instance. Returns -1 on unrecognized flavor, 0 otherwise.
*/
int
networkstatus_set_current_consensus_from_ns(networkstatus_t *c,
const char *flavor)
{
int flav = networkstatus_parse_flavor_name(flavor);
switch (flav) {
case FLAV_NS:
if (current_ns_consensus) {
networkstatus_copy_old_consensus_info(c, current_ns_consensus);
networkstatus_vote_free(current_ns_consensus);
}
current_ns_consensus = c;
break;
case FLAV_MICRODESC:
if (current_md_consensus) {
networkstatus_copy_old_consensus_info(c, current_md_consensus);
networkstatus_vote_free(current_md_consensus);
}
current_md_consensus = c;
break;
}
return current_md_consensus ? 0 : -1;
}
#endif //TOR_UNIT_TESTS
/** Try to replace the current cached v3 networkstatus with the one in
* <b>consensus</b>. If we don't have enough certificates to validate it,
* store it in consensus_waiting_for_certs and launch a certificate fetch.
+4
View File
@@ -114,6 +114,10 @@ int networkstatus_get_weight_scale_param(networkstatus_t *ns);
#ifdef NETWORKSTATUS_PRIVATE
STATIC void vote_routerstatus_free(vote_routerstatus_t *rs);
#ifdef TOR_UNIT_TESTS
STATIC int networkstatus_set_current_consensus_from_ns(networkstatus_t *c,
const char *flavor);
#endif // TOR_UNIT_TESTS
#endif
#endif
+6 -4
View File
@@ -67,8 +67,6 @@ typedef struct cert_list_t cert_list_t;
static int compute_weighted_bandwidths(const smartlist_t *sl,
bandwidth_weight_rule_t rule,
u64_dbl_t **bandwidths_out);
static const routerstatus_t *router_pick_directory_server_impl(
dirinfo_type_t auth, int flags, int *n_busy_out);
static const routerstatus_t *router_pick_trusteddirserver_impl(
const smartlist_t *sourcelist, dirinfo_type_t auth,
int flags, int *n_busy_out);
@@ -1472,7 +1470,7 @@ router_pick_dirserver_generic(smartlist_t *sourcelist,
* directories that we excluded for no other reason than
* PDS_NO_EXISTING_SERVERDESC_FETCH or PDS_NO_EXISTING_MICRODESC_FETCH.
*/
static const routerstatus_t *
STATIC const routerstatus_t *
router_pick_directory_server_impl(dirinfo_type_t type, int flags,
int *n_busy_out)
{
@@ -3238,7 +3236,11 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd)
return ri;
}
/** Free all memory held by the routerlist module. */
/** Free all memory held by the routerlist module.
* Note: Calling routerlist_free_all() should always be paired with
* a call to nodelist_free_all(). These should only be called during
* cleanup.
*/
void
routerlist_free_all(void)
{
+3
View File
@@ -233,6 +233,9 @@ STATIC int choose_array_element_by_weight(const u64_dbl_t *entries,
int n_entries);
STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
uint64_t *total_out);
STATIC const routerstatus_t *router_pick_directory_server_impl(
dirinfo_type_t auth, int flags,
int *n_busy_out);
MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
int seconds));
+1
View File
@@ -79,6 +79,7 @@ src_test_test_SOURCES = \
src/test/test_crypto.c \
src/test/test_data.c \
src/test/test_dir.c \
src/test/test_dir_common.c \
src/test/test_dir_handle_get.c \
src/test/test_entryconn.c \
src/test/test_entrynodes.c \
+20 -271
View File
@@ -26,6 +26,7 @@
#include "routerparse.h"
#include "routerset.h"
#include "test.h"
#include "test_dir_common.h"
#include "torcert.h"
static void
@@ -300,6 +301,8 @@ test_dir_formats(void *arg)
strlcat(buf2, "tunnelled-dir-server\n", sizeof(buf2));
strlcat(buf2, "router-sig-ed25519 ", sizeof(buf2));
options->ORPort_set = 1;
buf = router_dump_router_to_string(r2, pk1, pk2, &r2_onion_keypair, &kp2);
tt_assert(buf);
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
@@ -1489,13 +1492,6 @@ test_dir_param_voting(void *arg)
return;
}
extern const char AUTHORITY_CERT_1[];
extern const char AUTHORITY_SIGNKEY_1[];
extern const char AUTHORITY_CERT_2[];
extern const char AUTHORITY_SIGNKEY_2[];
extern const char AUTHORITY_CERT_3[];
extern const char AUTHORITY_SIGNKEY_3[];
/** Helper: Test that two networkstatus_voter_info_t do in fact represent the
* same voting authority, and that they do in fact have all the same
* information. */
@@ -1515,42 +1511,6 @@ test_same_voter(networkstatus_voter_info_t *v1,
;
}
/** Helper: Make a new routerinfo containing the right information for a
* given vote_routerstatus_t. */
static routerinfo_t *
generate_ri_from_rs(const vote_routerstatus_t *vrs)
{
routerinfo_t *r;
const routerstatus_t *rs = &vrs->status;
static time_t published = 0;
r = tor_malloc_zero(sizeof(routerinfo_t));
r->cert_expiration_time = TIME_MAX;
memcpy(r->cache_info.identity_digest, rs->identity_digest, DIGEST_LEN);
memcpy(r->cache_info.signed_descriptor_digest, rs->descriptor_digest,
DIGEST_LEN);
r->cache_info.do_not_cache = 1;
r->cache_info.routerlist_index = -1;
r->cache_info.signed_descriptor_body =
tor_strdup("123456789012345678901234567890123");
r->cache_info.signed_descriptor_len =
strlen(r->cache_info.signed_descriptor_body);
r->exit_policy = smartlist_new();
r->cache_info.published_on = ++published + time(NULL);
if (rs->has_bandwidth) {
/*
* Multiply by 1000 because the routerinfo_t and the routerstatus_t
* seem to use different units (*sigh*) and because we seem stuck on
* icky and perverse decimal kilobytes (*double sigh*) - see
* router_get_advertised_bandwidth_capped() of routerlist.c and
* routerstatus_format_entry() of dirserv.c.
*/
r->bandwidthrate = rs->bandwidth_kb * 1000;
r->bandwidthcapacity = rs->bandwidth_kb * 1000;
}
return r;
}
/** Helper: get a detached signatures document for one or two
* consensuses. */
static char *
@@ -1568,101 +1528,6 @@ get_detached_sigs(networkstatus_t *ns, networkstatus_t *ns2)
return r;
}
/**
* Generate a routerstatus for v3_networkstatus test
*/
static vote_routerstatus_t *
gen_routerstatus_for_v3ns(int idx, time_t now)
{
vote_routerstatus_t *vrs=NULL;
routerstatus_t *rs;
tor_addr_t addr_ipv6;
switch (idx) {
case 0:
/* Generate the first routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.1.2.14");
rs->published_on = now-1500;
strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
memset(rs->identity_digest, 3, DIGEST_LEN);
memset(rs->descriptor_digest, 78, DIGEST_LEN);
rs->addr = 0x99008801;
rs->or_port = 443;
rs->dir_port = 8000;
/* all flags but running and v2dir cleared */
rs->is_flagged_running = 1;
rs->is_v2_dir = 1;
break;
case 1:
/* Generate the second routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.2.0.5");
rs->published_on = now-1000;
strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
memset(rs->identity_digest, 5, DIGEST_LEN);
memset(rs->descriptor_digest, 77, DIGEST_LEN);
rs->addr = 0x99009901;
rs->or_port = 443;
rs->dir_port = 0;
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
rs->ipv6_orport = 4711;
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_possible_guard = rs->is_v2_dir = 1;
break;
case 2:
/* Generate the third routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.1.0.3");
rs->published_on = now-1000;
strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
memset(rs->identity_digest, 33, DIGEST_LEN);
memset(rs->descriptor_digest, 79, DIGEST_LEN);
rs->addr = 0xAA009901;
rs->or_port = 400;
rs->dir_port = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
rs->is_possible_guard = 1;
break;
case 3:
/* Generate a fourth routerstatus that is not running. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.1.6.3");
rs->published_on = now-1000;
strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
memset(rs->identity_digest, 34, DIGEST_LEN);
memset(rs->descriptor_digest, 47, DIGEST_LEN);
rs->addr = 0xC0000203;
rs->or_port = 500;
rs->dir_port = 1999;
/* Running flag (and others) cleared */
break;
case 4:
/* No more for this test; return NULL */
vrs = NULL;
break;
default:
/* Shouldn't happen */
tt_assert(0);
}
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
tor_asprintf(&vrs->microdesc->microdesc_hash_line,
"m 9,10,11,12,13,14,15,16,17 "
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
idx);
}
done:
return vrs;
}
/** Apply tweaks to the vote list for each voter */
static int
vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now)
@@ -1694,7 +1559,7 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now)
vrs = smartlist_get(v->routerstatus_list, 0);
memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN);
tt_assert(router_add_to_routerlist(
generate_ri_from_rs(vrs), &msg,0,0) >= 0);
dir_common_generate_ri_from_rs(vrs), &msg,0,0) >= 0);
}
}
@@ -1884,7 +1749,6 @@ test_a_networkstatus(
authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL;
crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL;
crypto_pk_t *sign_skey_leg1=NULL;
const char *msg=NULL;
/*
* Sum the non-zero returns from vote_tweaks() we've seen; if vote_tweaks()
* returns non-zero, it changed net_params and we should skip the tests for
@@ -1900,8 +1764,7 @@ test_a_networkstatus(
vote_routerstatus_t *vrs;
routerstatus_t *rs;
int idx, n_rs, n_vrs;
char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL,
*cp=NULL;
char *consensus_text=NULL, *cp=NULL;
smartlist_t *votes = smartlist_new();
/* For generating the two other consensuses. */
@@ -1916,79 +1779,13 @@ test_a_networkstatus(
tt_assert(rs_test);
tt_assert(vrs_test);
/* Parse certificates and keys. */
cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
tt_assert(cert1);
cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
tt_assert(cert2);
cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
tt_assert(cert3);
sign_skey_1 = crypto_pk_new();
sign_skey_2 = crypto_pk_new();
sign_skey_3 = crypto_pk_new();
tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3,
&sign_skey_1, &sign_skey_2,
&sign_skey_3));
sign_skey_leg1 = pk_generate(4);
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1,
AUTHORITY_SIGNKEY_1, -1));
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_2,
AUTHORITY_SIGNKEY_2, -1));
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_3,
AUTHORITY_SIGNKEY_3, -1));
tt_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key));
tt_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key));
/*
* Set up a vote; generate it; try to parse it.
*/
vote = tor_malloc_zero(sizeof(networkstatus_t));
vote->type = NS_TYPE_VOTE;
vote->published = now;
vote->valid_after = now+1000;
vote->fresh_until = now+2000;
vote->valid_until = now+3000;
vote->vote_seconds = 100;
vote->dist_seconds = 200;
vote->supported_methods = smartlist_new();
smartlist_split_string(vote->supported_methods, "1 2 3", NULL, 0, -1);
vote->client_versions = tor_strdup("0.1.2.14,0.1.2.15");
vote->server_versions = tor_strdup("0.1.2.14,0.1.2.15,0.1.2.16");
vote->known_flags = smartlist_new();
smartlist_split_string(vote->known_flags,
"Authority Exit Fast Guard Running Stable V2Dir Valid",
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
vote->voters = smartlist_new();
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter1");
voter->address = tor_strdup("1.2.3.4");
voter->addr = 0x01020304;
voter->dir_port = 80;
voter->or_port = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert1->identity_key, voter->identity_digest);
smartlist_add(vote->voters, voter);
vote->cert = authority_cert_dup(cert1);
vote->net_params = smartlist_new();
smartlist_split_string(vote->net_params, "circuitwindow=101 foo=990",
NULL, 0, 0);
vote->routerstatus_list = smartlist_new();
/* add routerstatuses */
idx = 0;
do {
vrs = vrs_gen(idx, now);
if (vrs) {
smartlist_add(vote->routerstatus_list, vrs);
tt_assert(router_add_to_routerlist(generate_ri_from_rs(vrs),
&msg,0,0)>=0);
++idx;
}
} while (vrs);
n_vrs = idx;
/* dump the vote and try to parse it. */
v1_text = format_networkstatus_vote(sign_skey_1, vote);
tt_assert(v1_text);
v1 = networkstatus_parse_vote_from_string(v1_text, NULL, NS_TYPE_VOTE);
tt_assert(!dir_common_construct_vote_1(&vote, cert1, sign_skey_1, vrs_gen,
&v1, &n_vrs, now, 1));
tt_assert(v1);
/* Make sure the parsed thing was right. */
@@ -2015,6 +1812,7 @@ test_a_networkstatus(
tt_str_op(cp,OP_EQ, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid");
tor_free(cp);
tt_int_op(smartlist_len(v1->routerstatus_list),OP_EQ, n_vrs);
tor_free(vote);
if (vote_tweaks) params_tweaked += vote_tweaks(v1, 1, now);
@@ -2026,33 +1824,10 @@ test_a_networkstatus(
}
/* Generate second vote. It disagrees on some of the times,
* and doesn't list versions, and knows some crazy flags */
vote->published = now+1;
vote->fresh_until = now+3005;
vote->dist_seconds = 300;
authority_cert_free(vote->cert);
vote->cert = authority_cert_dup(cert2);
SMARTLIST_FOREACH(vote->net_params, char *, c, tor_free(c));
smartlist_clear(vote->net_params);
smartlist_split_string(vote->net_params, "bar=2000000000 circuitwindow=20",
NULL, 0, 0);
tor_free(vote->client_versions);
tor_free(vote->server_versions);
voter = smartlist_get(vote->voters, 0);
tor_free(voter->nickname);
tor_free(voter->address);
voter->nickname = tor_strdup("Voter2");
voter->address = tor_strdup("2.3.4.5");
voter->addr = 0x02030405;
crypto_pk_get_digest(cert2->identity_key, voter->identity_digest);
smartlist_add(vote->known_flags, tor_strdup("MadeOfCheese"));
smartlist_add(vote->known_flags, tor_strdup("MadeOfTin"));
smartlist_sort_strings(vote->known_flags);
/* generate and parse v2. */
v2_text = format_networkstatus_vote(sign_skey_2, vote);
tt_assert(v2_text);
v2 = networkstatus_parse_vote_from_string(v2_text, NULL, NS_TYPE_VOTE);
* and doesn't list versions, and knows some crazy flags.
* Generate and parse v2. */
tt_assert(!dir_common_construct_vote_2(&vote, cert2, sign_skey_2, vrs_gen,
&v2, &n_vrs, now, 1));
tt_assert(v2);
if (vote_tweaks) params_tweaked += vote_tweaks(v2, 2, now);
@@ -2070,34 +1845,11 @@ test_a_networkstatus(
tt_assert(vrs);
vrs_test(vrs, 2, now);
}
tor_free(vote);
/* Generate the third vote. */
vote->published = now;
vote->fresh_until = now+2003;
vote->dist_seconds = 250;
authority_cert_free(vote->cert);
vote->cert = authority_cert_dup(cert3);
SMARTLIST_FOREACH(vote->net_params, char *, c, tor_free(c));
smartlist_clear(vote->net_params);
smartlist_split_string(vote->net_params, "circuitwindow=80 foo=660",
NULL, 0, 0);
smartlist_add(vote->supported_methods, tor_strdup("4"));
vote->client_versions = tor_strdup("0.1.2.14,0.1.2.17");
vote->server_versions = tor_strdup("0.1.2.10,0.1.2.15,0.1.2.16");
voter = smartlist_get(vote->voters, 0);
tor_free(voter->nickname);
tor_free(voter->address);
voter->nickname = tor_strdup("Voter3");
voter->address = tor_strdup("3.4.5.6");
voter->addr = 0x03040506;
crypto_pk_get_digest(cert3->identity_key, voter->identity_digest);
/* This one has a legacy id. */
memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
v3_text = format_networkstatus_vote(sign_skey_3, vote);
tt_assert(v3_text);
v3 = networkstatus_parse_vote_from_string(v3_text, NULL, NS_TYPE_VOTE);
/* Generate the third vote with a legacy id. */
tt_assert(!dir_common_construct_vote_3(&vote, cert3, sign_skey_3, vrs_gen,
&v3, &n_vrs, now, 1));
tt_assert(v3);
if (vote_tweaks) params_tweaked += vote_tweaks(v3, 3, now);
@@ -2324,9 +2076,6 @@ test_a_networkstatus(
done:
tor_free(cp);
smartlist_free(votes);
tor_free(v1_text);
tor_free(v2_text);
tor_free(v3_text);
tor_free(consensus_text);
tor_free(consensus_text_md);
@@ -2383,7 +2132,7 @@ static void
test_dir_v3_networkstatus(void *arg)
{
(void)arg;
test_a_networkstatus(gen_routerstatus_for_v3ns,
test_a_networkstatus(dir_common_gen_routerstatus_for_v3ns,
vote_tweaks_for_v3ns,
test_vrs_for_v3ns,
test_consensus_for_v3ns,
+418
View File
@@ -0,0 +1,418 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2014, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define DIRVOTE_PRIVATE
#include "crypto.h"
#include "test.h"
#include "container.h"
#include "or.h"
#include "dirvote.h"
#include "nodelist.h"
#include "routerlist.h"
#include "test_dir_common.h"
void dir_common_setup_vote(networkstatus_t **vote, time_t now);
networkstatus_t * dir_common_add_rs_and_parse(networkstatus_t *vote,
networkstatus_t **vote_out,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
crypto_pk_t *sign_skey, int *n_vrs,
time_t now, int clear_rl);
extern const char AUTHORITY_CERT_1[];
extern const char AUTHORITY_SIGNKEY_1[];
extern const char AUTHORITY_CERT_2[];
extern const char AUTHORITY_SIGNKEY_2[];
extern const char AUTHORITY_CERT_3[];
extern const char AUTHORITY_SIGNKEY_3[];
/** Initialize and set auth certs and keys
* Returns 0 on success, -1 on failure. Clean up handled by caller.
*/
int
dir_common_authority_pk_init(authority_cert_t **cert1,
authority_cert_t **cert2,
authority_cert_t **cert3,
crypto_pk_t **sign_skey_1,
crypto_pk_t **sign_skey_2,
crypto_pk_t **sign_skey_3)
{
/* Parse certificates and keys. */
authority_cert_t *cert;
cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
tt_assert(cert);
tt_assert(cert->identity_key);
*cert1 = cert;
tt_assert(*cert1);
*cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
tt_assert(*cert2);
*cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
tt_assert(*cert3);
*sign_skey_1 = crypto_pk_new();
*sign_skey_2 = crypto_pk_new();
*sign_skey_3 = crypto_pk_new();
tt_assert(!crypto_pk_read_private_key_from_string(*sign_skey_1,
AUTHORITY_SIGNKEY_1, -1));
tt_assert(!crypto_pk_read_private_key_from_string(*sign_skey_2,
AUTHORITY_SIGNKEY_2, -1));
tt_assert(!crypto_pk_read_private_key_from_string(*sign_skey_3,
AUTHORITY_SIGNKEY_3, -1));
tt_assert(!crypto_pk_cmp_keys(*sign_skey_1, (*cert1)->signing_key));
tt_assert(!crypto_pk_cmp_keys(*sign_skey_2, (*cert2)->signing_key));
return 0;
done:
return -1;
}
/**
* Generate a routerstatus for v3_networkstatus test.
*/
vote_routerstatus_t *
dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
{
vote_routerstatus_t *vrs=NULL;
routerstatus_t *rs = NULL;
tor_addr_t addr_ipv6;
switch (idx) {
case 0:
/* Generate the first routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.1.2.14");
rs->published_on = now-1500;
strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_1, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_1, DIGEST_LEN);
rs->addr = 0x99008801;
rs->or_port = 443;
rs->dir_port = 8000;
/* all flags but running and v2dir cleared */
rs->is_flagged_running = 1;
rs->is_v2_dir = 1;
break;
case 1:
/* Generate the second routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.2.0.5");
rs->published_on = now-1000;
strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_2, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_2, DIGEST_LEN);
rs->addr = 0x99009901;
rs->or_port = 443;
rs->dir_port = 0;
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
rs->ipv6_orport = 4711;
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_possible_guard = rs->is_v2_dir = 1;
break;
case 2:
/* Generate the third routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.1.0.3");
rs->published_on = now-1000;
strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_3, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_3, DIGEST_LEN);
rs->addr = 0xAA009901;
rs->or_port = 400;
rs->dir_port = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
rs->is_possible_guard = 1;
break;
case 3:
/* Generate a fourth routerstatus that is not running. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
vrs->version = tor_strdup("0.1.6.3");
rs->published_on = now-1000;
strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_4, DIGEST_LEN);
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_4, DIGEST_LEN);
rs->addr = 0xC0000203;
rs->or_port = 500;
rs->dir_port = 1999;
/* Running flag (and others) cleared */
break;
case 4:
/* No more for this test; return NULL */
vrs = NULL;
break;
default:
/* Shouldn't happen */
tt_assert(0);
}
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
tor_asprintf(&vrs->microdesc->microdesc_hash_line,
"m 9,10,11,12,13,14,15,16,17,18,19 "
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
idx);
}
done:
return vrs;
}
/** Initialize networkstatus vote object attributes. */
void
dir_common_setup_vote(networkstatus_t **vote, time_t now)
{
*vote = tor_malloc_zero(sizeof(networkstatus_t));
(*vote)->type = NS_TYPE_VOTE;
(*vote)->published = now;
(*vote)->supported_methods = smartlist_new();
(*vote)->known_flags = smartlist_new();
(*vote)->net_params = smartlist_new();
(*vote)->routerstatus_list = smartlist_new();
(*vote)->voters = smartlist_new();
}
/** Helper: Make a new routerinfo containing the right information for a
* given vote_routerstatus_t. */
routerinfo_t *
dir_common_generate_ri_from_rs(const vote_routerstatus_t *vrs)
{
routerinfo_t *r;
const routerstatus_t *rs = &vrs->status;
static time_t published = 0;
r = tor_malloc_zero(sizeof(routerinfo_t));
r->cert_expiration_time = TIME_MAX;
memcpy(r->cache_info.identity_digest, rs->identity_digest, DIGEST_LEN);
memcpy(r->cache_info.signed_descriptor_digest, rs->descriptor_digest,
DIGEST_LEN);
r->cache_info.do_not_cache = 1;
r->cache_info.routerlist_index = -1;
r->cache_info.signed_descriptor_body =
tor_strdup("123456789012345678901234567890123");
r->cache_info.signed_descriptor_len =
strlen(r->cache_info.signed_descriptor_body);
r->exit_policy = smartlist_new();
r->cache_info.published_on = ++published + time(NULL);
if (rs->has_bandwidth) {
/*
* Multiply by 1000 because the routerinfo_t and the routerstatus_t
* seem to use different units (*sigh*) and because we seem stuck on
* icky and perverse decimal kilobytes (*double sigh*) - see
* router_get_advertised_bandwidth_capped() of routerlist.c and
* routerstatus_format_entry() of dirserv.c.
*/
r->bandwidthrate = rs->bandwidth_kb * 1000;
r->bandwidthcapacity = rs->bandwidth_kb * 1000;
}
return r;
}
/** Create routerstatuses and signed vote.
* Create routerstatuses using *vrs_gen* and add them to global routerlist.
* Next, create signed vote using *sign_skey* and *vote*, which should have
* predefined header fields.
* Setting *clear_rl* clears the global routerlist before adding the new
* routers.
* Return the signed vote, same as *vote_out*. Save the number of routers added
* in *n_vrs*.
*/
networkstatus_t *
dir_common_add_rs_and_parse(networkstatus_t *vote, networkstatus_t **vote_out,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
crypto_pk_t *sign_skey, int *n_vrs, time_t now,
int clear_rl)
{
vote_routerstatus_t *vrs;
char *v_text=NULL;
const char *msg=NULL;
int idx;
was_router_added_t router_added = -1;
*vote_out = NULL;
if (clear_rl) {
nodelist_free_all();
routerlist_free_all();
}
idx = 0;
do {
vrs = vrs_gen(idx, now);
if (vrs) {
smartlist_add(vote->routerstatus_list, vrs);
router_added =
router_add_to_routerlist(dir_common_generate_ri_from_rs(vrs),
&msg,0,0);
tt_assert(router_added >= 0);
++idx;
}
} while (vrs);
*n_vrs = idx;
/* dump the vote and try to parse it. */
v_text = format_networkstatus_vote(sign_skey, vote);
tt_assert(v_text);
*vote_out = networkstatus_parse_vote_from_string(v_text, NULL, NS_TYPE_VOTE);
done:
if (v_text)
tor_free(v_text);
return *vote_out;
}
/** Create a fake *vote* where *cert* describes the signer, *sign_skey*
* is the signing key, and *vrs_gen* is the function we'll use to create the
* routers on which we're voting.
* We pass *vote_out*, *n_vrs*, and *clear_rl* directly to vrs_gen().
* Return 0 on success, return -1 on failure.
*/
int
dir_common_construct_vote_1(networkstatus_t **vote, authority_cert_t *cert,
crypto_pk_t *sign_skey,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
networkstatus_t **vote_out, int *n_vrs,
time_t now, int clear_rl)
{
networkstatus_voter_info_t *voter;
dir_common_setup_vote(vote, now);
(*vote)->valid_after = now+1000;
(*vote)->fresh_until = now+2000;
(*vote)->valid_until = now+3000;
(*vote)->vote_seconds = 100;
(*vote)->dist_seconds = 200;
smartlist_split_string((*vote)->supported_methods, "1 2 3", NULL, 0, -1);
(*vote)->client_versions = tor_strdup("0.1.2.14,0.1.2.15");
(*vote)->server_versions = tor_strdup("0.1.2.14,0.1.2.15,0.1.2.16");
smartlist_split_string((*vote)->known_flags,
"Authority Exit Fast Guard Running Stable V2Dir Valid",
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter1");
voter->address = tor_strdup("1.2.3.4");
voter->addr = 0x01020304;
voter->dir_port = 80;
voter->or_port = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
/*
* Set up a vote; generate it; try to parse it.
*/
smartlist_add((*vote)->voters, voter);
(*vote)->cert = authority_cert_dup(cert);
smartlist_split_string((*vote)->net_params, "circuitwindow=101 foo=990",
NULL, 0, 0);
*n_vrs = 0;
/* add routerstatuses */
if (!dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
n_vrs, now, clear_rl))
return -1;
return 0;
}
/** See dir_common_construct_vote_1.
* Produces a vote with slightly different values.
*/
int
dir_common_construct_vote_2(networkstatus_t **vote, authority_cert_t *cert,
crypto_pk_t *sign_skey,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
networkstatus_t **vote_out, int *n_vrs,
time_t now, int clear_rl)
{
networkstatus_voter_info_t *voter;
dir_common_setup_vote(vote, now);
(*vote)->type = NS_TYPE_VOTE;
(*vote)->published += 1;
(*vote)->valid_after = now+1000;
(*vote)->fresh_until = now+3005;
(*vote)->valid_until = now+3000;
(*vote)->vote_seconds = 100;
(*vote)->dist_seconds = 300;
smartlist_split_string((*vote)->supported_methods, "1 2 3", NULL, 0, -1);
smartlist_split_string((*vote)->known_flags,
"Authority Exit Fast Guard MadeOfCheese MadeOfTin "
"Running Stable V2Dir Valid", 0,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter2");
voter->address = tor_strdup("2.3.4.5");
voter->addr = 0x02030405;
voter->dir_port = 80;
voter->or_port = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
/*
* Set up a vote; generate it; try to parse it.
*/
smartlist_add((*vote)->voters, voter);
(*vote)->cert = authority_cert_dup(cert);
(*vote)->net_params = smartlist_new();
smartlist_split_string((*vote)->net_params,
"bar=2000000000 circuitwindow=20",
NULL, 0, 0);
/* add routerstatuses */
/* dump the vote and try to parse it. */
dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
n_vrs, now, clear_rl);
return 0;
}
/** See dir_common_construct_vote_1.
* Produces a vote with slightly different values. Adds a legacy key.
*/
int
dir_common_construct_vote_3(networkstatus_t **vote, authority_cert_t *cert,
crypto_pk_t *sign_skey,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
networkstatus_t **vote_out, int *n_vrs,
time_t now, int clear_rl)
{
networkstatus_voter_info_t *voter;
dir_common_setup_vote(vote, now);
(*vote)->valid_after = now+1000;
(*vote)->fresh_until = now+2003;
(*vote)->valid_until = now+3000;
(*vote)->vote_seconds = 100;
(*vote)->dist_seconds = 250;
smartlist_split_string((*vote)->supported_methods, "1 2 3 4", NULL, 0, -1);
(*vote)->client_versions = tor_strdup("0.1.2.14,0.1.2.17");
(*vote)->server_versions = tor_strdup("0.1.2.10,0.1.2.15,0.1.2.16");
smartlist_split_string((*vote)->known_flags,
"Authority Exit Fast Guard Running Stable V2Dir Valid",
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup("Voter2");
voter->address = tor_strdup("3.4.5.6");
voter->addr = 0x03040506;
voter->dir_port = 80;
voter->or_port = 9000;
voter->contact = tor_strdup("voter@example.com");
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
/*
* Set up a vote; generate it; try to parse it.
*/
smartlist_add((*vote)->voters, voter);
(*vote)->cert = authority_cert_dup(cert);
smartlist_split_string((*vote)->net_params, "circuitwindow=80 foo=660",
NULL, 0, 0);
/* add routerstatuses */
/* dump the vote and try to parse it. */
dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
n_vrs, now, clear_rl);
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2014, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
#include "networkstatus.h"
#include "routerparse.h"
#define TEST_DIR_ROUTER_ID_1 3
#define TEST_DIR_ROUTER_ID_2 5
#define TEST_DIR_ROUTER_ID_3 33
#define TEST_DIR_ROUTER_ID_4 34
#define TEST_DIR_ROUTER_DD_1 78
#define TEST_DIR_ROUTER_DD_2 77
#define TEST_DIR_ROUTER_DD_3 79
#define TEST_DIR_ROUTER_DD_4 44
int dir_common_authority_pk_init(authority_cert_t **cert1,
authority_cert_t **cert2,
authority_cert_t **cert3,
crypto_pk_t **sign_skey_1,
crypto_pk_t **sign_skey_2,
crypto_pk_t **sign_skey_3);
routerinfo_t * dir_common_generate_ri_from_rs(const vote_routerstatus_t *vrs);
vote_routerstatus_t * dir_common_gen_routerstatus_for_v3ns(int idx,
time_t now);
int dir_common_construct_vote_1(networkstatus_t **vote,
authority_cert_t *cert1,
crypto_pk_t *sign_skey,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
networkstatus_t **vote_out, int *n_vrs, time_t now,
int clear_rl);
int dir_common_construct_vote_2(networkstatus_t **vote,
authority_cert_t *cert2,
crypto_pk_t *sign_skey,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
networkstatus_t **vote_out, int *n_vrs, time_t now,
int clear_rl);
int dir_common_construct_vote_3(networkstatus_t **vote,
authority_cert_t *cert3,
crypto_pk_t *sign_skey,
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
networkstatus_t **vote_out, int *n_vrs, time_t now,
int clear_rl);
+2
View File
@@ -66,6 +66,8 @@ test_nodelist_node_get_verbose_nickname_not_named(void *arg)
static void
test_nodelist_node_is_dir(void *arg)
{
(void)arg;
routerstatus_t rs;
routerinfo_t ri;
node_t node;
+279 -1
View File
@@ -1,11 +1,35 @@
/* Copyright (c) 2014, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include <math.h>
#include <time.h>
#define DIRVOTE_PRIVATE
#define NETWORKSTATUS_PRIVATE
#define ROUTERLIST_PRIVATE
#define TOR_UNIT_TESTING
#include "or.h"
#include "routerlist.h"
#include "config.h"
#include "container.h"
#include "directory.h"
#include "dirvote.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
#include "routerlist.h"
#include "routerparse.h"
#include "test.h"
#include "test_dir_common.h"
extern const char AUTHORITY_CERT_1[];
extern const char AUTHORITY_SIGNKEY_1[];
extern const char AUTHORITY_CERT_2[];
extern const char AUTHORITY_SIGNKEY_2[];
extern const char AUTHORITY_CERT_3[];
extern const char AUTHORITY_SIGNKEY_3[];
void construct_consensus(const char **consensus_text_md);
/* 4 digests + 3 sep + pre + post + NULL */
static char output[4*BASE64_DIGEST256_LEN+3+2+2+1];
@@ -94,12 +118,266 @@ test_routerlist_launch_descriptor_downloads(void *arg)
smartlist_free(downloadable);
}
void
construct_consensus(const char **consensus_text_md)
{
networkstatus_t *vote = NULL;
networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL;
networkstatus_voter_info_t *voter = NULL;
authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL;
crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL;
crypto_pk_t *sign_skey_leg=NULL;
time_t now = time(NULL);
smartlist_t *votes = NULL;
addr_policy_t *pol1 = NULL, *pol2 = NULL, *pol3 = NULL;
int n_vrs;
tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3,
&sign_skey_1, &sign_skey_2,
&sign_skey_3));
sign_skey_leg = pk_generate(4);
dir_common_construct_vote_1(&vote, cert1, sign_skey_1,
&dir_common_gen_routerstatus_for_v3ns,
&v1, &n_vrs, now, 1);
tt_assert(v1);
tt_int_op(n_vrs, ==, 4);
tt_int_op(smartlist_len(v1->routerstatus_list), ==, 4);
dir_common_construct_vote_2(&vote, cert2, sign_skey_2,
&dir_common_gen_routerstatus_for_v3ns,
&v2, &n_vrs, now, 1);
tt_assert(v2);
tt_int_op(n_vrs, ==, 4);
tt_int_op(smartlist_len(v2->routerstatus_list), ==, 4);
dir_common_construct_vote_3(&vote, cert3, sign_skey_3,
&dir_common_gen_routerstatus_for_v3ns,
&v3, &n_vrs, now, 1);
tt_assert(v3);
tt_int_op(n_vrs, ==, 4);
tt_int_op(smartlist_len(v3->routerstatus_list), ==, 4);
votes = smartlist_new();
smartlist_add(votes, v1);
smartlist_add(votes, v2);
smartlist_add(votes, v3);
*consensus_text_md = networkstatus_compute_consensus(votes, 3,
cert1->identity_key,
sign_skey_1,
"AAAAAAAAAAAAAAAAAAAA",
sign_skey_leg,
FLAV_MICRODESC);
tt_assert(*consensus_text_md);
done:
if (vote)
tor_free(vote);
if (voter)
tor_free(voter);
if (pol1)
tor_free(pol1);
if (pol2)
tor_free(pol2);
if (pol3)
tor_free(pol3);
}
static void
test_router_pick_directory_server_impl(void *arg)
{
(void)arg;
networkstatus_t *con_md = NULL;
const char *consensus_text_md = NULL;
int flags = PDS_IGNORE_FASCISTFIREWALL|PDS_RETRY_IF_NO_SERVERS;
or_options_t *options = get_options_mutable();
const routerstatus_t *rs = NULL;
options->UseMicrodescriptors = 1;
char *router1_id = NULL, *router2_id = NULL, *router3_id = NULL;
node_t *node_router1 = NULL, *node_router2 = NULL, *node_router3 = NULL;
config_line_t *policy_line = NULL;
time_t now = time(NULL);
int tmp_dirport1, tmp_dirport3;
(void)arg;
/* No consensus available, fail early */
rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL);
tt_assert(rs == NULL);
construct_consensus(&consensus_text_md);
tt_assert(consensus_text_md);
con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL,
NS_TYPE_CONSENSUS);
tt_assert(con_md);
tt_int_op(con_md->flavor,==, FLAV_MICRODESC);
tt_assert(con_md->routerstatus_list);
tt_int_op(smartlist_len(con_md->routerstatus_list), ==, 3);
tt_assert(!networkstatus_set_current_consensus_from_ns(con_md,
"microdesc"));
nodelist_set_consensus(con_md);
nodelist_assert_ok();
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
/* We should not fail now we have a consensus and routerstatus_list
* and nodelist are populated. */
tt_assert(rs != NULL);
/* Manipulate the nodes so we get the dir server we expect */
router1_id = tor_malloc(DIGEST_LEN);
memset(router1_id, TEST_DIR_ROUTER_ID_1, DIGEST_LEN);
router2_id = tor_malloc(DIGEST_LEN);
memset(router2_id, TEST_DIR_ROUTER_ID_2, DIGEST_LEN);
router3_id = tor_malloc(DIGEST_LEN);
memset(router3_id, TEST_DIR_ROUTER_ID_3, DIGEST_LEN);
node_router1 = node_get_mutable_by_id(router1_id);
node_router2 = node_get_mutable_by_id(router2_id);
node_router3 = node_get_mutable_by_id(router3_id);
node_router1->is_running = 0;
node_router3->is_running = 0;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
rs = NULL;
node_router1->is_running = 1;
node_router3->is_running = 1;
node_router1->rs->is_v2_dir = 0;
node_router3->rs->is_v2_dir = 0;
tmp_dirport1 = node_router1->rs->dir_port;
tmp_dirport3 = node_router3->rs->dir_port;
node_router1->rs->dir_port = 0;
node_router3->rs->dir_port = 0;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
rs = NULL;
node_router1->rs->is_v2_dir = 1;
node_router3->rs->is_v2_dir = 1;
node_router1->rs->dir_port = tmp_dirport1;
node_router3->rs->dir_port = tmp_dirport3;
node_router1->is_valid = 0;
node_router3->is_valid = 0;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
rs = NULL;
node_router1->is_valid = 1;
node_router3->is_valid = 1;
flags |= PDS_FOR_GUARD;
node_router1->using_as_guard = 1;
node_router2->using_as_guard = 1;
node_router3->using_as_guard = 1;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs == NULL);
node_router1->using_as_guard = 0;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
rs = NULL;
node_router2->using_as_guard = 0;
node_router3->using_as_guard = 0;
/* One not valid, one guard. This should leave one remaining */
node_router1->is_valid = 0;
node_router2->using_as_guard = 1;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN));
rs = NULL;
node_router1->is_valid = 1;
node_router2->using_as_guard = 0;
/* Manipulate overloaded */
node_router2->rs->last_dir_503_at = now;
node_router3->rs->last_dir_503_at = now;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
node_router2->rs->last_dir_503_at = 0;
node_router3->rs->last_dir_503_at = 0;
/* Set a Fascist firewall */
flags &= ! PDS_IGNORE_FASCISTFIREWALL;
policy_line = tor_malloc_zero(sizeof(config_line_t));
policy_line->key = tor_strdup("ReachableORAddresses");
policy_line->value = tor_strdup("accept *:442, reject *:*");
options->ReachableORAddresses = policy_line;
policies_parse_from_options(options);
node_router1->rs->or_port = 444;
node_router2->rs->or_port = 443;
node_router3->rs->or_port = 442;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN));
node_router1->rs->or_port = 442;
node_router2->rs->or_port = 443;
node_router3->rs->or_port = 444;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
/* Fascist firewall and overloaded */
node_router1->rs->or_port = 442;
node_router2->rs->or_port = 443;
node_router3->rs->or_port = 442;
node_router3->rs->last_dir_503_at = now;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
node_router3->rs->last_dir_503_at = 0;
/* Fascists against OR and Dir */
policy_line = tor_malloc_zero(sizeof(config_line_t));
policy_line->key = tor_strdup("ReachableAddresses");
policy_line->value = tor_strdup("accept *:80, reject *:*");
options->ReachableDirAddresses = policy_line;
policies_parse_from_options(options);
node_router1->rs->or_port = 442;
node_router2->rs->or_port = 441;
node_router3->rs->or_port = 443;
node_router1->rs->dir_port = 80;
node_router2->rs->dir_port = 80;
node_router3->rs->dir_port = 81;
node_router1->rs->last_dir_503_at = now;
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
node_router1->rs->last_dir_503_at = 0;
done:
if (router1_id)
tor_free(router1_id);
if (router2_id)
tor_free(router2_id);
if (router3_id)
tor_free(router3_id);
if (options->ReachableORAddresses ||
options->ReachableDirAddresses)
policies_free_all();
}
#define NODE(name, flags) \
{ #name, test_routerlist_##name, (flags), NULL, NULL }
#define ROUTER(name,flags) \
{ #name, test_router_##name, (flags), NULL, NULL }
struct testcase_t routerlist_tests[] = {
NODE(initiate_descriptor_downloads, 0),
NODE(launch_descriptor_downloads, 0),
ROUTER(pick_directory_server_impl, TT_FORK),
END_OF_TESTCASES
};