mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge remote-tracking branch 'teor/bug18348-v2'
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
o Major bug fixes (relays, bridge clients):
|
||||
- Ensure relays always allow IPv4 OR and Dir connections.
|
||||
Ensure bridge clients use the address configured in the bridge line.
|
||||
Fixes bug 18348; bugfix on 0.2.8.1-alpha.
|
||||
Reported by sysrqb, patch by teor.
|
||||
@@ -1763,6 +1763,13 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
|
||||
log_backtrace(LOG_WARN, LD_BUG, "Address came from");
|
||||
}
|
||||
|
||||
/* Bridges are allowed to break IPv4/IPv6 ORPort preferences to connect to
|
||||
* the node's configured address when ClientPreferIPv6ORPort is auto */
|
||||
if (options->UseBridges && conn->type == CONN_TYPE_OR
|
||||
&& options->ClientPreferIPv6ORPort == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we couldn't satisfy an address family preference */
|
||||
if ((!pref_ipv6 && tor_addr_family(&real_addr) == AF_INET6)
|
||||
|| (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
|
||||
|
||||
+1
-1
@@ -972,7 +972,7 @@ directory_command_should_use_begindir(const or_options_t *options,
|
||||
return 0;
|
||||
if (indirection == DIRIND_ONEHOP)
|
||||
if (!fascist_firewall_allows_address_addr(addr, or_port,
|
||||
FIREWALL_OR_CONNECTION, 0) ||
|
||||
FIREWALL_OR_CONNECTION, 0, 0) ||
|
||||
directory_fetches_from_authorities(options))
|
||||
return 0; /* We're firewalled or are acting like a relay -- also no. */
|
||||
return 1;
|
||||
|
||||
+4
-3
@@ -2121,9 +2121,9 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
|
||||
}
|
||||
|
||||
/* Until we get a descriptor for the bridge, we only know one address for
|
||||
* it. If we */
|
||||
* it. */
|
||||
if (!fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
|
||||
FIREWALL_OR_CONNECTION, 0)) {
|
||||
FIREWALL_OR_CONNECTION, 0, 0)) {
|
||||
log_notice(LD_CONFIG, "Tried to fetch a descriptor directly from a "
|
||||
"bridge, but that bridge is not reachable through our "
|
||||
"firewall.");
|
||||
@@ -2193,7 +2193,8 @@ fetch_bridge_descriptors(const or_options_t *options, time_t now)
|
||||
|
||||
if (ask_bridge_directly &&
|
||||
!fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
|
||||
FIREWALL_OR_CONNECTION, 0)) {
|
||||
FIREWALL_OR_CONNECTION, 0,
|
||||
0)) {
|
||||
log_notice(LD_DIR, "Bridge at '%s' isn't reachable by our "
|
||||
"firewall policy. %s.",
|
||||
fmt_addrport(&bridge->addr, bridge->port),
|
||||
|
||||
@@ -981,6 +981,9 @@ node_has_ipv6_dirport(const node_t *node)
|
||||
* i) the node_t says that it prefers IPv6
|
||||
* or
|
||||
* ii) the router has no IPv4 OR address.
|
||||
*
|
||||
* If you don't have a node, consider looking it up.
|
||||
* If there is no node, use fascist_firewall_prefer_ipv6_orport().
|
||||
*/
|
||||
int
|
||||
node_ipv6_or_preferred(const node_t *node)
|
||||
@@ -1078,6 +1081,8 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
* i) the router has no IPv4 Dir address.
|
||||
* or
|
||||
* ii) our preference is for IPv6 Dir addresses.
|
||||
*
|
||||
* If there is no node, use fascist_firewall_prefer_ipv6_dirport().
|
||||
*/
|
||||
int
|
||||
node_ipv6_dir_preferred(const node_t *node)
|
||||
|
||||
+2
-2
@@ -4092,8 +4092,8 @@ typedef struct {
|
||||
int ClientUseIPv6;
|
||||
/** If true, prefer an IPv6 OR port over an IPv4 one for entry node
|
||||
* connections. If auto, bridge clients prefer IPv6, and other clients
|
||||
* prefer IPv4. Use fascist_firewall_prefer_ipv6_orport() instead of
|
||||
* accessing this value directly. */
|
||||
* prefer IPv4. Use node_ipv6_or_preferred() instead of accessing this value
|
||||
* directly. */
|
||||
int ClientPreferIPv6ORPort;
|
||||
/** If true, prefer an IPv6 directory port over an IPv4 one for direct
|
||||
* directory connections. If auto, bridge clients prefer IPv6, and other
|
||||
|
||||
+153
-155
@@ -399,20 +399,25 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
const or_options_t *options = get_options();
|
||||
const int client_mode = !server_mode(options);
|
||||
|
||||
if (!addr || tor_addr_is_null(addr) || !port) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!server_mode(options)) {
|
||||
if (tor_addr_family(addr) == AF_INET &&
|
||||
(!options->ClientUseIPv4 || (pref_only && pref_ipv6)))
|
||||
return 0;
|
||||
/* Clients stop using IPv4 if it's disabled. In most cases, clients also
|
||||
* stop using IPv4 if it's not preferred.
|
||||
* Servers must have IPv4 enabled and preferred. */
|
||||
if (tor_addr_family(addr) == AF_INET && client_mode &&
|
||||
(!options->ClientUseIPv4 || (pref_only && pref_ipv6))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Bridges can always use IPv6 */
|
||||
if (tor_addr_family(addr) == AF_INET6 &&
|
||||
(!fascist_firewall_use_ipv6(options) || (pref_only && !pref_ipv6)))
|
||||
return 0;
|
||||
/* Clients and Servers won't use IPv6 unless it's enabled (and in most
|
||||
* cases, IPv6 must also be preferred before it will be used). */
|
||||
if (tor_addr_family(addr) == AF_INET6 &&
|
||||
(!fascist_firewall_use_ipv6(options) || (pref_only && !pref_ipv6))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr_policy_permits_tor_addr(addr, port,
|
||||
@@ -420,6 +425,8 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
|
||||
}
|
||||
|
||||
/** Is this client configured to use IPv6?
|
||||
* Use node_ipv6_or/dir_preferred() when checking a specific node and OR/Dir
|
||||
* port: it supports bridge client per-node IPv6 preferences.
|
||||
*/
|
||||
int
|
||||
fascist_firewall_use_ipv6(const or_options_t *options)
|
||||
@@ -455,17 +462,12 @@ fascist_firewall_prefer_ipv6_impl(const or_options_t *options)
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6 ORPorts?
|
||||
* Use node_ipv6_or_preferred() whenever possible: it supports bridge client
|
||||
* per-node IPv6 preferences.
|
||||
*/
|
||||
int
|
||||
fascist_firewall_prefer_ipv6_orport(const or_options_t *options)
|
||||
{
|
||||
/* node->ipv6_preferred is set from fascist_firewall_prefer_ipv6_orport()
|
||||
* each time the consensus is loaded.
|
||||
* If our preferences change, we will only reset ipv6_preferred on the node
|
||||
* when the next consensus is loaded. But the consensus is realoded when the
|
||||
* configuration changes after a HUP. So as long as the result of this
|
||||
* function only depends on Tor's options, everything should work ok.
|
||||
*/
|
||||
int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
|
||||
|
||||
if (pref_ipv6 >= 0) {
|
||||
@@ -481,6 +483,9 @@ fascist_firewall_prefer_ipv6_orport(const or_options_t *options)
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6 DirPorts?
|
||||
*
|
||||
* (node_ipv6_dir_preferred() doesn't support bridge client per-node IPv6
|
||||
* preferences. There's no reason to use it instead of this function.)
|
||||
*/
|
||||
int
|
||||
fascist_firewall_prefer_ipv6_dirport(const or_options_t *options)
|
||||
@@ -502,26 +507,23 @@ fascist_firewall_prefer_ipv6_dirport(const or_options_t *options)
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* addr:port. Uses ReachableORAddresses or ReachableDirAddresses based on
|
||||
* fw_connection.
|
||||
* If pref_only, return false if addr is not in the client's preferred address
|
||||
* family.
|
||||
* If pref_only is true, return true if addr is in the client's preferred
|
||||
* address family, which is IPv6 if pref_ipv6 is true, and IPv4 otherwise.
|
||||
* If pref_only is false, ignore pref_ipv6, and return true if addr is allowed.
|
||||
*/
|
||||
int
|
||||
fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
const or_options_t *options = get_options();
|
||||
|
||||
if (fw_connection == FIREWALL_OR_CONNECTION) {
|
||||
return fascist_firewall_allows_address(addr, port,
|
||||
reachable_or_addr_policy,
|
||||
pref_only,
|
||||
fascist_firewall_prefer_ipv6_orport(options));
|
||||
pref_only, pref_ipv6);
|
||||
} else if (fw_connection == FIREWALL_DIR_CONNECTION) {
|
||||
return fascist_firewall_allows_address(addr, port,
|
||||
reachable_dir_addr_policy,
|
||||
pref_only,
|
||||
fascist_firewall_prefer_ipv6_dirport(options));
|
||||
pref_only, pref_ipv6);
|
||||
} else {
|
||||
log_warn(LD_BUG, "Bad firewall_connection_t value %d.",
|
||||
fw_connection);
|
||||
@@ -532,57 +534,58 @@ fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* addr:port (ap). Uses ReachableORAddresses or ReachableDirAddresses based on
|
||||
* fw_connection.
|
||||
* If pref_only, return false if addr is not in the client's preferred address
|
||||
* family.
|
||||
* pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
|
||||
*/
|
||||
int
|
||||
static int
|
||||
fascist_firewall_allows_address_ap(const tor_addr_port_t *ap,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
tor_assert(ap);
|
||||
return fascist_firewall_allows_address_addr(&ap->addr, ap->port,
|
||||
fw_connection, pref_only);
|
||||
fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
}
|
||||
|
||||
/* Return true iff we think our firewall will let us make a connection to
|
||||
* ipv4h_or_addr:ipv4_or_port. ipv4h_or_addr is interpreted in host order.
|
||||
* Uses ReachableORAddresses or ReachableDirAddresses based on
|
||||
* fw_connection.
|
||||
* If pref_only, return false if addr is not in the client's preferred address
|
||||
* family. */
|
||||
int
|
||||
* pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
|
||||
*/
|
||||
static 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 pref_only, int pref_ipv6)
|
||||
{
|
||||
tor_addr_t ipv4_or_addr;
|
||||
tor_addr_from_ipv4h(&ipv4_or_addr, ipv4h_or_addr);
|
||||
return fascist_firewall_allows_address_addr(&ipv4_or_addr, ipv4_or_port,
|
||||
fw_connection, pref_only);
|
||||
fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* ipv4h_addr/ipv6_addr. Uses ipv4_orport/ipv6_orport/ReachableORAddresses or
|
||||
* ipv4_dirport/ipv6_dirport/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. */
|
||||
* pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
|
||||
*/
|
||||
static int
|
||||
fascist_firewall_allows_base(uint32_t ipv4h_addr, uint16_t ipv4_orport,
|
||||
uint16_t ipv4_dirport,
|
||||
const tor_addr_t *ipv6_addr, uint16_t ipv6_orport,
|
||||
uint16_t ipv6_dirport,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
if (fascist_firewall_allows_address_ipv4h(ipv4h_addr,
|
||||
(fw_connection == FIREWALL_OR_CONNECTION
|
||||
? ipv4_orport
|
||||
: ipv4_dirport),
|
||||
fw_connection,
|
||||
pref_only)) {
|
||||
pref_only, pref_ipv6)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -591,18 +594,18 @@ fascist_firewall_allows_base(uint32_t ipv4h_addr, uint16_t ipv4_orport,
|
||||
? ipv6_orport
|
||||
: ipv6_dirport),
|
||||
fw_connection,
|
||||
pref_only)) {
|
||||
pref_only, pref_ipv6)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Like fascist_firewall_allows_ri, but doesn't consult the node. */
|
||||
/** Like fascist_firewall_allows_base(), but takes ri. */
|
||||
static int
|
||||
fascist_firewall_allows_ri_impl(const routerinfo_t *ri,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
if (!ri) {
|
||||
return 0;
|
||||
@@ -611,14 +614,15 @@ fascist_firewall_allows_ri_impl(const routerinfo_t *ri,
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same */
|
||||
return fascist_firewall_allows_base(ri->addr, ri->or_port, ri->dir_port,
|
||||
&ri->ipv6_addr, ri->ipv6_orport,
|
||||
ri->dir_port, fw_connection, pref_only);
|
||||
ri->dir_port, fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
}
|
||||
|
||||
/** Like fascist_firewall_allows_rs, but doesn't consult the node. */
|
||||
static int
|
||||
fascist_firewall_allows_rs_impl(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
if (!rs) {
|
||||
return 0;
|
||||
@@ -627,16 +631,15 @@ fascist_firewall_allows_rs_impl(const routerstatus_t *rs,
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same */
|
||||
return fascist_firewall_allows_base(rs->addr, rs->or_port, rs->dir_port,
|
||||
&rs->ipv6_addr, rs->ipv6_orport,
|
||||
rs->dir_port, fw_connection, pref_only);
|
||||
rs->dir_port, fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* <b>rs</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 rs are not permitted. */
|
||||
/** Like fascist_firewall_allows_base(), but takes rs.
|
||||
* Consults the corresponding node, then falls back to rs if node is NULL.
|
||||
* This should only happen when there's no valid consensus, and rs doesn't
|
||||
* correspond to a bridge client's bridge.
|
||||
*/
|
||||
int
|
||||
fascist_firewall_allows_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection, int pref_only)
|
||||
@@ -645,20 +648,32 @@ fascist_firewall_allows_rs(const routerstatus_t *rs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same */
|
||||
if (fascist_firewall_allows_rs_impl(rs, fw_connection, pref_only)) {
|
||||
return 1;
|
||||
} else {
|
||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||
|
||||
if (node) {
|
||||
return fascist_firewall_allows_node(node, fw_connection, pref_only);
|
||||
} else {
|
||||
/* There's no node-specific IPv6 preference, so use the generic IPv6
|
||||
* preference instead. */
|
||||
const or_options_t *options = get_options();
|
||||
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
|
||||
? fascist_firewall_prefer_ipv6_orport(options)
|
||||
: fascist_firewall_prefer_ipv6_dirport(options));
|
||||
|
||||
return fascist_firewall_allows_rs_impl(rs, fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
}
|
||||
}
|
||||
|
||||
/** Like fascist_firewall_allows_md, but doesn't consult the node. */
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* ipv6_addr:ipv6_orport based on ReachableORAddresses.
|
||||
* If <b>fw_connection</b> is FIREWALL_DIR_CONNECTION, returns 0.
|
||||
* pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
|
||||
*/
|
||||
static int
|
||||
fascist_firewall_allows_md_impl(const microdesc_t *md,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
if (!md) {
|
||||
return 0;
|
||||
@@ -671,17 +686,12 @@ fascist_firewall_allows_md_impl(const microdesc_t *md,
|
||||
|
||||
/* Also can't check IPv4, doesn't have that either */
|
||||
return fascist_firewall_allows_address_addr(&md->ipv6_addr, md->ipv6_orport,
|
||||
fw_connection, pref_only);
|
||||
fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
}
|
||||
|
||||
/** 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.
|
||||
* 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. */
|
||||
/** Like fascist_firewall_allows_base(), but takes node, and looks up pref_ipv6
|
||||
* from node_ipv6_or/dir_preferred(). */
|
||||
int
|
||||
fascist_firewall_allows_node(const node_t *node,
|
||||
firewall_connection_t fw_connection,
|
||||
@@ -693,18 +703,24 @@ fascist_firewall_allows_node(const node_t *node,
|
||||
|
||||
node_assert_ok(node);
|
||||
|
||||
const int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
|
||||
? node_ipv6_or_preferred(node)
|
||||
: node_ipv6_dir_preferred(node));
|
||||
|
||||
/* Sometimes, the rs is missing the IPv6 address info, and we need to go
|
||||
* all the way to the md */
|
||||
if (node->ri && fascist_firewall_allows_ri_impl(node->ri, fw_connection,
|
||||
pref_only)) {
|
||||
pref_only, pref_ipv6)) {
|
||||
return 1;
|
||||
} else if (node->rs && fascist_firewall_allows_rs_impl(node->rs,
|
||||
fw_connection,
|
||||
pref_only)) {
|
||||
pref_only,
|
||||
pref_ipv6)) {
|
||||
return 1;
|
||||
} else if (node->md && fascist_firewall_allows_md_impl(node->md,
|
||||
fw_connection,
|
||||
pref_only)) {
|
||||
pref_only,
|
||||
pref_ipv6)) {
|
||||
return 1;
|
||||
} else {
|
||||
/* If we know nothing, assume it's unreachable, we'll never get an address
|
||||
@@ -713,12 +729,7 @@ fascist_firewall_allows_node(const node_t *node,
|
||||
}
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* <b>ds</b> on either its IPv4 or IPv6 address. Uses ReachableORAddresses or
|
||||
* ReachableDirAddresses based on <b>fw_connection</b> (some directory
|
||||
* connections are tunneled over ORPorts).
|
||||
* If pref_only, return false if addr is not in the client's preferred address
|
||||
* family. */
|
||||
/** Like fascist_firewall_allows_rs(), but takes ds. */
|
||||
int
|
||||
fascist_firewall_allows_dir_server(const dir_server_t *ds,
|
||||
firewall_connection_t fw_connection,
|
||||
@@ -731,8 +742,8 @@ fascist_firewall_allows_dir_server(const dir_server_t *ds,
|
||||
/* A dir_server_t always has a fake_status. As long as it has the same
|
||||
* addresses/ports in both fake_status and dir_server_t, this works fine.
|
||||
* (See #17867.)
|
||||
* This function relies on fascist_firewall_allows_rs looking up the node on
|
||||
* failure, because it will get the latest info for the relay. */
|
||||
* This function relies on fascist_firewall_choose_address_rs looking up the
|
||||
* node if it can, because that will get the latest info for the relay. */
|
||||
return fascist_firewall_allows_rs(&ds->fake_status, fw_connection,
|
||||
pref_only);
|
||||
}
|
||||
@@ -741,23 +752,25 @@ fascist_firewall_allows_dir_server(const dir_server_t *ds,
|
||||
* choose one based on want_a and return it.
|
||||
* Otherwise, return whichever is allowed.
|
||||
* Otherwise, return NULL.
|
||||
* If pref_only, only return an address if it's in the client's preferred
|
||||
* address family. */
|
||||
* pref_only and pref_ipv6 work as in fascist_firewall_allows_address_addr().
|
||||
*/
|
||||
static const tor_addr_port_t *
|
||||
fascist_firewall_choose_address_impl(const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b,
|
||||
int want_a,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
const tor_addr_port_t *use_a = NULL;
|
||||
const tor_addr_port_t *use_b = NULL;
|
||||
|
||||
if (fascist_firewall_allows_address_ap(a, fw_connection, pref_only)) {
|
||||
if (fascist_firewall_allows_address_ap(a, fw_connection, pref_only,
|
||||
pref_ipv6)) {
|
||||
use_a = a;
|
||||
}
|
||||
|
||||
if (fascist_firewall_allows_address_ap(b, fw_connection, pref_only)) {
|
||||
if (fascist_firewall_allows_address_ap(b, fw_connection, pref_only,
|
||||
pref_ipv6)) {
|
||||
use_b = b;
|
||||
}
|
||||
|
||||
@@ -779,17 +792,17 @@ fascist_firewall_choose_address_impl(const tor_addr_port_t *a,
|
||||
* choose one based on want_a and return it.
|
||||
* - Otherwise, return whichever is preferred.
|
||||
* Otherwise, return NULL. */
|
||||
const tor_addr_port_t *
|
||||
STATIC const tor_addr_port_t *
|
||||
fascist_firewall_choose_address(const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b,
|
||||
int want_a,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
int pref_only, int pref_ipv6)
|
||||
{
|
||||
const tor_addr_port_t *pref = fascist_firewall_choose_address_impl(
|
||||
a, b, want_a,
|
||||
fw_connection,
|
||||
1);
|
||||
1, pref_ipv6);
|
||||
if (pref_only || pref) {
|
||||
/* If there is a preferred address, use it. If we can only use preferred
|
||||
* addresses, and neither address is preferred, pref will be NULL, and we
|
||||
@@ -799,7 +812,7 @@ fascist_firewall_choose_address(const tor_addr_port_t *a,
|
||||
/* If there's no preferred address, and we can return addresses that are
|
||||
* not preferred, use an address that's allowed */
|
||||
return fascist_firewall_choose_address_impl(a, b, want_a, fw_connection,
|
||||
0);
|
||||
0, pref_ipv6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,6 +823,8 @@ fascist_firewall_choose_address(const tor_addr_port_t *a,
|
||||
* <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 both addresses could be chosen (they are both preferred or both allowed)
|
||||
* choose IPv6 if pref_ipv6 is true, otherwise choose IPv4.
|
||||
* If neither address is chosen, return 0, else return 1. */
|
||||
static int
|
||||
fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
|
||||
@@ -820,14 +835,11 @@ fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
|
||||
uint16_t ipv6_dirport,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only,
|
||||
int pref_ipv6,
|
||||
tor_addr_port_t* ap)
|
||||
{
|
||||
const tor_addr_port_t *result = NULL;
|
||||
/* This argument is ignored as long as the address pair is IPv4/IPv6,
|
||||
* because we always have a preference in a client.
|
||||
* For bridge clients, this selects the preferred address, which was
|
||||
* previously IPv6 (if a bridge has both), so we keep that behaviour. */
|
||||
const int bridge_client_prefer_ipv4 = 0;
|
||||
const int want_ipv4 = !pref_ipv6;
|
||||
|
||||
tor_assert(ipv6_addr);
|
||||
tor_assert(ap);
|
||||
@@ -845,8 +857,9 @@ fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
|
||||
: ipv6_dirport);
|
||||
|
||||
result = fascist_firewall_choose_address(&ipv4_ap, &ipv6_ap,
|
||||
bridge_client_prefer_ipv4,
|
||||
fw_connection, pref_only);
|
||||
want_ipv4,
|
||||
fw_connection, pref_only,
|
||||
pref_ipv6);
|
||||
|
||||
if (result) {
|
||||
tor_addr_copy(&ap->addr, &result->addr);
|
||||
@@ -857,7 +870,7 @@ fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr,
|
||||
}
|
||||
}
|
||||
|
||||
/** Like fascist_firewall_choose_address_base, but takes a host-order IPv4
|
||||
/** Like fascist_firewall_choose_address_base(), but takes a host-order IPv4
|
||||
* address as the first parameter. */
|
||||
static int
|
||||
fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
|
||||
@@ -868,6 +881,7 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
|
||||
uint16_t ipv6_dirport,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only,
|
||||
int pref_ipv6,
|
||||
tor_addr_port_t* ap)
|
||||
{
|
||||
tor_addr_t ipv4_addr;
|
||||
@@ -875,34 +889,15 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
|
||||
return fascist_firewall_choose_address_base(&ipv4_addr, ipv4_orport,
|
||||
ipv4_dirport, ipv6_addr,
|
||||
ipv6_orport, ipv6_dirport,
|
||||
fw_connection, pref_only, ap);
|
||||
fw_connection, pref_only,
|
||||
pref_ipv6, ap);
|
||||
}
|
||||
|
||||
#define IPV6_OR_LOOKUP(r, identity_digest, ipv6_or_ap) \
|
||||
STMT_BEGIN \
|
||||
if (!(r)->ipv6_orport || tor_addr_is_null(&(r)->ipv6_addr)) { \
|
||||
const node_t *node = node_get_by_id((identity_digest)); \
|
||||
if (node) { \
|
||||
node_get_pref_ipv6_orport(node, &(ipv6_or_ap)); \
|
||||
} else { \
|
||||
tor_addr_make_null(&(ipv6_or_ap).addr, AF_INET6); \
|
||||
(ipv6_or_ap).port = 0; \
|
||||
} \
|
||||
} else { \
|
||||
tor_addr_copy(&(ipv6_or_ap).addr, &(r)->ipv6_addr); \
|
||||
(ipv6_or_ap).port = (r)->ipv6_orport; \
|
||||
} \
|
||||
STMT_END
|
||||
|
||||
/** 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
|
||||
* 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 rs are not valid. */
|
||||
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
|
||||
* Consults the corresponding node, then falls back to rs if node is NULL.
|
||||
* This should only happen when there's no valid consensus, and rs doesn't
|
||||
* correspond to a bridge client's bridge.
|
||||
*/
|
||||
int
|
||||
fascist_firewall_choose_address_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
@@ -914,32 +909,37 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
|
||||
|
||||
tor_assert(ap);
|
||||
|
||||
/* Don't do the lookup if the IPv6 address/port in rs is OK.
|
||||
* If it's OK, assume the dir_port is also OK. */
|
||||
tor_addr_port_t ipv6_or_ap;
|
||||
IPV6_OR_LOOKUP(rs, rs->identity_digest, ipv6_or_ap);
|
||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same.
|
||||
* Assume the IPv6 OR and Dir addresses are the same. */
|
||||
return fascist_firewall_choose_address_ipv4h(rs->addr,
|
||||
rs->or_port,
|
||||
rs->dir_port,
|
||||
&ipv6_or_ap.addr,
|
||||
ipv6_or_ap.port,
|
||||
rs->dir_port,
|
||||
fw_connection,
|
||||
pref_only,
|
||||
ap);
|
||||
if (node) {
|
||||
return fascist_firewall_choose_address_node(node, fw_connection, pref_only,
|
||||
ap);
|
||||
} else {
|
||||
/* There's no node-specific IPv6 preference, so use the generic IPv6
|
||||
* preference instead. */
|
||||
const or_options_t *options = get_options();
|
||||
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
|
||||
? fascist_firewall_prefer_ipv6_orport(options)
|
||||
: fascist_firewall_prefer_ipv6_dirport(options));
|
||||
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same.
|
||||
* Assume the IPv6 OR and Dir addresses are the same. */
|
||||
return fascist_firewall_choose_address_ipv4h(rs->addr,
|
||||
rs->or_port,
|
||||
rs->dir_port,
|
||||
&rs->ipv6_addr,
|
||||
rs->ipv6_orport,
|
||||
rs->dir_port,
|
||||
fw_connection,
|
||||
pref_only,
|
||||
pref_ipv6,
|
||||
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
|
||||
* 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. */
|
||||
/** Like fascist_firewall_choose_address_base(), but takes <b>node</b>, and
|
||||
* looks up the node's IPv6 preference rather than taking an argument
|
||||
* for pref_ipv6. */
|
||||
int
|
||||
fascist_firewall_choose_address_node(const node_t *node,
|
||||
firewall_connection_t fw_connection,
|
||||
@@ -951,6 +951,10 @@ fascist_firewall_choose_address_node(const node_t *node,
|
||||
|
||||
node_assert_ok(node);
|
||||
|
||||
const int pref_ipv6_node = (fw_connection == FIREWALL_OR_CONNECTION
|
||||
? node_ipv6_or_preferred(node)
|
||||
: node_ipv6_dir_preferred(node));
|
||||
|
||||
tor_addr_port_t ipv4_or_ap;
|
||||
node_get_prim_orport(node, &ipv4_or_ap);
|
||||
tor_addr_port_t ipv4_dir_ap;
|
||||
@@ -970,21 +974,16 @@ fascist_firewall_choose_address_node(const node_t *node,
|
||||
ipv6_dir_ap.port,
|
||||
fw_connection,
|
||||
pref_only,
|
||||
pref_ipv6_node,
|
||||
ap);
|
||||
}
|
||||
|
||||
/** Copy an address and port from <b>ds</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. */
|
||||
/** Like fascist_firewall_choose_address_rs(), but takes <b>ds</b>. */
|
||||
int
|
||||
fascist_firewall_choose_address_dir_server(const dir_server_t *ds,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t *ap)
|
||||
int pref_only,
|
||||
tor_addr_port_t *ap)
|
||||
{
|
||||
if (!ds) {
|
||||
return 0;
|
||||
@@ -994,8 +993,7 @@ fascist_firewall_choose_address_dir_server(const dir_server_t *ds,
|
||||
* addresses/ports in both fake_status and dir_server_t, this works fine.
|
||||
* (See #17867.)
|
||||
* This function relies on fascist_firewall_choose_address_rs looking up the
|
||||
* addresses from the node if it can, because that will get the latest info
|
||||
* for the relay. */
|
||||
* node if it can, because that will get the latest info for the relay. */
|
||||
return fascist_firewall_choose_address_rs(&ds->fake_status, fw_connection,
|
||||
pref_only, ap);
|
||||
}
|
||||
|
||||
+12
-16
@@ -35,16 +35,11 @@ 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,
|
||||
int fascist_firewall_allows_address_addr(const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_allows_address_ap(const tor_addr_port_t *ap,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
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 pref_only, int pref_ipv6);
|
||||
|
||||
int fascist_firewall_allows_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
@@ -55,12 +50,6 @@ int fascist_firewall_allows_dir_server(const dir_server_t *ds,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
|
||||
const tor_addr_port_t * fascist_firewall_choose_address(
|
||||
const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b,
|
||||
int want_a,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_choose_address_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
@@ -69,7 +58,7 @@ int fascist_firewall_choose_address_node(const node_t *node,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
int fascist_firewall_choose_address_dir_server(const dir_server_t *ds,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
|
||||
int dir_policy_permits_address(const tor_addr_t *addr);
|
||||
int socks_policy_permits_address(const tor_addr_t *addr);
|
||||
@@ -140,6 +129,13 @@ STATIC int fascist_firewall_allows_address(const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
smartlist_t *firewall_policy,
|
||||
int pref_only, int pref_ipv6);
|
||||
STATIC const tor_addr_port_t * fascist_firewall_choose_address(
|
||||
const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b,
|
||||
int want_a,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, int pref_ipv6);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -1566,14 +1566,14 @@ router_picked_poor_directory_log(const routerstatus_t *rs)
|
||||
} else if (!fascist_firewall_allows_rs(rs, FIREWALL_OR_CONNECTION, 1)
|
||||
&& !fascist_firewall_allows_rs(rs, FIREWALL_DIR_CONNECTION, 1)
|
||||
) {
|
||||
log_warn(LD_BUG, "Selected a directory %s with non-preferred OR and Dir "
|
||||
log_info(LD_BUG, "Selected a directory %s with non-preferred OR and Dir "
|
||||
"addresses for launching a connection: "
|
||||
"IPv4 %s OR %d Dir %d IPv6 %s OR %d Dir %d",
|
||||
routerstatus_describe(rs),
|
||||
fmt_addr32(rs->addr), rs->or_port,
|
||||
rs->dir_port, fmt_addr(&rs->ipv6_addr),
|
||||
rs->ipv6_orport, rs->dir_port);
|
||||
log_backtrace(LOG_WARN, LD_BUG, "Node search initiated by");
|
||||
log_backtrace(LOG_INFO, LD_BUG, "Node search initiated by");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+345
-173
@@ -1374,6 +1374,51 @@ test_policies_fascist_firewall_allows_address(void *arg)
|
||||
#define TEST_IPV6_OR_PORT 61234
|
||||
#define TEST_IPV6_DIR_PORT 62345
|
||||
|
||||
/* Check that fascist_firewall_choose_address_rs() returns the expected
|
||||
* results. */
|
||||
#define CHECK_CHOSEN_ADDR_RS(fake_rs, fw_connection, pref_only, expect_rv, \
|
||||
expect_ap) \
|
||||
STMT_BEGIN \
|
||||
tor_addr_port_t chosen_rs_ap; \
|
||||
tor_addr_make_null(&chosen_rs_ap.addr, AF_INET); \
|
||||
chosen_rs_ap.port = 0; \
|
||||
tt_int_op(fascist_firewall_choose_address_rs(&(fake_rs), \
|
||||
(fw_connection), \
|
||||
(pref_only), \
|
||||
&chosen_rs_ap), \
|
||||
OP_EQ, (expect_rv)); \
|
||||
tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_rs_ap.addr)); \
|
||||
tt_int_op((expect_ap).port, OP_EQ, chosen_rs_ap.port); \
|
||||
STMT_END
|
||||
|
||||
/* Check that fascist_firewall_choose_address_node() returns the expected
|
||||
* results. */
|
||||
#define CHECK_CHOSEN_ADDR_NODE(fake_node, fw_connection, pref_only, \
|
||||
expect_rv, expect_ap) \
|
||||
STMT_BEGIN \
|
||||
tor_addr_port_t chosen_node_ap; \
|
||||
tor_addr_make_null(&chosen_node_ap.addr, AF_INET); \
|
||||
chosen_node_ap.port = 0; \
|
||||
tt_int_op(fascist_firewall_choose_address_node(&(fake_node), \
|
||||
(fw_connection), \
|
||||
(pref_only), \
|
||||
&chosen_node_ap), \
|
||||
OP_EQ, (expect_rv)); \
|
||||
tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_node_ap.addr)); \
|
||||
tt_int_op((expect_ap).port, OP_EQ, chosen_node_ap.port); \
|
||||
STMT_END
|
||||
|
||||
/* Check that fascist_firewall_choose_address_rs and
|
||||
* fascist_firewall_choose_address_node() both return the expected results. */
|
||||
#define CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, fw_connection, pref_only, \
|
||||
expect_rv, expect_ap) \
|
||||
STMT_BEGIN \
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, fw_connection, pref_only, expect_rv, \
|
||||
expect_ap); \
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, fw_connection, pref_only, expect_rv, \
|
||||
expect_ap); \
|
||||
STMT_END
|
||||
|
||||
/** Run unit tests for fascist_firewall_choose_address */
|
||||
static void
|
||||
test_policies_fascist_firewall_choose_address(void *arg)
|
||||
@@ -1402,6 +1447,111 @@ test_policies_fascist_firewall_choose_address(void *arg)
|
||||
tor_addr_make_null(&n_ipv6_ap.addr, AF_INET6);
|
||||
n_ipv6_ap.port = 0;
|
||||
|
||||
/* Sanity check fascist_firewall_choose_address with IPv4 and IPv6 on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
mock_options.ClientUseIPv6 = 1;
|
||||
mock_options.UseBridges = 0;
|
||||
|
||||
/* Prefer IPv4 */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
|
||||
FIREWALL_OR_CONNECTION, 0, 0)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
|
||||
FIREWALL_OR_CONNECTION, 1, 0)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 1,
|
||||
FIREWALL_DIR_CONNECTION, 0, 0)
|
||||
== &ipv4_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 1,
|
||||
FIREWALL_DIR_CONNECTION, 1, 0)
|
||||
== &ipv4_dir_ap);
|
||||
|
||||
/* Prefer IPv6 */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0, 1)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1, 1)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0, 1)
|
||||
== &ipv6_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1, 1)
|
||||
== &ipv6_dir_ap);
|
||||
|
||||
/* Unusual inputs */
|
||||
|
||||
/* null preferred OR addresses */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0, 1)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &ipv6_or_ap, 1,
|
||||
FIREWALL_OR_CONNECTION, 0, 0)
|
||||
== &ipv6_or_ap);
|
||||
|
||||
/* null both OR addresses */
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0, 1)
|
||||
== NULL);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1,
|
||||
FIREWALL_OR_CONNECTION, 0, 0)
|
||||
== NULL);
|
||||
|
||||
/* null preferred Dir addresses */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0, 1)
|
||||
== &ipv4_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &ipv6_dir_ap, 1,
|
||||
FIREWALL_DIR_CONNECTION, 0, 0)
|
||||
== &ipv6_dir_ap);
|
||||
|
||||
/* null both Dir addresses */
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0, 1)
|
||||
== NULL);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 1,
|
||||
FIREWALL_DIR_CONNECTION, 0, 0)
|
||||
== NULL);
|
||||
|
||||
/* Prefer IPv4 but want IPv6 (contradictory) */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0, 0)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1, 0)
|
||||
== &ipv4_or_ap);
|
||||
|
||||
/* Prefer IPv6 but want IPv4 (contradictory) */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
|
||||
FIREWALL_OR_CONNECTION, 0, 1)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 1,
|
||||
FIREWALL_OR_CONNECTION, 1, 1)
|
||||
== &ipv6_or_ap);
|
||||
|
||||
/* Make a fake rs. There will be no corresponding node.
|
||||
* This is what happens when there's no consensus and we're bootstrapping
|
||||
* from authorities / fallbacks. */
|
||||
routerstatus_t fake_rs;
|
||||
memset(&fake_rs, 0, sizeof(routerstatus_t));
|
||||
/* In a routerstatus, the OR and Dir addresses are the same */
|
||||
fake_rs.addr = tor_addr_to_ipv4h(&ipv4_or_ap.addr);
|
||||
fake_rs.or_port = ipv4_or_ap.port;
|
||||
fake_rs.dir_port = ipv4_dir_ap.port;
|
||||
|
||||
tor_addr_copy(&fake_rs.ipv6_addr, &ipv6_or_ap.addr);
|
||||
fake_rs.ipv6_orport = ipv6_or_ap.port;
|
||||
/* In a routerstatus, the IPv4 and IPv6 DirPorts are the same.*/
|
||||
ipv6_dir_ap.port = TEST_IPV4_DIR_PORT;
|
||||
|
||||
/* Make a fake node. Even though it contains the fake_rs, a lookup won't
|
||||
* find the node from the rs, because they're not in the hash table. */
|
||||
node_t fake_node;
|
||||
memset(&fake_node, 0, sizeof(node_t));
|
||||
fake_node.rs = &fake_rs;
|
||||
|
||||
/* Choose an address with IPv4 and IPv6 on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
@@ -1411,82 +1561,82 @@ test_policies_fascist_firewall_choose_address(void *arg)
|
||||
/* 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);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 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);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_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);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv6_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv6_dir_ap);
|
||||
|
||||
/* Preferring IPv4 OR / IPv6 Dir */
|
||||
mock_options.ClientPreferIPv6ORPort = 0;
|
||||
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)
|
||||
== &ipv6_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv6_dir_ap);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv6_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv6_dir_ap);
|
||||
|
||||
/* Preferring IPv6 OR / IPv4 Dir */
|
||||
mock_options.ClientPreferIPv6ORPort = 1;
|
||||
mock_options.ClientPreferIPv6DirPort = 0;
|
||||
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)
|
||||
== &ipv4_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv4_dir_ap);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* Choose an address with UseBridges on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
@@ -1497,157 +1647,175 @@ test_policies_fascist_firewall_choose_address(void *arg)
|
||||
/* 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);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* Auto:
|
||||
* - bridge clients prefer the configured bridge OR address,
|
||||
* - other clients prefer IPv4 OR by default,
|
||||
* - all clients prefer IPv4 Dir by default.
|
||||
* - bridge clients prefer the configured bridge OR address from the node,
|
||||
* (the configured address family sets node.ipv6_preferred)
|
||||
* - other clients prefer IPv4 OR by default (see above),
|
||||
* - all clients, including bridge clients, prefer IPv4 Dir by default.
|
||||
*/
|
||||
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);
|
||||
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred with a bridge
|
||||
* configured with an IPv4 address */
|
||||
fake_node.ipv6_preferred = 0;
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 0, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 1, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred with a bridge
|
||||
* configured with an IPv6 address */
|
||||
fake_node.ipv6_preferred = 1;
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 0, 1, ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 1, 1, ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* When a rs has no node, it defaults to IPv4 under auto. */
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_OR_CONNECTION, 0, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_OR_CONNECTION, 1, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_DIR_CONNECTION, 0, 1, ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_DIR_CONNECTION, 1, 1, ipv4_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);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv6_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv6_dir_ap);
|
||||
|
||||
/* In the default configuration (Auto / IPv6 off), bridge clients should
|
||||
* still use IPv6, and only prefer it for bridges configured with an IPv6
|
||||
* address, regardless of ClientUseIPv6. */
|
||||
* use both IPv4 and IPv6, but only prefer IPv6 for bridges configured with
|
||||
* an IPv6 address, regardless of ClientUseIPv6. (See above.) */
|
||||
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)
|
||||
== &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);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred with a bridge
|
||||
* configured with an IPv4 address */
|
||||
fake_node.ipv6_preferred = 0;
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 0, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 1, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred with a bridge
|
||||
* configured with an IPv6 address */
|
||||
fake_node.ipv6_preferred = 1;
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 0, 1, ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_OR_CONNECTION, 1, 1, ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_NODE(fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* When a rs has no node, it defaults to IPv4 under auto. */
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_OR_CONNECTION, 0, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_OR_CONNECTION, 1, 1, ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_DIR_CONNECTION, 0, 1, ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RS(fake_rs, FIREWALL_DIR_CONNECTION, 1, 1, ipv4_dir_ap);
|
||||
|
||||
/* Choose an address with IPv4 on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
mock_options.ClientUseIPv6 = 0;
|
||||
mock_options.UseBridges = 0;
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
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);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
/* Choose an address with IPv6 on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 0;
|
||||
mock_options.ClientUseIPv6 = 1;
|
||||
mock_options.UseBridges = 0;
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
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);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv6_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv6_dir_ap);
|
||||
|
||||
/* Choose an address with ClientUseIPv4 0.
|
||||
* This means "use IPv6" regardless of the other settings. */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 0;
|
||||
mock_options.ClientUseIPv6 = 0;
|
||||
mock_options.UseBridges = 0;
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
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);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv6_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv6_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv6_dir_ap);
|
||||
|
||||
/* Choose from unusual inputs */
|
||||
/* Choose an address with ORPort_set 1 (server mode).
|
||||
* This means "use IPv4" regardless of the other settings. */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
mock_options.ORPort_set = 1;
|
||||
mock_options.ClientUseIPv4 = 0;
|
||||
mock_options.ClientUseIPv6 = 1;
|
||||
mock_options.UseBridges = 1;
|
||||
mock_options.ClientPreferIPv6ORPort = 1;
|
||||
mock_options.ClientPreferIPv6DirPort = 1;
|
||||
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== NULL);
|
||||
/* Simulate the initialisation of fake_node.ipv6_preferred */
|
||||
fake_node.ipv6_preferred = fascist_firewall_prefer_ipv6_orport(
|
||||
&mock_options);
|
||||
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv4_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv6_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&n_ipv4_ap, &n_ipv6_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== NULL);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 0, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_OR_CONNECTION, 1, 1,
|
||||
ipv4_or_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 0, 1,
|
||||
ipv4_dir_ap);
|
||||
CHECK_CHOSEN_ADDR_RN(fake_rs, fake_node, FIREWALL_DIR_CONNECTION, 1, 1,
|
||||
ipv4_dir_ap);
|
||||
|
||||
done:
|
||||
UNMOCK(get_options);
|
||||
@@ -1660,6 +1828,10 @@ test_policies_fascist_firewall_choose_address(void *arg)
|
||||
#undef TEST_IPV6_OR_PORT
|
||||
#undef TEST_IPV6_DIR_PORT
|
||||
|
||||
#undef CHECK_CHOSEN_ADDR_RS
|
||||
#undef CHECK_CHOSEN_ADDR_NODE
|
||||
#undef CHECK_CHOSEN_ADDR_RN
|
||||
|
||||
struct testcase_t policy_tests[] = {
|
||||
{ "router_dump_exit_policy_to_string", test_dump_exit_policy_to_string, 0,
|
||||
NULL, NULL },
|
||||
|
||||
Reference in New Issue
Block a user