aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-09-04 18:24:20 -0400
committerNick Mathewson <nickm@torproject.org>2012-09-04 18:24:20 -0400
commitd7a646edcfbceaab412bc1558ec83a3551c2c8a4 (patch)
treea0d5b084a6a2d2db7c77e18c94c1bc10c53c9a28 /src
parentec94d0307e06b9ea5732e86e369dcf5c727f05cb (diff)
parentd827a5495a9d05976f5610655f7e4b5b160a2dac (diff)
downloadtor-d7a646edcfbceaab412bc1558ec83a3551c2c8a4.tar.gz
tor-d7a646edcfbceaab412bc1558ec83a3551c2c8a4.zip
Merge branch 'bug5535_only_rebased'
Diffstat (limited to 'src')
-rw-r--r--src/or/circuitbuild.c72
-rw-r--r--src/or/config.c2
-rw-r--r--src/or/nodelist.c53
-rw-r--r--src/or/nodelist.h8
-rw-r--r--src/or/or.h11
-rw-r--r--src/or/routerparse.c9
6 files changed, 111 insertions, 44 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index ba617ffa45..2a449b0cc0 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -3792,12 +3792,10 @@ onion_extend_cpath(origin_circuit_t *circ)
} else if (cur_len == 0) { /* picking first node */
const node_t *r = choose_good_entry_server(purpose, state);
if (r) {
- /* If we're extending to a bridge, use the preferred address
- rather than the primary, for potentially extending to an IPv6
- bridge. */
- int use_pref_addr = (r->ri != NULL &&
- r->ri->purpose == ROUTER_PURPOSE_BRIDGE);
- info = extend_info_from_node(r, use_pref_addr);
+ /* If we're a client, use the preferred address rather than the
+ primary address, for potentially connecting to an IPv6 OR
+ port. */
+ info = extend_info_from_node(r, server_mode(get_options()) == 0);
tor_assert(info);
}
} else {
@@ -3865,34 +3863,43 @@ extend_info_alloc(const char *nickname, const char *digest,
/** Allocate and return a new extend_info that can be used to build a
* circuit to or through the node <b>node</b>. Use the primary address
- * of the node unless <b>for_direct_connect</b> is true, in which case
- * the preferred address is used instead. May return NULL if there is
- * not enough info about <b>node</b> to extend to it--for example, if
- * there is no routerinfo_t or microdesc_t.
+ * of the node (i.e. its IPv4 address) unless
+ * <b>for_direct_connect</b> is true, in which case the preferred
+ * address is used instead. May return NULL if there is not enough
+ * info about <b>node</b> to extend to it--for example, if there is no
+ * routerinfo_t or microdesc_t.
**/
extend_info_t *
extend_info_from_node(const node_t *node, int for_direct_connect)
{
- if (node->ri) {
- const routerinfo_t *r = node->ri;
- tor_addr_port_t ap;
- if (for_direct_connect)
- node_get_pref_orport(node, &ap);
- else
- node_get_prim_orport(node, &ap);
- return extend_info_alloc(r->nickname, r->cache_info.identity_digest,
- r->onion_pkey, &ap.addr, ap.port);
- } else if (node->rs && node->md) {
- tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, node->rs->addr);
+ tor_addr_port_t ap;
+
+ if (node->ri == NULL && (node->rs == NULL || node->md == NULL))
+ return NULL;
+
+ if (for_direct_connect)
+ node_get_pref_orport(node, &ap);
+ else
+ node_get_prim_orport(node, &ap);
+
+ log_debug(LD_CIRC, "using %s:%d for %s",
+ fmt_and_decorate_addr(&ap.addr), ap.port,
+ node->ri ? node->ri->nickname : node->rs->nickname);
+
+ if (node->ri)
+ return extend_info_alloc(node->ri->nickname,
+ node->identity,
+ node->ri->onion_pkey,
+ &ap.addr,
+ ap.port);
+ else if (node->rs && node->md)
return extend_info_alloc(node->rs->nickname,
node->identity,
node->md->onion_pkey,
- &addr,
- node->rs->or_port);
- } else {
+ &ap.addr,
+ ap.port);
+ else
return NULL;
- }
}
/** Release storage held by an extend_info_t struct. */
@@ -5607,10 +5614,15 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
}
}
- /* Indicate that we prefer connecting to this bridge over the
- protocol that the bridge address indicates. Last bridge
- descriptor handled wins. */
- node->ipv6_preferred = tor_addr_family(&bridge->addr) == AF_INET6;
+ /* Mark bridge as preferably connected to over IPv6 if its IPv6
+ address is in a Bridge line and ClientPreferIPv6ORPort is
+ set. Unless both is true, a potential IPv6 OR port of this
+ bridge won't get selected.
+
+ XXX ipv6_preferred is never reset (#6757) */
+ if (get_options()->ClientPreferIPv6ORPort == 1 &&
+ tor_addr_family(&bridge->addr) == AF_INET6)
+ node->ipv6_preferred = 1;
/* XXXipv6 we lack support for falling back to another address for
the same relay, warn the user */
diff --git a/src/or/config.c b/src/or/config.c
index a5a8fec507..f21016d48f 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -225,8 +225,10 @@ static config_var_t _option_vars[] = {
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
V(ClientOnly, BOOL, "0"),
+ V(ClientPreferIPv6ORPort, BOOL, "0"),
V(ClientRejectInternalAddresses, BOOL, "1"),
V(ClientTransportPlugin, LINELIST, NULL),
+ V(ClientUseIPv6, BOOL, "0"),
V(ConsensusParams, STRING, NULL),
V(ConnLimit, UINT, "1000"),
V(ConnDirectionStatistics, BOOL, "0"),
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 9d0247f4ea..e35039bdb8 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -206,6 +206,7 @@ nodelist_set_consensus(networkstatus_t *ns)
{
const or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
+ int client = !server_mode(options);
init_nodelist();
if (ns->flavor == FLAV_MICRODESC)
@@ -242,6 +243,11 @@ nodelist_set_consensus(networkstatus_t *ns)
node->is_bad_directory = rs->is_bad_directory;
node->is_bad_exit = rs->is_bad_exit;
node->is_hs_dir = rs->is_hs_dir;
+ node->ipv6_preferred = 0;
+ if (client && options->ClientPreferIPv6ORPort == 1 &&
+ (tor_addr_is_null(&rs->ipv6_addr) == 0 ||
+ (node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0)))
+ node->ipv6_preferred = 1;
}
} SMARTLIST_FOREACH_END(rs);
@@ -815,31 +821,44 @@ node_get_declared_family(const node_t *node)
int
node_ipv6_preferred(const node_t *node)
{
+ tor_addr_port_t ipv4_addr;
node_assert_ok(node);
- if (node->ri)
- return (!tor_addr_is_null(&node->ri->ipv6_addr)
- && (node->ipv6_preferred || node->ri->addr == 0));
- if (node->rs)
- return (!tor_addr_is_null(&node->rs->ipv6_addr)
- && (node->ipv6_preferred || node->rs->addr == 0));
+
+ if (node->ipv6_preferred || node_get_prim_orport(node, &ipv4_addr)) {
+ if (node->ri)
+ return !tor_addr_is_null(&node->ri->ipv6_addr);
+ if (node->md)
+ return !tor_addr_is_null(&node->md->ipv6_addr);
+ if (node->rs)
+ return !tor_addr_is_null(&node->rs->ipv6_addr);
+ }
return 0;
}
/** Copy the primary (IPv4) OR port (IP address and TCP port) for
- * <b>node</b> into *<b>ap_out</b>. */
-void
+ * <b>node</b> into *<b>ap_out</b>. Return 0 if a valid address and
+ * port was copied, else return non-zero.*/
+int
node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
{
node_assert_ok(node);
tor_assert(ap_out);
if (node->ri) {
+ if (node->ri->addr == 0 || node->ri->or_port == 0)
+ return -1;
tor_addr_from_ipv4h(&ap_out->addr, node->ri->addr);
ap_out->port = node->ri->or_port;
- } else if (node->rs) {
+ return 0;
+ }
+ if (node->rs) {
+ if (node->rs->addr == 0 || node->rs->or_port == 0)
+ return -1;
tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr);
ap_out->port = node->rs->or_port;
+ return 0;
}
+ return -1;
}
/** Copy the preferred OR port (IP address and TCP port) for
@@ -849,7 +868,13 @@ node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out)
{
tor_assert(ap_out);
- if (node_ipv6_preferred(node))
+ /* Cheap implementation of config option ClientUseIPv6 -- simply
+ don't prefer IPv6 when ClientUseIPv6 is not set. (See #4455 for
+ more on this subject.) Note that this filter is too strict since
+ we're hindering not only clients! Erring on the safe side
+ shouldn't be a problem though. XXX move this check to where
+ outgoing connections are made? -LN */
+ if (get_options()->ClientUseIPv6 == 1 && node_ipv6_preferred(node))
node_get_pref_ipv6_orport(node, ap_out);
else
node_get_prim_orport(node, ap_out);
@@ -863,9 +888,17 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
node_assert_ok(node);
tor_assert(ap_out);
+ /* We prefer the microdesc over a potential routerstatus here. They
+ are not being synchronised atm so there might be a chance that
+ they differ at some point, f.ex. when flipping
+ UseMicrodescriptors? -LN */
+
if (node->ri) {
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
ap_out->port = node->ri->ipv6_orport;
+ } else if (node->md) {
+ tor_addr_copy(&ap_out->addr, &node->md->ipv6_addr);
+ ap_out->port = node->md->ipv6_orport;
} else if (node->rs) {
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
ap_out->port = node->rs->ipv6_orport;
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 5558827961..fb65fa5483 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -42,18 +42,18 @@ int node_get_purpose(const node_t *node);
int node_is_me(const node_t *node);
int node_exit_policy_rejects_all(const node_t *node);
smartlist_t *node_get_all_orports(const node_t *node);
-void node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out);
-void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out);
-void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out);
-uint32_t node_get_prim_addr_ipv4h(const node_t *node);
int node_allows_single_hop_exits(const node_t *node);
const char *node_get_nickname(const node_t *node);
const char *node_get_platform(const node_t *node);
+uint32_t node_get_prim_addr_ipv4h(const node_t *node);
void node_get_address_string(const node_t *node, char *cp, size_t len);
long node_get_declared_uptime(const node_t *node);
time_t node_get_published_on(const node_t *node);
const smartlist_t *node_get_declared_family(const node_t *node);
int node_ipv6_preferred(const node_t *node);
+int node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out);
+void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out);
+void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out);
smartlist_t *nodelist_get_list(void);
diff --git a/src/or/or.h b/src/or/or.h
index 00a359c533..4bf99e2eaa 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1960,6 +1960,10 @@ typedef struct microdesc_t {
/** As routerinfo_t.onion_pkey */
crypto_pk_t *onion_pkey;
+ /** As routerinfo_t.ipv6_add */
+ tor_addr_t ipv6_addr;
+ /** As routerinfo_t.ipv6_orport */
+ uint16_t ipv6_orport;
/** As routerinfo_t.family */
smartlist_t *family;
/** Exit policy summary */
@@ -3487,6 +3491,13 @@ typedef struct {
* over randomly chosen exits. */
int ClientRejectInternalAddresses;
+ /** If true, clients may connect over IPv6. XXX we don't really
+ enforce this -- clients _may_ set up outgoing IPv6 connections
+ even when this option is not set. */
+ int ClientUseIPv6;
+ /** If true, prefer an IPv6 OR port over an IPv4 one. */
+ int ClientPreferIPv6ORPort;
+
/** The length of time that we think a consensus should be fresh. */
int V3AuthVotingInterval;
/** The length of time we think it will take to distribute votes. */
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index cda1c00664..7bee08434f 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -524,6 +524,7 @@ static token_rule_t networkstatus_detached_signature_token_table[] = {
/** List of tokens recognized in microdescriptors */
static token_rule_t microdesc_token_table[] = {
T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
+ T0N("a", K_A, GE(1), NO_OBJ ),
T01("family", K_FAMILY, ARGS, NO_OBJ ),
T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
@@ -4454,6 +4455,14 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->onion_pkey = tok->key;
tok->key = NULL;
+ {
+ smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
+ if (a_lines) {
+ find_single_ipv6_orport(a_lines, &md->ipv6_addr, &md->ipv6_orport);
+ smartlist_free(a_lines);
+ }
+ }
+
if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) {
int i;
md->family = smartlist_new();