Merge branch 'tickets_5529_5534_5974_6406'

This commit is contained in:
Nick Mathewson
2012-07-19 17:52:21 -04:00
16 changed files with 193 additions and 53 deletions
+3
View File
@@ -0,0 +1,3 @@
o Code refactoring:
- Move last_reachable and testing_since from routerinfo_t to
node_t. Implements enhancement 5529.
+4
View File
@@ -0,0 +1,4 @@
o Major features (IPv6):
Add support for bridge authorities to accept IPv6 bridge addresses
and include them in network status documents. Implements
enhancement 5534.
+4
View File
@@ -0,0 +1,4 @@
o Minor features:
- Add new configure option AuthDirHasIPv6Connectivity. Implements
feature #5974.
+4
View File
@@ -0,0 +1,4 @@
o Minor features:
- Add new configure option AuthDirPublishIPv6. Implements
enhancement #6406.
+14
View File
@@ -1728,6 +1728,20 @@ DIRECTORY AUTHORITY SERVER OPTIONS
votes on whether to accept relays as hidden service directories.
(Default: 1)
**AuthDirHasIPv6Connectivity** **0**|**1**|**auto**::
Authoritative directories only. When set to 0, OR ports with an
IPv6 address are being accepted without reachability testing.
When set to 1, IPv6 OR ports are being tested just like IPv4 OR
ports. When set to auto, Tor tries to find out if the authority
relay has IPv6 connectivity or not. (Default: auto)
**AuthDirPublishIPv6** **0**|**1**::
Authoritative directories only. When set to 0, Tor will not
include IPv6 OR ports in votes. When set to 1, Tor will vote for
IPv6 OR ports. (Default: 0).
HIDDEN SERVICE OPTIONS
----------------------
+2
View File
@@ -201,6 +201,8 @@ static config_var_t _option_vars[] = {
V(AuthDirListBadExits, BOOL, "0"),
V(AuthDirMaxServersPerAddr, UINT, "2"),
V(AuthDirMaxServersPerAuthAddr,UINT, "5"),
V(AuthDirHasIPv6Connectivity, AUTOBOOL, "auto"),
V(AuthDirPublishIPv6, BOOL, "0"),
VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"),
V(AutomapHostsOnResolve, BOOL, "0"),
V(AutomapHostsSuffixes, CSV, ".onion,.exit"),
+1 -1
View File
@@ -1540,7 +1540,7 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
return -1;
}
if (authdir_mode_tests_reachability(options)) {
dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
dirserv_orconn_tls_done(&conn->_base.addr, conn->_base.port,
(const char*)peer_id);
}
+74 -23
View File
@@ -988,7 +988,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
answer = ! we_are_hibernating();
} else if (router->is_hibernating &&
(router->cache_info.published_on +
HIBERNATION_PUBLICATION_SKEW) > router->last_reachable) {
HIBERNATION_PUBLICATION_SKEW) > node->last_reachable) {
/* A hibernating router is down unless we (somehow) had contact with it
* since it declared itself to be hibernating. */
answer = 0;
@@ -998,7 +998,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
} else {
/* Otherwise, a router counts as up if we found it reachable in the last
REACHABLE_TIMEOUT seconds. */
answer = (now < router->last_reachable + REACHABLE_TIMEOUT);
answer = (now < node->last_reachable + REACHABLE_TIMEOUT);
}
if (!answer && running_long_enough_to_decide_unreachable()) {
@@ -1010,9 +1010,9 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
it.
*/
time_t when = now;
if (router->last_reachable &&
router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now)
when = router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD;
if (node->last_reachable &&
node->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now)
when = node->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD;
rep_hist_note_router_unreachable(router->cache_info.identity_digest, when);
}
@@ -2088,6 +2088,21 @@ routerstatus_format_entry(char *buf, size_t buf_len,
return 0;
cp = buf + strlen(buf);
/* Possible "a" line, not included in consensus for now. */
if (!tor_addr_is_null(&rs->ipv6_addr)) {
const char *addr_str = fmt_and_decorate_addr(&rs->ipv6_addr);
r = tor_snprintf(cp, buf_len - (cp-buf),
"a %s:%d\n",
addr_str,
(int)rs->ipv6_orport);
if (r<0) {
log_warn(LD_BUG, "Not enough space in buffer.");
return -1;
}
cp += strlen(cp);
}
/* NOTE: Whenever this list expands, be sure to increase MAX_FLAG_LINE_LEN*/
r = tor_snprintf(cp, buf_len - (cp-buf),
"s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
@@ -2453,6 +2468,16 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
strlcpy(rs->nickname, ri->nickname, sizeof(rs->nickname));
rs->or_port = ri->or_port;
rs->dir_port = ri->dir_port;
if (options->AuthDirPublishIPv6 == 1 &&
!tor_addr_is_null(&ri->ipv6_addr) &&
(options->AuthDirHasIPv6Connectivity == 0 ||
node->last_reachable6 >= now - REACHABLE_TIMEOUT)) {
/* We're configured for publishing IPv6 OR ports. There's an IPv6
OR port and it's reachable (or we know that we're not on IPv6)
so copy it to the routerstatus. */
tor_addr_copy(&rs->ipv6_addr, &ri->ipv6_addr);
rs->ipv6_orport = ri->ipv6_orport;
}
}
/** Routerstatus <b>rs</b> is part of a group of routers that are on
@@ -3273,36 +3298,42 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
* Inform the reachability checker that we could get to this guy.
*/
void
dirserv_orconn_tls_done(const char *address,
dirserv_orconn_tls_done(const tor_addr_t *addr,
uint16_t or_port,
const char *digest_rcvd)
{
routerinfo_t *ri;
node_t *node = NULL;
tor_addr_port_t orport;
routerinfo_t *ri = NULL;
time_t now = time(NULL);
tor_assert(address);
tor_assert(addr);
tor_assert(digest_rcvd);
ri = router_get_mutable_by_digest(digest_rcvd);
if (ri == NULL)
node = node_get_mutable_by_id(digest_rcvd);
if (node == NULL || node->ri == NULL)
return;
ri = node->ri;
if (!strcasecmp(address, ri->address) && or_port == ri->or_port) {
tor_addr_copy(&orport.addr, addr);
orport.port = or_port;
if (router_has_orport(ri, &orport)) {
/* Found the right router. */
if (!authdir_mode_bridge(get_options()) ||
ri->purpose == ROUTER_PURPOSE_BRIDGE) {
char addrstr[TOR_ADDR_BUF_LEN];
/* This is a bridge or we're not a bridge authorititative --
mark it as reachable. */
tor_addr_t addr, *addrp=NULL;
log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
router_describe(ri),
address, ri->or_port);
if (tor_addr_parse(&addr, ri->address) != -1)
addrp = &addr;
else
log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address);
rep_hist_note_router_reachable(digest_rcvd, addrp, or_port, now);
ri->last_reachable = now;
tor_addr_to_str(addrstr, addr, sizeof(addrstr), 1),
ri->or_port);
if (tor_addr_family(addr) == AF_INET) {
rep_hist_note_router_reachable(digest_rcvd, addr, or_port, now);
node->last_reachable = now;
} else if (tor_addr_family(addr) == AF_INET6) {
/* No rephist for IPv6. */
node->last_reachable6 = now;
}
}
}
}
@@ -3325,7 +3356,7 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
/* It just came out of hibernation; launch a reachability test */
return 1;
}
if (! routers_have_same_or_addr(ri, ri_old)) {
if (! routers_have_same_or_addrs(ri, ri_old)) {
/* Address or port changed; launch a reachability test */
return 1;
}
@@ -3338,15 +3369,35 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
void
dirserv_single_reachability_test(time_t now, routerinfo_t *router)
{
node_t *node = NULL;
tor_addr_t router_addr;
tor_assert(router);
node = node_get_mutable_by_id(router->cache_info.identity_digest);
tor_assert(node);
/* IPv4. */
log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
router->nickname, router->address, router->or_port);
/* Remember when we started trying to determine reachability */
if (!router->testing_since)
router->testing_since = now;
if (!node->testing_since)
node->testing_since = now;
tor_addr_from_ipv4h(&router_addr, router->addr);
connection_or_connect(&router_addr, router->or_port,
router->cache_info.identity_digest);
/* Possible IPv6. */
if (!tor_addr_is_null(&router->ipv6_addr)) {
char addrstr[TOR_ADDR_BUF_LEN];
log_debug(LD_OR, "Testing reachability of %s at %s:%u.",
router->nickname,
tor_addr_to_str(addrstr, &router->ipv6_addr, sizeof(addrstr), 1),
router->ipv6_orport);
if (!node->testing_since6)
node->testing_since6 = now;
connection_or_connect(&router->ipv6_addr, router->ipv6_orport,
router->cache_info.identity_digest);
}
}
/** Auth dir server only: load balance such that we only
+1 -1
View File
@@ -107,7 +107,7 @@ int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
int is_extrainfo);
int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
const char **msg);
void dirserv_orconn_tls_done(const char *address,
void dirserv_orconn_tls_done(const tor_addr_t *addr,
uint16_t or_port,
const char *digest_rcvd);
int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+33 -4
View File
@@ -115,19 +115,48 @@ node_get_or_create(const char *identity_digest)
return node;
}
/** Add <b>ri</b> to the nodelist. */
/** Called when a node's address changes. */
static void
node_addrs_changed(node_t *node)
{
node->last_reachable = node->last_reachable6 = 0;
node->testing_since = node->testing_since6 = 0;
node->country = -1;
}
/** Add <b>ri</b> to an appropriate node in the nodelist. If we replace an
* old routerinfo, and <b>ri_old_out</b> is not NULL, set *<b>ri_old_out</b>
* to the previous routerinfo.
*/
node_t *
nodelist_add_routerinfo(routerinfo_t *ri)
nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out)
{
node_t *node;
const char *id_digest;
int had_router = 0;
tor_assert(ri);
init_nodelist();
node = node_get_or_create(ri->cache_info.identity_digest);
id_digest = ri->cache_info.identity_digest;
node = node_get_or_create(id_digest);
if (node->ri) {
if (!routers_have_same_or_addrs(node->ri, ri)) {
node_addrs_changed(node);
}
had_router = 1;
if (ri_old_out)
*ri_old_out = node->ri;
} else {
if (ri_old_out)
*ri_old_out = NULL;
}
node->ri = ri;
if (node->country == -1)
node_set_country(node);
if (authdir_mode(get_options())) {
if (authdir_mode(get_options()) && !had_router) {
const char *discard=NULL;
uint32_t status = dirserv_router_get_status(ri, &discard);
dirserv_set_node_flags_from_authoritative_status(node, status);
+1 -1
View File
@@ -15,7 +15,7 @@
node_t *node_get_mutable_by_id(const char *identity_digest);
const node_t *node_get_by_id(const char *identity_digest);
const node_t *node_get_by_hex_id(const char *identity_digest);
node_t *nodelist_add_routerinfo(routerinfo_t *ri);
node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
node_t *nodelist_add_microdesc(microdesc_t *md);
void nodelist_set_consensus(networkstatus_t *ns);
+19 -12
View File
@@ -1793,15 +1793,6 @@ typedef struct {
* things; see notes on ROUTER_PURPOSE_* macros above.
*/
uint8_t purpose;
/* The below items are used only by authdirservers for
* reachability testing. */
/** When was the last time we could reach this OR? */
time_t last_reachable;
/** When did we start testing reachability for this OR? */
time_t testing_since;
} routerinfo_t;
/** Information needed to keep and cache a signed extra-info document. */
@@ -1833,6 +1824,8 @@ typedef struct routerstatus_t {
uint32_t addr; /**< IPv4 address for this router. */
uint16_t or_port; /**< OR port for this router. */
uint16_t dir_port; /**< Directory port for this router. */
tor_addr_t ipv6_addr; /**< IPv6 address for this router. */
uint16_t ipv6_orport; /**<IPV6 OR port for this router. */
unsigned int is_authority:1; /**< True iff this router is an authority. */
unsigned int is_exit:1; /**< True iff this router is a good exit. */
unsigned int is_stable:1; /**< True iff this router stays up a long time. */
@@ -2006,13 +1999,13 @@ typedef struct node_t {
routerstatus_t *rs;
/* local info: copied from routerstatus, then possibly frobbed based
* on experience. Authorities set this stuff directly. */
* on experience. Authorities set this stuff directly. Note that
* these reflect knowledge of the primary (IPv4) OR port only. */
unsigned int is_running:1; /**< As far as we know, is this OR currently
* running? */
unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
* (For Authdir: Have we validated this OR?)
*/
* (For Authdir: Have we validated this OR?) */
unsigned int is_fast:1; /** Do we think this is a fast OR? */
unsigned int is_stable:1; /** Do we think this is a stable OR? */
unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
@@ -2036,7 +2029,19 @@ typedef struct node_t {
/* Local info: derived. */
/** According to the geoip db what country is this router in? */
/* XXXprop186 what is this suppose to mean with multiple OR ports? */
country_t country;
/* The below items are used only by authdirservers for
* reachability testing. */
/** When was the last time we could reach this OR? */
time_t last_reachable; /* IPv4. */
time_t last_reachable6; /* IPv6. */
/** When did we start testing reachability for this OR? */
time_t testing_since; /* IPv4. */
time_t testing_since6; /* IPv6. */
} node_t;
/** How many times will we try to download a router's descriptor before giving
@@ -3268,6 +3273,8 @@ typedef struct {
int AuthDirMaxServersPerAuthAddr; /**< Do not permit more than this
* number of servers per IP address shared
* with an authority. */
int AuthDirHasIPv6Connectivity; /**< Autoboolean: are we on IPv6? */
int AuthDirPublishIPv6; /**< Boolean: should we list IPv6 OR ports? */
/** If non-zero, always vote the Fast flag for any relay advertising
* this amount of capacity or more. */
+20
View File
@@ -2230,6 +2230,26 @@ router_get_pref_ipv6_orport(const routerinfo_t *router,
ap_out->port = router->ipv6_orport;
}
/** Return 1 if any of <b>router</b>'s addresses are <b>addr</b>.
* Otherwise return 0. */
int
router_has_addr(const routerinfo_t *router, const tor_addr_t *addr)
{
return
tor_addr_eq_ipv4h(addr, router->addr) ||
tor_addr_eq(&router->ipv6_addr, addr);
}
int
router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport)
{
return
(tor_addr_eq_ipv4h(&orport->addr, router->addr) &&
orport->port == router->or_port) ||
(tor_addr_eq(&orport->addr, &router->ipv6_addr) &&
orport->port == router->ipv6_orport);
}
/** Load the contents of <b>filename</b>, find the last line starting with
* <b>end_line</b>, ensure that its timestamp is not more than 25 hours in
* the past or more than 1 hour in the future with respect to <b>now</b>,
+2
View File
@@ -93,6 +93,8 @@ void router_get_pref_orport(const routerinfo_t *router,
void router_get_pref_ipv6_orport(const routerinfo_t *router,
tor_addr_port_t *addr_port_out);
int router_ipv6_preferred(const routerinfo_t *router);
int router_has_addr(const routerinfo_t *router, const tor_addr_t *addr);
int router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport);
int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo,
crypto_pk_t *ident_key);
int is_legal_nickname(const char *s);
+10 -10
View File
@@ -1343,9 +1343,11 @@ mark_all_trusteddirservers_up(void)
/** Return true iff r1 and r2 have the same address and OR port. */
int
routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2)
routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2)
{
return r1->addr == r2->addr && r1->or_port == r2->or_port;
return r1->addr == r2->addr && r1->or_port == r2->or_port &&
tor_addr_eq(&r1->ipv6_addr, &r2->ipv6_addr) &&
r1->ipv6_orport == r2->ipv6_orport;
}
/** Reset all internal variables used to count failed downloads of network
@@ -2875,7 +2877,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
&ri->cache_info);
smartlist_add(rl->routers, ri);
ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1;
nodelist_add_routerinfo(ri);
nodelist_set_routerinfo(ri, NULL);
router_dir_info_changed();
#ifdef DEBUG_ROUTERLIST
routerlist_assert_ok(rl);
@@ -3104,8 +3106,11 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri_old);
nodelist_remove_routerinfo(ri_old);
nodelist_add_routerinfo(ri_new);
{
routerinfo_t *ri_old_tmp=NULL;
nodelist_set_routerinfo(ri_new, &ri_old_tmp);
tor_assert(ri_old == ri_old_tmp);
}
router_dir_info_changed();
if (idx >= 0) {
@@ -3442,11 +3447,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* Same key, and either new, or listed in the consensus. */
log_debug(LD_DIR, "Replacing entry for router %s",
router_describe(router));
if (routers_have_same_or_addr(router, old_router)) {
/* these carry over when the address and orport are unchanged. */
router->last_reachable = old_router->last_reachable;
router->testing_since = old_router->testing_since;
}
routerlist_replace(routerlist, old_router, router);
if (!from_cache) {
signed_desc_append_to_journal(&router->cache_info,
+1 -1
View File
@@ -36,7 +36,7 @@ const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type,
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
const routerinfo_t *routerlist_find_my_routerinfo(void);
const node_t *router_find_exact_exit_enclave(const char *address,