diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 3688909acb..84a7081588 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -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 },