[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Use fascist firewall and ClientUseIPv4 for bridge clients
commit 3b8216f2155f224bf66497c71de4cecb55cd83e6
Author: teor (Tim Wilson-Brown) <teor2345@xxxxxxxxx>
Date: Mon Jan 4 00:35:22 2016 +1100
Use fascist firewall and ClientUseIPv4 for bridge clients
Bridge clients ignore ClientUseIPv6, acting as if it is always 1.
This preserves existing behaviour.
Make ClientPreferIPv6OR/DirPort auto by default:
* Bridge clients prefer IPv6 by default.
* Other clients prefer IPv4 by default.
This preserves existing behaviour.
---
doc/tor.1.txt | 16 +--
src/or/config.c | 49 ++------
src/or/connection.c | 20 +--
src/or/directory.c | 12 +-
src/or/nodelist.c | 156 +++++++++---------------
src/or/nodelist.h | 5 +-
src/or/or.h | 10 +-
src/or/policies.c | 296 +++++++++++++++++++--------------------------
src/or/policies.h | 17 +--
src/or/routerlist.c | 8 +-
src/test/test_entrynodes.c | 45 ++++++-
src/test/test_policy.c | 154 +++++++++++++++++------
12 files changed, 403 insertions(+), 385 deletions(-)
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 26abef1..f201a61 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1500,19 +1500,21 @@ The following options are useful only for clients (that is, if
in a **Bridge**, proxy, or pluggable transport line will try connecting
over IPv6 even if **ClientUseIPv6** is set to 0. (Default: 0)
-[[ClientPreferIPv6DirPort]] **ClientPreferIPv6DirPort** **0**|**1**::
+[[ClientPreferIPv6DirPort]] **ClientPreferIPv6DirPort** **0**|**1**|**auto**::
If this option is set to 1, Tor prefers a directory port with an IPv6
address over one with IPv4, for direct connections, if a given directory
server has both. (Tor also prefers an IPv6 DirPort if IPv4Client is set to
- 0.) Other things may influence the choice. This option breaks a tie to the
- favor of IPv6. (Default: 0)
+ 0.) If this option is set to auto, Tor bridge clients prefer IPv6, and
+ other clients prefer IPv4. Other things may influence the choice. This
+ option breaks a tie to the favor of IPv6. (Default: auto)
-[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**::
+[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**|**auto**::
If this option is set to 1, Tor prefers an OR port with an IPv6
address over one with IPv4 if a given entry node has both. (Tor also
- prefers an IPv6 ORPort if IPv4Client is set to 0.) Other things may
- influence the choice. This option breaks a tie to the favor of IPv6.
- (Default: 0)
+ prefers an IPv6 ORPort if IPv4Client is set to 0.) If this option is set
+ to auto, Tor bridge clients prefer IPv6, and other clients prefer IPv4.
+ Other things may influence the choice. This option breaks a tie to the
+ favor of IPv6. (Default: auto)
[[PathsNeededToBuildCircuits]] **PathsNeededToBuildCircuits** __NUM__::
Tor clients don't build circuits for user traffic until they know
diff --git a/src/or/config.c b/src/or/config.c
index d676c6e..caa01d1 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -190,8 +190,8 @@ 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(ClientPreferIPv6DirPort, BOOL, "0"),
+ V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"),
+ V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"),
V(ClientRejectInternalAddresses, BOOL, "1"),
V(ClientTransportPlugin, LINELIST, NULL),
V(ClientUseIPv6, BOOL, "0"),
@@ -3073,9 +3073,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- /* Terminate Reachable*Addresses with reject *, but check if it has an
- * IPv6 entry on the way through */
- int reachable_knows_ipv6 = 0;
+ /* Terminate Reachable*Addresses with reject *
+ */
for (i=0; i<3; i++) {
config_line_t **linep =
(i==0) ? &options->ReachableAddresses :
@@ -3085,20 +3084,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
continue;
/* We need to end with a reject *:*, not an implicit accept *:* */
for (;;) {
- /* Check if the policy has an IPv6 entry, or uses IPv4-specific
- * policies (and therefore we assume it's aware of IPv6). */
- if (!strcmpstart((*linep)->value, "accept6") ||
- !strcmpstart((*linep)->value, "reject6") ||
- !strstr((*linep)->value, "*6") ||
- strchr((*linep)->value, '[') ||
- !strcmpstart((*linep)->value, "accept4") ||
- !strcmpstart((*linep)->value, "reject4") ||
- !strstr((*linep)->value, "*4"))
- reachable_knows_ipv6 = 1;
- /* already has a reject all */
- if (!strcmp((*linep)->value, "reject *:*") ||
- !strcmp((*linep)->value, "reject *"))
- break;
linep = &((*linep)->next);
if (!*linep) {
*linep = tor_malloc_zero(sizeof(config_line_t));
@@ -3112,18 +3097,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- if (options->ClientUseIPv6 &&
- (options->ReachableAddresses ||
- options->ReachableORAddresses ||
- options->ReachableDirAddresses) &&
- !reachable_knows_ipv6)
- log_warn(LD_CONFIG, "You have set ClientUseIPv6 1 and at least one of "
- "ReachableAddresses, ReachableORAddresses, or "
- "ReachableDirAddresses, but without any IPv6-specific rules. "
- "Tor won't connect to any IPv6 addresses, unless a rule accepts "
- "them. (Use 'accept6 *:*' or 'reject6 *:*' as the last rule to "
- "disable this warning.)");
-
if ((options->ReachableAddresses ||
options->ReachableORAddresses ||
options->ReachableDirAddresses ||
@@ -3135,18 +3108,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
/* We check if Reachable*Addresses blocks all addresses in
* parse_reachable_addresses(). */
- if (options->ClientUseIPv4 == 0 && options->ClientUseIPv6 == 0)
+ if (options->ClientUseIPv4 == 0 && !fascist_firewall_use_ipv6(options))
REJECT("Tor cannot connect to the Internet if ClientUseIPv4 is 0 and "
"ClientUseIPv6 is 0. Please set at least one of these options "
- "to 1.");
+ "to 1, or configure bridges.");
- if (options->ClientUseIPv6 == 0 && options->ClientPreferIPv6ORPort == 1)
+ if (!fascist_firewall_use_ipv6(options)
+ && options->ClientPreferIPv6ORPort == 1)
log_warn(LD_CONFIG, "ClientPreferIPv6ORPort 1 is ignored unless "
- "ClientUseIPv6 is also 1.");
+ "ClientUseIPv6 is also 1, or bridges are configured.");
- if (options->ClientUseIPv6 == 0 && options->ClientPreferIPv6DirPort == 1)
+ if (!fascist_firewall_use_ipv6(options)
+ && options->ClientPreferIPv6DirPort == 1)
log_warn(LD_CONFIG, "ClientPreferIPv6DirPort 1 is ignored unless "
- "ClientUseIPv6 is also 1.");
+ "ClientUseIPv6 is also 1, or bridges are configured.");
if (options->UseBridges &&
server_mode(options))
diff --git a/src/or/connection.c b/src/or/connection.c
index f252d2f..0420f26 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1722,7 +1722,7 @@ connection_connect_sockaddr,(connection_t *conn,
return inprogress ? 0 : 1;
}
-/* Log a message if connection violates ClientUseIPv4 0 or ClientUseIPv6 0.
+/* Log a message if connection attempt is made when IPv4 or IPv6 is disabled.
* Log a less severe message if we couldn't conform to ClientPreferIPv6ORPort
* or ClientPreferIPv6ORPort. */
static void
@@ -1730,9 +1730,9 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
{
const or_options_t *options = get_options();
- /* Only non-bridge clients care about ClientUseIPv4/6, bail out early on
- * servers and bridge clients */
- if (options->UseBridges || server_mode(options) || !conn
+ /* Only clients care about ClientUseIPv4/6, bail out early on servers, and
+ * on connections we don't care about */
+ if (server_mode(options) || !conn
|| conn->type == CONN_TYPE_EXIT) {
return;
}
@@ -1742,11 +1742,11 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
return;
}
- const int must_ipv4 = (options->ClientUseIPv6 == 0);
+ const int must_ipv4 = !fascist_firewall_use_ipv6(options);
const int must_ipv6 = (options->ClientUseIPv4 == 0);
const int pref_ipv6 = (conn->type == CONN_TYPE_OR
- ? nodelist_prefer_ipv6_orport(options)
- : nodelist_prefer_ipv6_dirport(options));
+ ? fascist_firewall_prefer_ipv6_orport(options)
+ : fascist_firewall_prefer_ipv6_dirport(options));
tor_addr_t real_addr;
tor_addr_make_null(&real_addr, AF_UNSPEC);
@@ -1773,12 +1773,14 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
if ((!pref_ipv6 && tor_addr_family(&real_addr) == AF_INET6)
|| (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
log_info(LD_NET, "Connection to %s doesn't satisfy ClientPreferIPv6%sPort "
- "%d, with ClientUseIPv4 %d and ClientUseIPv6 %d.",
+ "%d, with ClientUseIPv4 %d, and fascist_firewall_use_ipv6 %d "
+ "(ClientUseIPv6 %d and UseBridges %d).",
fmt_addr(&real_addr),
conn->type == CONN_TYPE_OR ? "OR" : "Dir",
conn->type == CONN_TYPE_OR ? options->ClientPreferIPv6ORPort
: options->ClientPreferIPv6DirPort,
- options->ClientUseIPv4, options->ClientUseIPv4);
+ options->ClientUseIPv4, fascist_firewall_use_ipv6(options),
+ options->ClientUseIPv6, options->UseBridges);
}
}
diff --git a/src/or/directory.c b/src/or/directory.c
index 665ba27..b3a2f36 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -730,7 +730,8 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
* directory server, we have selected a server that has at least one address
* allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
* selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
- * possible. (If UseBridges is set, clients ignore all these settings.)
+ * possible. (If UseBridges is set, clients always use IPv6, and prefer it
+ * by default.)
*
* Now choose an address that we can use to connect to the directory server.
*/
@@ -1070,6 +1071,15 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
anonymized_connection, use_begindir);
+ if (!dir_port && !use_begindir) {
+ char ipaddr[TOR_ADDR_BUF_LEN];
+ tor_addr_to_str(ipaddr, &addr, TOR_ADDR_BUF_LEN, 0);
+ log_warn(LD_BUG, "Cannot use directory server without dirport or "
+ "begindir! Address: %s, DirPort: %d, Connection Port: %d",
+ escaped_safe_str_client(ipaddr), dir_port, port);
+ return;
+ }
+
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
#ifndef NON_ANONYMOUS_MODE_ENABLED
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 7ca1146..c8f93bf 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -214,76 +214,6 @@ nodelist_add_microdesc(microdesc_t *md)
return node;
}
-/** Do we prefer to connect to IPv6, ignoring ClientPreferIPv6ORPort and
- * ClientPreferIPv6DirPort?
- * If we're unsure, return -1, otherwise, return 1 for IPv6 and 0 for IPv4.
- */
-static int
-nodelist_prefer_ipv6(const or_options_t *options)
-{
- /*
- Cheap implementation of config options ClientUseIPv4 & ClientUseIPv6 --
- If we're a server, use IPv4.
- If we're a client running with bridges, use IPv6.
- Otherwise, use IPv6 if we can and it's preferred, or if IPv4 is disabled.
- See #4455 and #17840 for more on this subject.
- */
-
- /* Servers prefer IPv4 */
- if (server_mode(options)) {
- return 0;
- }
-
- /* Bridge clients prefer IPv6 */
- if (options->UseBridges) {
- return 1;
- }
-
- if (!options->ClientUseIPv4) {
- return 1;
- }
-
- return -1;
-}
-
-/** Do we prefer to connect to IPv6 ORPorts?
- */
-int
-nodelist_prefer_ipv6_orport(const or_options_t *options)
-{
- int pref_ipv6 = nodelist_prefer_ipv6(options);
-
- if (pref_ipv6 >= 0) {
- return pref_ipv6;
- }
-
- /* We prefer IPv6 ORPorts if the option is set */
- if (options->ClientUseIPv6 && options->ClientPreferIPv6ORPort) {
- return 1;
- }
-
- return 0;
-}
-
-/** Do we prefer to connect to IPv6 DirPorts?
- */
-int
-nodelist_prefer_ipv6_dirport(const or_options_t *options)
-{
- int pref_ipv6 = nodelist_prefer_ipv6(options);
-
- if (pref_ipv6 >= 0) {
- return pref_ipv6;
- }
-
- /* We prefer IPv6 DirPorts if the option is set */
- if (options->ClientUseIPv6 && options->ClientPreferIPv6DirPort) {
- return 1;
- }
-
- return 0;
-}
-
/** Tell the nodelist that the current usable consensus is <b>ns</b>.
* This makes the nodelist change all of the routerstatus entries for
* the nodes, drop nodes that no longer have enough info to get used,
@@ -330,7 +260,7 @@ nodelist_set_consensus(networkstatus_t *ns)
node->is_bad_exit = rs->is_bad_exit;
node->is_hs_dir = rs->is_hs_dir;
node->ipv6_preferred = 0;
- if (nodelist_prefer_ipv6_orport(options) &&
+ if (fascist_firewall_prefer_ipv6_orport(options) &&
(tor_addr_is_null(&rs->ipv6_addr) == 0 ||
(node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0)))
node->ipv6_preferred = 1;
@@ -916,9 +846,13 @@ node_get_addr(const node_t *node, tor_addr_t *addr_out)
uint32_t
node_get_prim_addr_ipv4h(const node_t *node)
{
- if (node->ri) {
+ /* Don't check the ORPort or DirPort, as this function isn't port-specific,
+ * and the node might have a valid IPv4 address, yet have a zero
+ * ORPort or DirPort.
+ */
+ if (node->ri && tor_addr_is_valid_ipv4h(node->ri->addr, 0)) {
return node->ri->addr;
- } else if (node->rs) {
+ } else if (node->rs && tor_addr_is_valid_ipv4h(node->rs->addr, 0)) {
return node->rs->addr;
}
return 0;
@@ -994,20 +928,44 @@ node_get_declared_family(const node_t *node)
return NULL;
}
-/* Does this node have a valid IPv6 address? */
-static int
+/* Does this node have a valid IPv6 address?
+ * Prefer node_has_ipv6_orport() or node_has_ipv6_dirport() for
+ * checking specific ports. */
+int
node_has_ipv6_addr(const node_t *node)
{
- 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);
+ /* Don't check the ORPort or DirPort, as this function isn't port-specific,
+ * and the node might have a valid IPv6 address, yet have a zero
+ * ORPort or DirPort.
+ */
+ if (node->ri && tor_addr_is_valid(&node->ri->ipv6_addr, 0))
+ return 1;
+ if (node->rs && tor_addr_is_valid(&node->rs->ipv6_addr, 0))
+ return 1;
+ if (node->md && tor_addr_is_valid(&node->md->ipv6_addr, 0))
+ return 1;
return 0;
}
+/* Does this node have a valid IPv6 ORPort? */
+int
+node_has_ipv6_orport(const node_t *node)
+{
+ tor_addr_port_t ipv6_orport;
+ node_get_pref_ipv6_orport(node, &ipv6_orport);
+ return tor_addr_port_is_valid_ap(&ipv6_orport, 0);
+}
+
+/* Does this node have a valid IPv6 DirPort? */
+int
+node_has_ipv6_dirport(const node_t *node)
+{
+ tor_addr_port_t ipv6_dirport;
+ node_get_pref_ipv6_dirport(node, &ipv6_dirport);
+ return tor_addr_port_is_valid_ap(&ipv6_dirport, 0);
+}
+
/** Return 1 if we prefer the IPv6 address and OR TCP port of
* <b>node</b>, else 0.
*
@@ -1028,20 +986,18 @@ node_ipv6_or_preferred(const node_t *node)
tor_addr_port_t ipv4_addr;
node_assert_ok(node);
- if (!options->ClientUseIPv6) {
+ if (!fascist_firewall_use_ipv6(options)) {
return 0;
} else if (node->ipv6_preferred || node_get_prim_orport(node, &ipv4_addr)
- || nodelist_prefer_ipv6_orport(get_options())) {
- return node_has_ipv6_addr(node);
+ || fascist_firewall_prefer_ipv6_orport(get_options())) {
+ return node_has_ipv6_orport(node);
}
return 0;
}
#define RETURN_IPV4_AP(r, port_field, ap_out) \
STMT_BEGIN \
- if (r) { \
- if ((r)->addr == 0 || (r)->port_field == 0) \
- return -1; \
+ if (r && tor_addr_port_is_valid_ipv4h((r)->addr, (r)->port_field, 0)) { \
tor_addr_from_ipv4h(&(ap_out)->addr, (r)->addr); \
(ap_out)->port = (r)->port_field; \
return 0; \
@@ -1091,16 +1047,16 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
* fascist_firewall_* functions. Also check if the address or port are valid,
* and try another alternative if they are not. */
- if (node->ri && node->ri->ipv6_orport
- && !tor_addr_is_null(&node->ri->ipv6_addr)) {
+ if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
+ node->ri->ipv6_orport, 0)) {
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
ap_out->port = node->ri->ipv6_orport;
- } else if (node->rs && node->rs->ipv6_orport
- && !tor_addr_is_null(&node->rs->ipv6_addr)) {
+ } else if (node->rs && tor_addr_port_is_valid(&node->rs->ipv6_addr,
+ node->rs->ipv6_orport, 0)) {
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
ap_out->port = node->rs->ipv6_orport;
- } else if (node->md && node->md->ipv6_orport
- && !tor_addr_is_null(&node->md->ipv6_addr)) {
+ } else if (node->md && tor_addr_port_is_valid(&node->md->ipv6_addr,
+ node->md->ipv6_orport, 0)) {
tor_addr_copy(&ap_out->addr, &node->md->ipv6_addr);
ap_out->port = node->md->ipv6_orport;
} else {
@@ -1129,11 +1085,11 @@ node_ipv6_dir_preferred(const node_t *node)
tor_addr_port_t ipv4_addr;
node_assert_ok(node);
- if (!options->ClientUseIPv6) {
+ if (!fascist_firewall_use_ipv6(options)) {
return 0;
} else if (node->ipv6_preferred || node_get_prim_dirport(node, &ipv4_addr)
- || nodelist_prefer_ipv6_dirport(get_options())) {
- return node_has_ipv6_addr(node);
+ || fascist_firewall_prefer_ipv6_dirport(get_options())) {
+ return node_has_ipv6_dirport(node);
}
return 0;
}
@@ -1183,12 +1139,12 @@ node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out)
* they are not. Note that microdescriptors have no dir_port. */
/* Assume IPv4 and IPv6 dirports are the same */
- if (node->ri && node->ri->dir_port
- && !tor_addr_is_null(&node->ri->ipv6_addr)) {
+ if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
+ node->ri->dir_port, 0)) {
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
ap_out->port = node->ri->dir_port;
- } else if (node->rs && node->rs->dir_port
- && !tor_addr_is_null(&node->rs->ipv6_addr)) {
+ } else if (node->rs && tor_addr_port_is_valid(&node->rs->ipv6_addr,
+ node->rs->dir_port, 0)) {
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
ap_out->port = node->rs->dir_port;
} else {
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index fa1f22e..8271e75 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -21,8 +21,6 @@ MOCK_DECL(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_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
node_t *nodelist_add_microdesc(microdesc_t *md);
-int nodelist_prefer_ipv6_orport(const or_options_t *options);
-int nodelist_prefer_ipv6_dirport(const or_options_t *options);
void nodelist_set_consensus(networkstatus_t *ns);
void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
@@ -58,6 +56,9 @@ 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_has_ipv6_addr(const node_t *node);
+int node_has_ipv6_orport(const node_t *node);
+int node_has_ipv6_dirport(const node_t *node);
/* Deprecated - use node_ipv6_or_preferred or node_ipv6_dir_preferred */
#define node_ipv6_preferred(node) node_ipv6_or_preferred(node)
int node_ipv6_or_preferred(const node_t *node);
diff --git a/src/or/or.h b/src/or/or.h
index 412789c..79b1c95 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -4066,14 +4066,18 @@ typedef struct {
* connecting over IPv4. We enforce this for OR and Dir connections. */
int ClientUseIPv4;
/** If true, clients may connect over IPv6. If false, they will avoid
- * connecting over IPv4. We enforce this for OR and Dir connections. */
+ * connecting over IPv4. We enforce this for OR and Dir connections.
+ * Use fascist_firewall_use_ipv6() instead of accessing this value
+ * directly. */
int ClientUseIPv6;
/** If true, prefer an IPv6 OR port over an IPv4 one for entry node
- * connections. Use nodelist_prefer_ipv6_orport() instead of accessing
+ * connections. If auto, bridge clients prefer IPv6, and other clients
+ * prefer IPv4. Use fascist_firewall_prefer_ipv6_orport() instead of accessing
* this value directly. */
int ClientPreferIPv6ORPort;
/** If true, prefer an IPv6 directory port over an IPv4 one for direct
- * directory connections. Use nodelist_prefer_ipv6_dirport() instead of
+ * directory connections. If auto, bridge clients prefer IPv6, and other
+ * clients prefer IPv4. Use fascist_firewall_prefer_ipv6_dirport() instead of
* accessing this value directly. */
int ClientPreferIPv6DirPort;
diff --git a/src/or/policies.c b/src/or/policies.c
index 2a97df7..ecc89da 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -272,8 +272,8 @@ parse_reachable_addresses(void)
ret = -1;
}
- /* XX/teor - we ignore ReachableAddresses for bridge clients and relays */
- if (!options->UseBridges || server_mode(options)) {
+ /* We ignore ReachableAddresses for relays */
+ if (!server_mode(options)) {
if ((reachable_or_addr_policy
&& policy_is_reject_star(reachable_or_addr_policy, AF_UNSPEC))
|| (reachable_dir_addr_policy
@@ -282,12 +282,45 @@ parse_reachable_addresses(void)
"ReachableAddresses, ReachableORAddresses, or "
"ReachableDirAddresses reject all addresses. Please accept "
"some addresses in these options.");
+ } else if (options->ClientUseIPv4 == 1
+ && ((reachable_or_addr_policy
+ && policy_is_reject_star(reachable_or_addr_policy, AF_INET))
+ || (reachable_dir_addr_policy
+ && policy_is_reject_star(reachable_dir_addr_policy, AF_INET)))) {
+ log_warn(LD_CONFIG, "You have set ClientUseIPv4 1, but "
+ "ReachableAddresses, ReachableORAddresses, or "
+ "ReachableDirAddresses reject all IPv4 addresses. "
+ "Tor will not connect using IPv4.");
+ } else if (fascist_firewall_use_ipv6(options)
+ && ((reachable_or_addr_policy
+ && policy_is_reject_star(reachable_or_addr_policy, AF_INET6))
+ || (reachable_dir_addr_policy
+ && policy_is_reject_star(reachable_dir_addr_policy, AF_INET6)))) {
+ log_warn(LD_CONFIG, "You have configured tor to use IPv6 "
+ "(ClientUseIPv6 1 or UseBridges 1), but "
+ "ReachableAddresses, ReachableORAddresses, or "
+ "ReachableDirAddresses reject all IPv6 addresses. "
+ "Tor will not connect using IPv6.");
}
}
return ret;
}
+/** Return true iff the firewall options, including ClientUseIPv4 0 and
+ * ClientUseIPv6 0, might block any address:port combination.
+ */
+int
+firewall_is_fascist_or(void)
+{
+ const or_options_t *options = get_options();
+ /* Assume every non-bridge relay has an IPv4 address.
+ * Clients which use bridges may only know the IPv6 address of their
+ * bridge. */
+ return (reachable_or_addr_policy != NULL || options->ClientUseIPv4 == 0
+ || (options->ClientUseIPv6 == 0 && options->UseBridges == 1));
+}
+
/** Return true iff <b>policy</b> (possibly NULL) will allow a
* connection to <b>addr</b>:<b>port</b>.
*/
@@ -326,14 +359,14 @@ addr_policy_permits_address(uint32_t addr, uint16_t port,
/** Return true iff we think our firewall will let us make a connection to
* addr:port.
*
- * If UseBridges is set, or we are configured as a server, ignore the
- * following address family preferences.
+ * If we are configured as a server, ignore any address family preference and
+ * just use IPv4.
* Otherwise:
* - return false for all IPv4 addresses:
* - if ClientUseIPv4 is 0, or
* if pref_only and pref_ipv6 are both true;
* - return false for all IPv6 addresses:
- * - if ClientUseIPv6 is 0, or
+ * - if fascist_firewall_use_ipv6() is 0, or
* - if pref_only is true and pref_ipv6 is false.
*
* Return false if addr is NULL or tor_addr_is_null(), or if port is 0. */
@@ -349,13 +382,14 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
return 0;
}
- if (!options->UseBridges && !server_mode(options)) {
+ if (!server_mode(options)) {
if (tor_addr_family(addr) == AF_INET &&
(!options->ClientUseIPv4 || (pref_only && pref_ipv6)))
return 0;
+ /* Bridges can always use IPv6 */
if (tor_addr_family(addr) == AF_INET6 &&
- (!options->ClientUseIPv6 || (pref_only && !pref_ipv6)))
+ (!fascist_firewall_use_ipv6(options) || (pref_only && !pref_ipv6)))
return 0;
}
@@ -363,6 +397,87 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
firewall_policy);
}
+/** Is this client configured to use IPv6?
+ * Clients use IPv6 if ClientUseIPv6 is 1, or UseBridges is 1.
+ */
+int fascist_firewall_use_ipv6(const or_options_t *options)
+{
+ return (options->ClientUseIPv6 == 1 || options->UseBridges == 1);
+}
+
+/** Do we prefer to connect to IPv6, ignoring ClientPreferIPv6ORPort and
+ * ClientPreferIPv6DirPort?
+ * If we're unsure, return -1, otherwise, return 1 for IPv6 and 0 for IPv4.
+ */
+static int
+fascist_firewall_prefer_ipv6_impl(const or_options_t *options)
+{
+ /*
+ Cheap implementation of config options ClientUseIPv4 & ClientUseIPv6 --
+ If we're a server or IPv6 is disabled, use IPv4.
+ If IPv4 is disabled, use IPv6.
+ */
+
+ if (server_mode(options) || !fascist_firewall_use_ipv6(options)) {
+ return 0;
+ }
+
+ if (!options->ClientUseIPv4) {
+ return 1;
+ }
+
+ return -1;
+}
+
+/** Do we prefer to connect to IPv6 ORPorts?
+ */
+int
+fascist_firewall_prefer_ipv6_orport(const or_options_t *options)
+{
+ int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
+
+ if (pref_ipv6 >= 0) {
+ return pref_ipv6;
+ }
+
+ /* We can use both IPv4 and IPv6 - which do we prefer? */
+ if (options->ClientPreferIPv6ORPort == 1) {
+ return 1;
+ }
+
+ /* For bridge clients, ClientPreferIPv6ORPort auto means "prefer IPv6". */
+ if (options->UseBridges && options->ClientPreferIPv6ORPort != 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/** Do we prefer to connect to IPv6 DirPorts?
+ */
+int
+fascist_firewall_prefer_ipv6_dirport(const or_options_t *options)
+{
+ int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
+
+ if (pref_ipv6 >= 0) {
+ return pref_ipv6;
+ }
+
+ /* We can use both IPv4 and IPv6 - which do we prefer? */
+ if (options->ClientPreferIPv6DirPort == 1) {
+ return 1;
+ }
+
+ /* For bridge clients, ClientPreferIPv6ORPort auto means "prefer IPv6".
+ * XX/teor - do bridge clients ever use a DirPort? */
+ if (options->UseBridges && options->ClientPreferIPv6DirPort != 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
/** Return true iff we think our firewall will let us make a connection to
* addr:port. Uses ReachableORAddresses or ReachableDirAddresses based on
* fw_connection.
@@ -380,12 +495,12 @@ fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
return fascist_firewall_allows_address(addr, port,
reachable_or_addr_policy,
pref_only,
- nodelist_prefer_ipv6_orport(options));
+ fascist_firewall_prefer_ipv6_orport(options));
} else if (fw_connection == FIREWALL_DIR_CONNECTION) {
return fascist_firewall_allows_address(addr, port,
reachable_dir_addr_policy,
pref_only,
- nodelist_prefer_ipv6_dirport(options));
+ fascist_firewall_prefer_ipv6_dirport(options));
} else {
log_warn(LD_BUG, "Bad firewall_connection_t value %d.",
fw_connection);
@@ -478,30 +593,6 @@ fascist_firewall_allows_ri_impl(const routerinfo_t *ri,
ri->dir_port, fw_connection, pref_only);
}
-/** Return true iff we think our firewall will let us make a connection to
- * <b>ri</b> on either its IPv4 or IPv6 address. Uses
- * or_port/ipv6_orport/ReachableORAddresses or dir_port/ReachableDirAddresses
- * based on IPv4/IPv6 and <b>fw_connection</b>.
- * If pref_only, return false if addr is not in the client's preferred address
- * family.
- * Consults the corresponding node if the addresses in ri are not permitted. */
-int
-fascist_firewall_allows_ri(const routerinfo_t *ri,
- firewall_connection_t fw_connection, int pref_only)
-{
- if (!ri) {
- return 0;
- }
-
- /* Assume IPv4 and IPv6 DirPorts are the same */
- if (fascist_firewall_allows_ri_impl(ri, fw_connection, pref_only)) {
- return 1;
- } else {
- const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
- return fascist_firewall_allows_node(node, fw_connection, pref_only);
- }
-}
-
/** Like fascist_firewall_allows_rs, but doesn't consult the node. */
static int
fascist_firewall_allows_rs_impl(const routerstatus_t *rs,
@@ -563,40 +654,6 @@ fascist_firewall_allows_md_impl(const microdesc_t *md,
}
/** Return true iff we think our firewall will let us make a connection to
- * <b>md</b> on its IPv6 address. (The IPv4 address is in the routerstatus and
- * the routerinfo.) Uses ipv6_orport/ReachableORAddresses or
- * dir_port/ReachableDirAddresses based on <b>fw_connection</b>.
- * If pref_only, return false if addr is not in the client's preferred address
- * family.
- * Consults the corresponding node if the address in md is not permitted. */
-int
-fascist_firewall_allows_md(const microdesc_t *md,
- firewall_connection_t fw_connection,
- int pref_only)
-{
- if (!md) {
- return 0;
- }
-
- if (fascist_firewall_allows_md_impl(md, fw_connection, pref_only)) {
- return 1;
- } else {
- networkstatus_t *ns;
- ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
- if (!ns) {
- return 0;
- }
- const routerstatus_t *rs;
- rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
- if (!rs) {
- return 0;
- }
- const node_t *node = node_get_by_id(rs->identity_digest);
- return fascist_firewall_allows_node(node, fw_connection, pref_only);
- }
-}
-
-/** Return true iff we think our firewall will let us make a connection to
* <b>node</b>:
* - if <b>preferred</b> is true, on its preferred address,
* - if not, on either its IPv4 or IPv6 address.
@@ -816,44 +873,6 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
} \
STMT_END
-/** Copy an address and port from <b>ri</b> into <b>ap</b> that we think our
- * firewall will let us connect to. Uses ipv4h_addr/ipv6_addr and
- * ipv4_orport/ipv6_orport/ReachableORAddresses or
- * ipv4_dirport/ipv6_dirport/ReachableDirAddresses based on IPv4/IPv6 and
- * <b>fw_connection</b>.
- * If pref_only, only choose preferred addresses. In either case, choose
- * a preferred address before an address that's not preferred.
- * If neither address is chosen, return 0, else return 1.
- * Consults the corresponding node if the addresses in ri are not valid. */
-int
-fascist_firewall_choose_address_ri(const routerinfo_t *ri,
- firewall_connection_t fw_connection,
- int pref_only, tor_addr_port_t* ap)
-{
- if (!ri) {
- return 0;
- }
-
- tor_assert(ap);
-
- /* Don't do the lookup if the IPv6 address/port in ri is OK.
- * If it's OK, assume the dir_port is also OK. */
- tor_addr_port_t ipv6_or_ap;
- IPV6_OR_LOOKUP(ri, ri->cache_info.identity_digest, ipv6_or_ap);
-
- /* Assume IPv4 and IPv6 DirPorts are the same.
- * Assume the IPv6 OR and Dir addresses are the same. */
- return fascist_firewall_choose_address_ipv4h(ri->addr,
- ri->or_port,
- ri->dir_port,
- &ipv6_or_ap.addr,
- ipv6_or_ap.port,
- ri->dir_port,
- fw_connection,
- pref_only,
- ap);
-}
-
/** Copy an address and port from <b>rs</b> into <b>ap</b> that we think our
* firewall will let us connect to. Uses ipv4h_addr/ipv6_addr and
* ipv4_orport/ipv6_orport/ReachableORAddresses or
@@ -892,73 +911,6 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
ap);
}
-/* Copy the IPv6 address and ORPort from <b>md</b> into <b>ap</b> if we think
- * our firewall will let us connect to it. Uses ReachableORAddresses.
- * If pref_only, only copy if it's a preferred address.
- * If <b>fw_connection</b> is FIREWALL_DIR_CONNECTION, don't copy the address.
- * If the address isn't copied, return 0, else return 1. */
-static int
-fascist_firewall_choose_address_md_impl(const microdesc_t *md,
- firewall_connection_t fw_connection,
- int pref_only, tor_addr_port_t* ap)
-{
- if (!md) {
- return 0;
- }
-
- /* Can't check dirport, it doesn't have one */
- if (fw_connection == FIREWALL_DIR_CONNECTION) {
- return 0;
- }
-
- tor_assert(ap);
-
- if (fascist_firewall_allows_md(md, fw_connection, pref_only)) {
- tor_addr_copy(&ap->addr, &md->ipv6_addr);
- ap->port = md->ipv6_orport;
- return 1;
- } else {
- return 0;
- }
-}
-
-/** Lookup the node for md, and call fascist_firewall_choose_address_node on
- * it. If any step in this process fails, fall back to calling
- * fascist_firewall_choose_address_md_impl. */
-int
-fascist_firewall_choose_address_md(const microdesc_t *md,
- firewall_connection_t fw_connection,
- int pref_only, tor_addr_port_t* ap)
-{
- if (!md) {
- return 0;
- }
-
- tor_assert(ap);
-
- /* If we can't get the node, */
- networkstatus_t *ns;
- ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
- if (!ns) {
- return fascist_firewall_choose_address_md_impl(md, fw_connection,
- pref_only, ap);
- }
- const routerstatus_t *rs;
- rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
- if (!rs) {
- return fascist_firewall_choose_address_md_impl(md, fw_connection,
- pref_only, ap);
- }
- const node_t *node = node_get_by_id(rs->identity_digest);
- if (node) {
- return fascist_firewall_choose_address_node(node, fw_connection,
- pref_only, ap);
- } else {
- return fascist_firewall_choose_address_md_impl(md, fw_connection,
- pref_only, ap);
- }
-}
-
/** Copy an address and port from <b>node</b> into <b>ap</b> that we think our
* firewall will let us connect to. Uses ipv4h_addr/ipv6_addr and
* ipv4_orport/ipv6_orport/ReachableORAddresses or
diff --git a/src/or/policies.h b/src/or/policies.h
index 7309bcf..ac4f7ea 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -29,6 +29,11 @@ typedef enum firewall_connection_t {
typedef int exit_policy_parser_cfg_t;
+int firewall_is_fascist_or(void);
+int fascist_firewall_use_ipv6(const or_options_t *options);
+int fascist_firewall_prefer_ipv6_orport(const or_options_t *options);
+int fascist_firewall_prefer_ipv6_dirport(const or_options_t *options);
+
int fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
firewall_connection_t fw_connection,
int pref_only);
@@ -39,15 +44,9 @@ int fascist_firewall_allows_address_ipv4h(uint32_t ipv4h_or_addr,
uint16_t ipv4_or_port,
firewall_connection_t fw_connection,
int pref_only);
-int fascist_firewall_allows_ri(const routerinfo_t *ri,
- firewall_connection_t fw_connection,
- int pref_only);
int fascist_firewall_allows_rs(const routerstatus_t *rs,
firewall_connection_t fw_connection,
int pref_only);
-int fascist_firewall_allows_md(const microdesc_t *md,
- firewall_connection_t fw_connection,
- int pref_only);
int fascist_firewall_allows_node(const node_t *node,
firewall_connection_t fw_connection,
int pref_only);
@@ -61,15 +60,9 @@ const tor_addr_port_t * fascist_firewall_choose_address(
int want_a,
firewall_connection_t fw_connection,
int pref_only);
-int fascist_firewall_choose_address_ri(const routerinfo_t *ri,
- firewall_connection_t fw_connection,
- int pref_only, tor_addr_port_t* ap);
int fascist_firewall_choose_address_rs(const routerstatus_t *rs,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t* ap);
-int fascist_firewall_choose_address_md(const microdesc_t *md,
- firewall_connection_t fw_connection,
- int pref_only, tor_addr_port_t* ap);
int fascist_firewall_choose_address_node(const node_t *node,
firewall_connection_t fw_connection,
int pref_only, tor_addr_port_t* ap);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 2923da3..247818d 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -1594,8 +1594,8 @@ router_picked_poor_directory_log(const routerstatus_t *rs)
#define RETRY_ALTERNATE_IP_VERSION(retry_label) \
STMT_BEGIN \
if (result == NULL && try_ip_pref && options->ClientUseIPv4 \
- && options->ClientUseIPv6 && !server_mode(options) && n_not_preferred \
- && !n_busy) { \
+ && fascist_firewall_use_ipv6(options) && !server_mode(options) \
+ && n_not_preferred && !n_busy) { \
n_excluded = 0; \
n_busy = 0; \
try_ip_pref = 0; \
@@ -1976,7 +1976,7 @@ router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
continue;
if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
continue;
- /* Choose a node with a preferred OR address */
+ /* Choose a node with an OR address that matches the firewall rules */
if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, pref_addr))
continue;
@@ -2443,7 +2443,7 @@ node_sl_choose_by_bandwidth(const smartlist_t *sl,
* If <b>CRN_PREF_ADDR</b> is set in flags, we only consider nodes that
* have an address that is preferred by the ClientPreferIPv6ORPort setting
* (regardless of this flag, we exclude nodes that aren't allowed by the
- * firewall, including ClientUseIPv4 0 and ClientUseIPv6 0).
+ * firewall, including ClientUseIPv4 0 and fascist_firewall_use_ipv6() == 0).
*/
const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index e4947e0..a0208b9 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -107,6 +107,11 @@ test_choose_random_entry_no_guards(void *arg)
chosen_entry = choose_random_entry(NULL);
tt_assert(chosen_entry);
+ /* And with the preference on auto */
+ mocked_options.ClientPreferIPv6ORPort = -1;
+ chosen_entry = choose_random_entry(NULL);
+ tt_assert(chosen_entry);
+
/* Check that we don't get a guard if it doesn't pass mandatory address
* settings */
memset(&mocked_options, 0, sizeof(mocked_options));
@@ -128,6 +133,21 @@ test_choose_random_entry_no_guards(void *arg)
chosen_entry = choose_random_entry(NULL);
tt_assert(chosen_entry);
+ /* Check that we get a guard if it passes preferred address settings when
+ * they're auto */
+ memset(&mocked_options, 0, sizeof(mocked_options));
+ mocked_options.ClientUseIPv4 = 1;
+ mocked_options.ClientPreferIPv6ORPort = -1;
+
+ chosen_entry = choose_random_entry(NULL);
+ tt_assert(chosen_entry);
+
+ /* And with IPv6 active */
+ mocked_options.ClientUseIPv6 = 1;
+
+ chosen_entry = choose_random_entry(NULL);
+ tt_assert(chosen_entry);
+
done:
memset(&mocked_options, 0, sizeof(mocked_options));
UNMOCK(get_options);
@@ -166,6 +186,11 @@ test_choose_random_entry_one_possible_guard(void *arg)
chosen_entry = choose_random_entry(NULL);
tt_ptr_op(chosen_entry, OP_EQ, the_guard);
+ /* And with the preference on auto */
+ mocked_options.ClientPreferIPv6ORPort = -1;
+ chosen_entry = choose_random_entry(NULL);
+ tt_ptr_op(chosen_entry, OP_EQ, the_guard);
+
/* Check that we don't get a guard if it doesn't pass mandatory address
* settings */
memset(&mocked_options, 0, sizeof(mocked_options));
@@ -190,6 +215,21 @@ test_choose_random_entry_one_possible_guard(void *arg)
* time, so we can't be sure we get the guard */
tt_assert(chosen_entry);
+ /* Check that we get the guard if it passes preferred address settings when
+ * they're auto */
+ memset(&mocked_options, 0, sizeof(mocked_options));
+ mocked_options.ClientUseIPv4 = 1;
+ mocked_options.ClientPreferIPv6ORPort = -1;
+
+ chosen_entry = choose_random_entry(NULL);
+ tt_ptr_op(chosen_entry, OP_EQ, the_guard);
+
+ /* and with IPv6 active */
+ mocked_options.ClientUseIPv6 = 1;
+
+ chosen_entry = choose_random_entry(NULL);
+ tt_ptr_op(chosen_entry, OP_EQ, the_guard);
+
done:
memset(&mocked_options, 0, sizeof(mocked_options));
UNMOCK(get_options);
@@ -722,8 +762,9 @@ test_node_preferred_orport(void *arg)
/* Setup options */
memset(&mocked_options, 0, sizeof(mocked_options));
- /* We don't test ClientPreferIPv6ORPort here, because it's only used in
- * nodelist_set_consensus to setup each node_t. */
+ /* We don't test ClientPreferIPv6ORPort here, because it's used in
+ * nodelist_set_consensus to setup node.ipv6_preferred, which we set
+ * directly. */
MOCK(get_options, mock_get_options);
/* Setup IP addresses */
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 077d1b2..1daa38e 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -1235,8 +1235,8 @@ test_policies_fascist_firewall_allows_address(void *arg)
/* Test the function's address matching with UseBridges on */
memset(&mock_options, 0, sizeof(or_options_t));
- mock_options.ClientUseIPv4 = 0;
- mock_options.ClientUseIPv6 = 0;
+ mock_options.ClientUseIPv4 = 1;
+ mock_options.ClientUseIPv6 = 1;
mock_options.UseBridges = 1;
tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0)
@@ -1248,6 +1248,38 @@ test_policies_fascist_firewall_allows_address(void *arg)
tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0)
== 0);
+ /* Preferring IPv4 */
+ tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0)
+ == 1);
+ tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0)
+ == 0);
+ tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0)
+ == 0);
+ tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0)
+ == 0);
+
+ /* Preferring IPv6 */
+ tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1)
+ == 0);
+ tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1)
+ == 1);
+ tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1)
+ == 0);
+ tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1)
+ == 0);
+
+ /* bridge clients always use IPv6, regardless of ClientUseIPv6 */
+ mock_options.ClientUseIPv4 = 1;
+ mock_options.ClientUseIPv6 = 0;
+ tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0)
+ == 1);
+ tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0)
+ == 1);
+ tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0)
+ == 0);
+ tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0)
+ == 0);
+
/* Test the function's address matching with IPv4 on */
memset(&mock_options, 0, sizeof(or_options_t));
mock_options.ClientUseIPv4 = 1;
@@ -1389,6 +1421,22 @@ test_policies_fascist_firewall_choose_address(void *arg)
FIREWALL_DIR_CONNECTION, 1)
== &ipv4_dir_ap);
+ /* Auto (Preferring IPv4) */
+ mock_options.ClientPreferIPv6ORPort = -1;
+ mock_options.ClientPreferIPv6DirPort = -1;
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 0)
+ == &ipv4_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 1)
+ == &ipv4_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 0)
+ == &ipv4_dir_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 1)
+ == &ipv4_dir_ap);
+
/* Preferring IPv6 */
mock_options.ClientPreferIPv6ORPort = 1;
mock_options.ClientPreferIPv6DirPort = 1;
@@ -1440,41 +1488,75 @@ test_policies_fascist_firewall_choose_address(void *arg)
/* Choose an address with UseBridges on */
memset(&mock_options, 0, sizeof(or_options_t));
mock_options.UseBridges = 1;
+ mock_options.ClientUseIPv4 = 1;
+ mock_options.ClientUseIPv6 = 1;
- for (mock_options.ClientUseIPv4 = 0; mock_options.ClientUseIPv4 <= 1;
- mock_options.ClientUseIPv4++) {
- for (mock_options.ClientUseIPv6 = 0; mock_options.ClientUseIPv6 <= 1;
- mock_options.ClientUseIPv6++) {
- for (mock_options.ClientPreferIPv6ORPort = 0;
- mock_options.ClientPreferIPv6ORPort <= 1;
- mock_options.ClientPreferIPv6ORPort++) {
- for (mock_options.ClientPreferIPv6DirPort = 0;
- mock_options.ClientPreferIPv6DirPort <= 1;
- mock_options.ClientPreferIPv6DirPort++) {
- /* This (ab)uses the actual enum values */
- tt_assert(FIREWALL_OR_CONNECTION < FIREWALL_DIR_CONNECTION);
- for (firewall_connection_t fw_connection = FIREWALL_OR_CONNECTION;
- fw_connection <= FIREWALL_DIR_CONNECTION; fw_connection++) {
- for (int pref_only = 0; pref_only <= 1; pref_only++) {
-
- /* Ignoring all other settings, want_a should choose the address
- * for bridge clients */
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap,
- &ipv6_or_ap, 1,
- fw_connection,
- pref_only)
- == &ipv4_or_ap);
- tt_assert(fascist_firewall_choose_address(&ipv4_or_ap,
- &ipv6_or_ap, 0,
- fw_connection,
- pref_only)
- == &ipv6_or_ap);
- }
- }
- }
- }
- }
- }
+ /* Preferring IPv4 */
+ mock_options.ClientPreferIPv6ORPort = 0;
+ mock_options.ClientPreferIPv6DirPort = 0;
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 0)
+ == &ipv4_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 1)
+ == &ipv4_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 0)
+ == &ipv4_dir_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 1)
+ == &ipv4_dir_ap);
+
+ /* Auto (Preferring IPv6 for bridge clients) */
+ mock_options.ClientPreferIPv6ORPort = -1;
+ mock_options.ClientPreferIPv6DirPort = -1;
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 0)
+ == &ipv6_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 1)
+ == &ipv6_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 0)
+ == &ipv6_dir_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 1)
+ == &ipv6_dir_ap);
+
+ /* Preferring IPv6 */
+ mock_options.ClientPreferIPv6ORPort = 1;
+ mock_options.ClientPreferIPv6DirPort = 1;
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 0)
+ == &ipv6_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 1)
+ == &ipv6_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 0)
+ == &ipv6_dir_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 1)
+ == &ipv6_dir_ap);
+
+
+ /* In the default configuration (Auto / IPv6 off), bridge clients should
+ * still use and prefer IPv6 regardless of ClientUseIPv6. */
+ mock_options.ClientUseIPv6 = 0;
+ mock_options.ClientPreferIPv6ORPort = -1;
+ mock_options.ClientPreferIPv6DirPort = -1;
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 0)
+ == &ipv6_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
+ FIREWALL_OR_CONNECTION, 1)
+ == &ipv6_or_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 0)
+ == &ipv6_dir_ap);
+ tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
+ FIREWALL_DIR_CONNECTION, 1)
+ == &ipv6_dir_ap);
/* Choose an address with IPv4 on */
memset(&mock_options, 0, sizeof(or_options_t));
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits