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.
This commit is contained in:
teor (Tim Wilson-Brown)
2016-01-04 00:35:22 +11:00
parent 4528f89316
commit 3b8216f215
12 changed files with 402 additions and 384 deletions
+12 -37
View File
@@ -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))
+11 -9
View File
@@ -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);
}
}
+11 -1
View File
@@ -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
+56 -100
View File
@@ -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 {
+3 -2
View File
@@ -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);
+7 -3
View File
@@ -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;
+124 -172
View File
@@ -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,
@@ -562,40 +653,6 @@ fascist_firewall_allows_md_impl(const microdesc_t *md,
fw_connection, pref_only);
}
/** 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,
@@ -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
+5 -12
View File
@@ -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);
+4 -4
View File
@@ -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,
+43 -2
View File
@@ -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 */
+117 -35
View File
@@ -1235,10 +1235,42 @@ 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)
== 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);
/* 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)
@@ -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++) {
/* 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);
/* 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);
}
}
}
}
}
}
/* 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));