aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/ticket332385
-rw-r--r--src/app/config/resolve_addr.c29
-rw-r--r--src/test/test_config.c852
3 files changed, 228 insertions, 658 deletions
diff --git a/changes/ticket33238 b/changes/ticket33238
new file mode 100644
index 0000000000..2c4c3968cc
--- /dev/null
+++ b/changes/ticket33238
@@ -0,0 +1,5 @@
+ o Minor feature (address discovery):
+ - If no Address statements are found, relays now prioritize guessing their
+ address by looking at the local interface instead of the local hostname.
+ If the interface address can't be found, the local hostname is used.
+ Closes ticket 33238.
diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c
index 167a4aa4dd..8c08c6ec03 100644
--- a/src/app/config/resolve_addr.c
+++ b/src/app/config/resolve_addr.c
@@ -445,8 +445,8 @@ static fn_address_ret_t
{
/* These functions are in order for our find address algorithm. */
get_address_from_config,
- get_address_from_hostname,
get_address_from_interface,
+ get_address_from_hostname,
};
/** Length of address table as in how many functions. */
static const size_t fn_address_table_len = ARRAY_LENGTH(fn_address_table);
@@ -478,7 +478,17 @@ static const size_t fn_address_table_len = ARRAY_LENGTH(fn_address_table);
*
* If no given Address, fallback to the local hostname (see section 2).
*
- * 2. Look at the local hostname.
+ * 2. Look at the network interface.
+ *
+ * Attempt to find the first public usable address from the list of
+ * network interface returned by the OS.
+ *
+ * On failure, we attempt to look at the local hostname (3).
+ *
+ * On success, addr_out is set with it, method_out is set to "INTERFACE"
+ * and hostname_out is set to NULL.
+ *
+ * 3. Look at the local hostname.
*
* If the local hostname resolves to a non internal address, addr_out is
* set with it, method_out is set to "GETHOSTNAME" and hostname_out is set
@@ -489,20 +499,7 @@ static const size_t fn_address_table_len = ARRAY_LENGTH(fn_address_table);
* If the local hostname resolves to an internal address, an error is
* returned.
*
- * If the local hostname can NOT be resolved, fallback to the network
- * interface (see section 3).
- *
- * 3. Look at the network interface.
- *
- * Attempt to find the first public usable address from the list of
- * network interface returned by the OS.
- *
- * On failure, an error is returned. This error indicates that all
- * attempts have failed and thus the address for the given family can not
- * be found.
- *
- * On success, addr_out is set with it, method_out is set to "INTERFACE"
- * and hostname_out is set to NULL.
+ * If the local hostname can NOT be resolved, an error is returned.
*
* @param options Global configuration options.
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 84b18c90ed..c4d6a6efcd 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -53,6 +53,7 @@
#include "test/test_helpers.h"
#include "test/resolve_test_helpers.h"
+#include "test/log_test_helpers.h"
#include "feature/dirclient/dir_server_st.h"
#include "core/or/port_cfg_st.h"
@@ -989,6 +990,9 @@ test_config_fix_my_family(void *arg)
}
static int n_hostname_01010101 = 0;
+static const char *ret_addr_lookup_01010101[2] = {
+ "1.1.1.1", "0101::0101",
+};
/** This mock function is meant to replace tor_addr_lookup().
* It answers with 1.1.1.1 as IP adddress that resulted from lookup.
@@ -1002,12 +1006,13 @@ tor_addr_lookup_01010101(const char *name, uint16_t family, tor_addr_t *addr)
if (family == AF_INET) {
if (name && addr) {
- tor_addr_from_ipv4h(addr, 0x01010101);
+ int ret = tor_addr_parse(addr, ret_addr_lookup_01010101[0]);
+ tt_int_op(ret, OP_EQ, family);
}
} else if (family == AF_INET6) {
if (name && addr) {
- int ret = tor_addr_parse(addr, "0101::0101");
- tt_int_op(ret, OP_EQ, AF_INET6);
+ int ret = tor_addr_parse(addr, ret_addr_lookup_01010101[1]);
+ tt_int_op(ret, OP_EQ, family);
}
}
done:
@@ -1154,6 +1159,9 @@ tor_gethostname_failure(char *name, size_t namelen)
static int n_get_interface_address6 = 0;
static sa_family_t last_address6_family;
+static const char *ret_get_interface_address6_08080808[2] = {
+ "8.8.8.8", "0808::0808",
+};
/** This mock function is meant to replace get_interface_address().
* It answers with address 8.8.8.8. This function increments
@@ -1169,11 +1177,12 @@ get_interface_address6_08080808(int severity, sa_family_t family,
if (family == AF_INET) {
if (addr) {
- tor_addr_from_ipv4h(addr, 0x08080808);
+ int ret = tor_addr_parse(addr, ret_get_interface_address6_08080808[0]);
+ tt_int_op(ret, OP_EQ, AF_INET);
}
} else if (family == AF_INET6) {
if (addr) {
- int ret = tor_addr_parse(addr, "0808::0808");
+ int ret = tor_addr_parse(addr, ret_get_interface_address6_08080808[1]);
tt_int_op(ret, OP_EQ, AF_INET6);
}
}
@@ -1188,6 +1197,7 @@ get_interface_address6_08080808(int severity, sa_family_t family,
* This function increments <b>n_get_interface_address6</b> by one every
* time it is called.
*/
+#if 0
static int
get_interface_address6_replacement(int severity, sa_family_t family,
tor_addr_t *addr)
@@ -1205,6 +1215,7 @@ get_interface_address6_replacement(int severity, sa_family_t family,
return 0;
}
+#endif
static int n_get_interface_address6_failure = 0;
@@ -1389,8 +1400,40 @@ test_config_find_my_address_mixed(void *arg)
UNMOCK(tor_addr_lookup);
}
+/** Parameters for the find_my_address() test. We test both AF_INET and
+ * AF_INET6 but we have one interface to do so thus we run the same exact unit
+ * tests for both without copying them. */
+typedef struct find_my_address_params_t {
+ /* Index where the mock function results are located. For intance,
+ * tor_addr_lookup_01010101() will have its returned value depending on the
+ * family in ret_addr_lookup_01010101[].
+ *
+ * Values that can be found:
+ * AF_INET : index 0.
+ * AF_INET6: index 1.
+ */
+ int idx;
+ int family;
+ const char *public_ip;
+ const char *internal_ip;
+} find_my_address_params_t;
+
+static find_my_address_params_t addr_param_v4 = {
+ .idx = 0,
+ .family = AF_INET,
+ .public_ip = "128.52.128.105",
+ .internal_ip = "127.0.0.1",
+};
+
+static find_my_address_params_t addr_param_v6 = {
+ .idx = 1,
+ .family = AF_INET6,
+ .public_ip = "4242::4242",
+ .internal_ip = "::1",
+};
+
static void
-test_config_find_my_address_v6(void *arg)
+test_config_find_my_address(void *arg)
{
or_options_t *options;
tor_addr_t resolved_addr, test_addr;
@@ -1398,786 +1441,306 @@ test_config_find_my_address_v6(void *arg)
char *hostname_out = NULL;
bool retval;
int prev_n_hostname_01010101;
- int prev_n_hostname_localhost;
int prev_n_hostname_failure;
+ int prev_n_hostname_localhost;
int prev_n_gethostname_replacement;
int prev_n_gethostname_failure;
int prev_n_gethostname_localhost;
int prev_n_get_interface_address6;
int prev_n_get_interface_address6_failure;
- (void)arg;
+ const find_my_address_params_t *p = arg;
options = options_new();
-
options_init(options);
/*
- * CASE 1:
- * If options->Address is a valid IPv6 address string, we want
- * the corresponding address to be parsed and returned.
+ * Case 1:
+ * 1. Address is a valid address.
+ *
+ * Expected to succeed.
*/
- config_line_append(&options->Address, "Address",
- "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
- tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
+ config_line_append(&options->Address, "Address", p->public_ip);
+ tor_addr_parse(&test_addr, p->public_ip);
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(retval == true);
- tt_want_str_op(method_used, OP_EQ, "CONFIGURED");
- tt_want(hostname_out == NULL);
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- config_free_lines(options->Address);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+ CLEANUP_FOUND_ADDRESS;
/*
- * CASE 2:
- * If options->Address is a valid DNS address, we want find_my_address()
- * function to ask tor_addr_lookup() for help with resolving it
- * and return the address that was resolved (in host order).
+ * Case 2: Address is a resolvable address. Expected to succeed.
*/
-
MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
config_line_append(&options->Address, "Address", "www.torproject.org");
- tor_addr_parse(&test_addr, "0101::0101");
-
- prev_n_hostname_01010101 = n_hostname_01010101;
-
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(retval == true);
- tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
- tt_want_str_op(method_used, OP_EQ, "RESOLVED");
- tt_want_str_op(hostname_out, OP_EQ, "www.torproject.org");
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- UNMOCK(tor_addr_lookup);
-
- config_free_lines(options->Address);
- tor_free(hostname_out);
-
- /*
- * CASE 3:
- * Given that options->Address is NULL, we want find_my_address()
- * to try and use tor_gethostname() to get hostname AND use
- * tor_addr_lookup() to get IP address.
- */
-
- tor_addr_make_unspec(&resolved_addr);
- options->Address = NULL;
- tor_addr_parse(&test_addr, "0101::0101");
-
- MOCK(tor_gethostname, tor_gethostname_replacement);
- MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
+ tor_addr_parse(&test_addr, ret_addr_lookup_01010101[p->idx]);
- prev_n_gethostname_replacement = n_gethostname_replacement;
prev_n_hostname_01010101 = n_hostname_01010101;
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(retval == true);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
- tt_want_str_op(method_used, OP_EQ, "GETHOSTNAME");
- tt_want_str_op(hostname_out, OP_EQ, "onionrouter!");
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- UNMOCK(tor_gethostname);
- UNMOCK(tor_addr_lookup);
-
- tor_free(hostname_out);
-
- /*
- * CASE 4:
- * Given that options->Address is a local host address, we want
- * find_my_address() function to fail.
- */
-
- tor_addr_make_unspec(&resolved_addr);
- config_line_append(&options->Address, "Address", "::1");
- tor_addr_parse(&test_addr, "::1");
-
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(tor_addr_is_null(&resolved_addr) == 1);
- tt_want(retval == false);
-
- config_free_lines(options->Address);
- tor_free(hostname_out);
-
- /*
- * CASE 5:
- * We want find_my_address() to fail if DNS address in options->Address
- * cannot be resolved.
- */
-
- MOCK(tor_addr_lookup, tor_addr_lookup_failure);
-
- prev_n_hostname_failure = n_hostname_failure;
-
- config_line_append(&options->Address, "Address", "www.tor-project.org");
-
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(tor_addr_is_null(&resolved_addr) == 1);
- tt_want(retval == false);
+ tt_int_op(n_hostname_01010101, OP_EQ, ++prev_n_hostname_01010101);
+ VALIDATE_FOUND_ADDRESS(true, "RESOLVED", "www.torproject.org");
+ CLEANUP_FOUND_ADDRESS;
UNMOCK(tor_addr_lookup);
- config_free_lines(options->Address);
- options->Address = NULL;
- tor_free(hostname_out);
-
/*
- * CASE 6:
- * If options->Address is NULL AND gettting local hostname fails, we want
- * find_my_address() to fail as well.
+ * Case 3: Address is a local addressi (internal). Expected to fail.
*/
+ config_line_append(&options->Address, "Address", p->internal_ip);
- MOCK(tor_gethostname,tor_gethostname_failure);
-
- prev_n_gethostname_failure = n_gethostname_failure;
+ setup_full_capture_of_logs(LOG_NOTICE);
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_gethostname_failure == prev_n_gethostname_failure + 1);
- tt_want(tor_addr_is_null(&resolved_addr) == 1);
- tt_want(retval == false);
+ expect_log_msg_containing("is a private IP address. Tor relays that "
+ "use the default DirAuthorities must have "
+ "public IP addresses.");
+ teardown_capture_of_logs();
- UNMOCK(tor_gethostname);
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
/*
- * CASE 7:
- * We want find_my_address() to try and get network interface address via
- * get_interface_address() if hostname returned by tor_gethostname() cannot
- * be resolved into IP address.
+ * Case 4: Address is a local address but custom authorities. Expected to
+ * succeed.
*/
+ config_line_append(&options->Address, "Address", p->internal_ip);
+ options->DirAuthorities = tor_malloc_zero(sizeof(config_line_t));
+ tor_addr_parse(&test_addr, p->internal_ip);
- MOCK(tor_gethostname, tor_gethostname_replacement);
- MOCK(tor_addr_lookup, tor_addr_lookup_failure);
- MOCK(get_interface_address6, get_interface_address6_08080808);
-
- tor_addr_parse(&test_addr, "0808::0808");
-
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_get_interface_address6 = n_get_interface_address6;
-
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(retval == true);
- tt_want_int_op(n_gethostname_replacement, OP_EQ,
- prev_n_gethostname_replacement + 1);
- tt_want_int_op(n_get_interface_address6, OP_EQ,
- prev_n_get_interface_address6 + 1);
- tt_want_str_op(method_used, OP_EQ, "INTERFACE");
- tt_want(hostname_out == NULL);
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- UNMOCK(get_interface_address);
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+ CLEANUP_FOUND_ADDRESS;
/*
- * CASE 8:
- * Suppose options->Address is NULL AND hostname returned by
- * tor_gethostname() is unresolvable. We want find_my_address to fail if
- * get_interface_address() fails.
+ * Case 5: Multiple address in Address. Expected to fail.
*/
+ config_line_append(&options->Address, "Address", p->public_ip);
+ config_line_append(&options->Address, "Address", p->public_ip);
- MOCK(get_interface_address6, get_interface_address6_failure);
-
- prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
- prev_n_gethostname_replacement = n_gethostname_replacement;
+ setup_full_capture_of_logs(LOG_NOTICE);
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_get_interface_address6_failure ==
- prev_n_get_interface_address6_failure + 1);
- tt_want(n_gethostname_replacement ==
- prev_n_gethostname_replacement + 1);
- tt_want(retval == false);
+ expect_log_msg_containing("Found 2 Address statement of address family");
+ teardown_capture_of_logs();
- UNMOCK(get_interface_address);
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
/*
- * CASE 9:
- * Given that options->Address is NULL AND tor_addr_lookup()
- * fails AND hostname returned by gethostname() resolves
- * to local IP address, we want find_my_address() function to
- * call get_interface_address6(.,AF_INET6,.) and return IP address
- * the latter function has found.
+ * Case 6: Another address family is configured. Expected to fail.
*/
+ if (p->family == AF_INET) {
+ config_line_append(&options->Address, "Address", "4242::4242");
+ } else {
+ config_line_append(&options->Address, "Address", "1.1.1.1");
+ }
- MOCK(tor_addr_lookup, tor_addr_lookup_failure);
- MOCK(tor_gethostname, tor_gethostname_replacement);
- MOCK(get_interface_address6, get_interface_address6_08080808);
-
- tor_addr_parse(&test_addr, "0808::0808");
-
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_failure = n_hostname_failure;
- prev_n_get_interface_address6 = n_get_interface_address6;
+ setup_full_capture_of_logs(LOG_NOTICE);
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(last_address6_family == AF_INET6);
- tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(retval == true);
- tt_want_str_op(method_used, OP_EQ, "INTERFACE");
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- UNMOCK(tor_addr_lookup);
- UNMOCK(tor_gethostname);
- UNMOCK(get_interface_address6);
+ expect_log_msg_containing("No Address option found for family");
+ teardown_capture_of_logs();
- tor_free(hostname_out);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
/*
- * CASE 10: We want find_my_address() to fail if all of the following
- * are true:
- * 1. options->Address is not NULL
- * 2. ... but it cannot be converted to struct in_addr by
- * tor_inet_aton()
- * 3. ... and tor_addr_lookup() fails to resolve the
- * options->Address
+ * Case 7: Address is a non resolvable hostname. Expected to fail.
*/
-
MOCK(tor_addr_lookup, tor_addr_lookup_failure);
+ config_line_append(&options->Address, "Address", "www.torproject.org");
prev_n_hostname_failure = n_hostname_failure;
- config_line_append(&options->Address, "Address", "some_hostname");
+ setup_full_capture_of_logs(LOG_NOTICE);
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(retval == false);
+ expect_log_msg_containing("Could not resolve local Address "
+ "'www.torproject.org'. Failing.");
+ teardown_capture_of_logs();
- UNMOCK(tor_gethostname);
- UNMOCK(tor_addr_lookup);
+ tt_int_op(n_hostname_failure, OP_EQ, ++prev_n_hostname_failure);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
- tor_free(hostname_out);
+ UNMOCK(tor_addr_lookup);
/*
- * CASE 11:
- * Suppose the following sequence of events:
- * 1. options->Address is NULL
- * 2. tor_gethostname() succeeds to get hostname of machine Tor
- * if running on.
- * 3. Hostname from previous step cannot be converted to
- * address by using tor_inet_aton() function.
- * 4. However, tor_addr_lookup() succeeds in resolving the
- * hostname from step 2.
- * 5. Unfortunately, tor_addr_is_internal() deems this address
- * to be internal.
- * 6. get_interface_address6(.,AF_INET,.) returns non-internal
- * IPv4
+ * Case 8:
+ * 1. Address is NULL
+ * 2. Interface address is a valid address.
*
- * We want resolve_my_addr() to succeed with method "INTERFACE"
- * and address from step 6.
+ * Expected to succeed.
*/
-
- config_free_lines(options->Address);
options->Address = NULL;
- tor_addr_parse(&test_addr, "0808::0808");
+ tor_addr_parse(&test_addr, ret_get_interface_address6_08080808[p->idx]);
- MOCK(tor_gethostname, tor_gethostname_replacement);
- MOCK(tor_addr_lookup, tor_addr_lookup_localhost);
MOCK(get_interface_address6, get_interface_address6_08080808);
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_localhost = n_hostname_localhost;
prev_n_get_interface_address6 = n_get_interface_address6;
- retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
- tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
+ tt_int_op(n_get_interface_address6, OP_EQ, ++prev_n_get_interface_address6);
+ VALIDATE_FOUND_ADDRESS(true, "INTERFACE", NULL);
+ CLEANUP_FOUND_ADDRESS;
- tt_str_op(method_used, OP_EQ, "INTERFACE");
- tt_ptr_op(hostname_out, OP_EQ, NULL);
- tt_want(retval == true);
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
+ UNMOCK(get_interface_address6);
/*
- * CASE 11b:
- * 1-5 as above.
- * 6. get_interface_address6() fails.
+ * Case 9:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname resolves to a valid address.
*
- * In this subcase, we want find_my_address() to fail.
+ * Expected to succeed.
*/
+ options->Address = NULL;
+ tor_addr_parse(&test_addr, ret_addr_lookup_01010101[p->idx]);
- UNMOCK(get_interface_address6);
MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_replacement);
+ MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_localhost = n_hostname_localhost;
prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_hostname_01010101 = n_hostname_01010101;
+ prev_n_gethostname_replacement = n_gethostname_replacement;
- retval = find_my_address(options, AF_INET6, LOG_DEBUG, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
- tt_want(n_get_interface_address6_failure ==
- prev_n_get_interface_address6_failure + 1);
-
- tt_want(retval == false);
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_hostname_01010101, OP_EQ,
+ ++prev_n_hostname_01010101);
+ tt_int_op(n_gethostname_replacement, OP_EQ,
+ ++prev_n_gethostname_replacement);
+ VALIDATE_FOUND_ADDRESS(true, "GETHOSTNAME", "onionrouter!");
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(get_interface_address6);
UNMOCK(tor_gethostname);
UNMOCK(tor_addr_lookup);
- UNMOCK(get_interface_address6);
- /* CASE 12:
- * Suppose the following happens:
- * 1. options->Address is NULL AND options->DirAuthorities is non-NULL
- * 2. tor_gethostname() succeeds in getting hostname of a machine ...
- * 3. ... which is successfully parsed by tor_inet_aton() ...
- * 4. into IPv4 address that tor_addr_is_inernal() considers to be
- * internal.
+ /*
+ * Case 10:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname resolves to an internal address.
*
- * In this case, we want find_my_address() to fail.
+ * Expected to fail.
*/
-
- tor_free(options->Address);
options->Address = NULL;
- options->DirAuthorities = tor_malloc_zero(sizeof(config_line_t));
- MOCK(tor_gethostname,tor_gethostname_localhost);
+ MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_localhost);
+ MOCK(tor_addr_lookup, tor_addr_lookup_localhost);
+ prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_hostname_localhost = n_hostname_localhost;
prev_n_gethostname_localhost = n_gethostname_localhost;
- retval = find_my_address(options, AF_INET6, LOG_DEBUG, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_gethostname_localhost == prev_n_gethostname_localhost + 1);
- tt_want(retval == false);
-
- UNMOCK(tor_gethostname);
-
- done:
- config_free_lines(options->Address);
- tor_free(options->DirAuthorities);
- or_options_free(options);
- tor_free(hostname_out);
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_hostname_localhost, OP_EQ,
+ ++prev_n_hostname_localhost);
+ tt_int_op(n_gethostname_localhost, OP_EQ,
+ ++prev_n_gethostname_localhost);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
- UNMOCK(tor_gethostname);
- UNMOCK(tor_addr_lookup);
- UNMOCK(get_interface_address);
UNMOCK(get_interface_address6);
UNMOCK(tor_gethostname);
-}
-
-static void
-test_config_find_my_address_v4(void *arg)
-{
- or_options_t *options;
- tor_addr_t resolved_addr, test_addr;
- const char *method_used;
- char *hostname_out = NULL;
- bool retval;
- int prev_n_hostname_01010101;
- int prev_n_hostname_localhost;
- int prev_n_hostname_failure;
- int prev_n_gethostname_replacement;
- int prev_n_gethostname_failure;
- int prev_n_gethostname_localhost;
- int prev_n_get_interface_address6;
- int prev_n_get_interface_address6_failure;
-
- (void)arg;
-
- options = options_new();
-
- options_init(options);
-
- /*
- * CASE 1:
- * If options->Address is a valid IPv4 address string, we want
- * the corresponding address to be parsed and returned.
- */
- config_line_append(&options->Address, "Address", "128.52.128.105");
- tor_addr_parse(&test_addr, "128.52.128.105");
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(retval == true);
- tt_want_str_op(method_used,OP_EQ,"CONFIGURED");
- tt_want(hostname_out == NULL);
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- config_free_lines(options->Address);
-
-/*
- * CASE 2:
- * If options->Address is a valid DNS address, we want find_my_address()
- * function to ask tor_addr_lookup() for help with resolving it
- * and return the address that was resolved (in host order).
- */
-
- MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
-
- config_line_append(&options->Address, "Address", "www.torproject.org");
- tor_addr_parse(&test_addr, "1.1.1.1");
-
- prev_n_hostname_01010101 = n_hostname_01010101;
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(retval == true);
- tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
- tt_want_str_op(method_used,OP_EQ,"RESOLVED");
- tt_want_str_op(hostname_out,OP_EQ,"www.torproject.org");
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
UNMOCK(tor_addr_lookup);
- config_free_lines(options->Address);
- tor_free(hostname_out);
-
-/*
- * CASE 3:
- * Given that options->Address is NULL, we want find_my_address()
- * to try and use tor_gethostname() to get hostname AND use
- * tor_addr_lookup() to get IP address.
- */
-
- tor_addr_make_unspec(&resolved_addr);
- options->Address = NULL;
- tor_addr_parse(&test_addr, "1.1.1.1");
-
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(tor_addr_lookup,tor_addr_lookup_01010101);
-
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_01010101 = n_hostname_01010101;
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(retval == true);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
- tt_want_str_op(method_used,OP_EQ,"GETHOSTNAME");
- tt_want_str_op(hostname_out,OP_EQ,"onionrouter!");
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- UNMOCK(tor_gethostname);
- UNMOCK(tor_addr_lookup);
-
- tor_free(hostname_out);
-
-/*
- * CASE 4:
- * Given that options->Address is a local host address, we want
- * find_my_address() function to fail.
- */
-
- tor_addr_make_unspec(&resolved_addr);
- config_line_append(&options->Address, "Address", "127.0.0.1");
- tor_addr_parse(&test_addr, "127.0.0.1");
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(tor_addr_is_null(&resolved_addr) == 1);
- tt_want(retval == false);
-
- config_free_lines(options->Address);
- tor_free(hostname_out);
-
-/*
- * CASE 5:
- * We want find_my_address() to fail if DNS address in options->Address
- * cannot be resolved.
- */
-
- MOCK(tor_addr_lookup,tor_addr_lookup_failure);
-
- prev_n_hostname_failure = n_hostname_failure;
-
- config_line_append(&options->Address, "Address", "www.tor-project.org");
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(tor_addr_is_null(&resolved_addr) == 1);
- tt_want(retval == false);
-
- UNMOCK(tor_addr_lookup);
-
- config_free_lines(options->Address);
+ /*
+ * Case 11:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname fails to be found.
+ *
+ * Expected to fail.
+ */
options->Address = NULL;
- tor_free(hostname_out);
-
-/*
- * CASE 6:
- * If options->Address is NULL AND gettting local hostname fails, we want
- * find_my_address() to fail as well.
- */
-
- MOCK(tor_gethostname,tor_gethostname_failure);
-
- prev_n_gethostname_failure = n_gethostname_failure;
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(n_gethostname_failure == prev_n_gethostname_failure + 1);
- tt_want(tor_addr_is_null(&resolved_addr) == 1);
- tt_want(retval == false);
-
- UNMOCK(tor_gethostname);
- tor_free(hostname_out);
-
-/*
- * CASE 7:
- * We want find_my_address() to try and get network interface address via
- * get_interface_address() if hostname returned by tor_gethostname() cannot be
- * resolved into IP address.
- */
-
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(tor_addr_lookup,tor_addr_lookup_failure);
- MOCK(get_interface_address6, get_interface_address6_08080808);
-
- tor_addr_parse(&test_addr, "8.8.8.8");
-
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_get_interface_address6 = n_get_interface_address6;
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(retval == true);
- tt_want_int_op(n_gethostname_replacement, OP_EQ,
- prev_n_gethostname_replacement + 1);
- tt_want_int_op(n_get_interface_address6, OP_EQ,
- prev_n_get_interface_address6 + 1);
- tt_want_str_op(method_used,OP_EQ,"INTERFACE");
- tt_want(hostname_out == NULL);
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- UNMOCK(get_interface_address);
- tor_free(hostname_out);
-
-/*
- * CASE 8:
- * Suppose options->Address is NULL AND hostname returned by tor_gethostname()
- * is unresolvable. We want find_my_address to fail if
- * get_interface_address() fails.
- */
MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_failure);
prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
- prev_n_gethostname_replacement = n_gethostname_replacement;
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(n_get_interface_address6_failure ==
- prev_n_get_interface_address6_failure + 1);
- tt_want(n_gethostname_replacement ==
- prev_n_gethostname_replacement + 1);
- tt_want(retval == false);
-
- UNMOCK(get_interface_address);
- tor_free(hostname_out);
-
-/*
- * CASE 9:
- * Given that options->Address is NULL AND tor_addr_lookup()
- * fails AND hostname returned by gethostname() resolves
- * to local IP address, we want find_my_address() function to
- * call get_interface_address6(.,AF_INET,.) and return IP address
- * the latter function has found.
- */
-
- MOCK(tor_addr_lookup,tor_addr_lookup_failure);
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(get_interface_address6,get_interface_address6_replacement);
-
- tor_addr_parse(&test_addr, "9.9.9.9");
-
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_failure = n_hostname_failure;
- prev_n_get_interface_address6 = n_get_interface_address6;
+ prev_n_gethostname_failure = n_gethostname_failure;
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(last_address6_family == AF_INET);
- tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(retval == true);
- tt_want_str_op(method_used,OP_EQ,"INTERFACE");
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_gethostname_failure, OP_EQ,
+ ++prev_n_gethostname_failure);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
- UNMOCK(tor_addr_lookup);
- UNMOCK(tor_gethostname);
UNMOCK(get_interface_address6);
-
- tor_free(hostname_out);
-
- /*
- * CASE 10: We want find_my_address() to fail if all of the following
- * are true:
- * 1. options->Address is not NULL
- * 2. ... but it cannot be converted to struct in_addr by
- * tor_inet_aton()
- * 3. ... and tor_addr_lookup() fails to resolve the
- * options->Address
- */
-
- MOCK(tor_addr_lookup, tor_addr_lookup_failure);
-
- prev_n_hostname_failure = n_hostname_failure;
-
- config_line_append(&options->Address, "Address", "some_hostname");
-
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
- tt_want(retval == false);
-
UNMOCK(tor_gethostname);
- UNMOCK(tor_addr_lookup);
-
- tor_free(hostname_out);
/*
- * CASE 11:
- * Suppose the following sequence of events:
- * 1. options->Address is NULL
- * 2. tor_gethostname() succeeds to get hostname of machine Tor
- * if running on.
- * 3. Hostname from previous step cannot be converted to
- * address by using tor_inet_aton() function.
- * 4. However, tor_addr_lookup() succeeds in resolving the
- * hostname from step 2.
- * 5. Unfortunately, tor_addr_is_internal() deems this address
- * to be internal.
- * 6. get_interface_address6(.,AF_INET,.) returns non-internal
- * IPv4
+ * Case 12:
+ * 1. Address is NULL
+ * 2. Interface address fails to be found.
+ * 3. Local hostname can't be resolved.
*
- * We want resolve_my_addr() to succeed with method "INTERFACE"
- * and address from step 6.
+ * Expected to fail.
*/
-
- config_free_lines(options->Address);
options->Address = NULL;
- tor_addr_parse(&test_addr, "9.9.9.9");
- MOCK(tor_gethostname,tor_gethostname_replacement);
- MOCK(tor_addr_lookup,tor_addr_lookup_localhost);
- MOCK(get_interface_address6,get_interface_address6_replacement);
+ MOCK(get_interface_address6, get_interface_address6_failure);
+ MOCK(tor_gethostname, tor_gethostname_replacement);
+ MOCK(tor_addr_lookup, tor_addr_lookup_failure);
+ prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_localhost = n_hostname_localhost;
- prev_n_get_interface_address6 = n_get_interface_address6;
+ prev_n_hostname_failure = n_hostname_failure;
- retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
- tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
-
- tt_str_op(method_used,OP_EQ,"INTERFACE");
- tt_ptr_op(hostname_out, OP_EQ, NULL);
- tt_want(retval == true);
- tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
-
- /*
- * CASE 11b:
- * 1-5 as above.
- * 6. get_interface_address6() fails.
- *
- * In this subcase, we want find_my_address() to fail.
- */
+ tt_int_op(n_get_interface_address6_failure, OP_EQ,
+ ++prev_n_get_interface_address6_failure);
+ tt_int_op(n_gethostname_replacement, OP_EQ,
+ ++prev_n_gethostname_replacement);
+ tt_int_op(n_hostname_failure, OP_EQ,
+ ++prev_n_hostname_failure);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ CLEANUP_FOUND_ADDRESS;
UNMOCK(get_interface_address6);
- MOCK(get_interface_address6,get_interface_address6_failure);
-
- prev_n_gethostname_replacement = n_gethostname_replacement;
- prev_n_hostname_localhost = n_hostname_localhost;
- prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
-
- retval = find_my_address(options, AF_INET, LOG_DEBUG, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
- tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
- tt_want(n_get_interface_address6_failure ==
- prev_n_get_interface_address6_failure + 1);
-
- tt_want(retval == false);
-
UNMOCK(tor_gethostname);
UNMOCK(tor_addr_lookup);
- UNMOCK(get_interface_address6);
-
- /* CASE 12:
- * Suppose the following happens:
- * 1. options->Address is NULL AND options->DirAuthorities is non-NULL
- * 2. tor_gethostname() succeeds in getting hostname of a machine ...
- * 3. ... which is successfully parsed by tor_inet_aton() ...
- * 4. into IPv4 address that tor_addr_is_inernal() considers to be
- * internal.
- *
- * In this case, we want find_my_address() to fail.
- */
-
- tor_free(options->Address);
- options->Address = NULL;
- options->DirAuthorities = tor_malloc_zero(sizeof(config_line_t));
-
- MOCK(tor_gethostname,tor_gethostname_localhost);
-
- prev_n_gethostname_localhost = n_gethostname_localhost;
-
- retval = find_my_address(options, AF_INET, LOG_DEBUG, &resolved_addr,
- &method_used, &hostname_out);
-
- tt_want(n_gethostname_localhost == prev_n_gethostname_localhost + 1);
- tt_want(retval == false);
-
- UNMOCK(tor_gethostname);
done:
- config_free_lines(options->Address);
- tor_free(options->DirAuthorities);
or_options_free(options);
- tor_free(hostname_out);
UNMOCK(tor_gethostname);
UNMOCK(tor_addr_lookup);
- UNMOCK(get_interface_address);
UNMOCK(get_interface_address6);
- UNMOCK(tor_gethostname);
}
static void
@@ -6851,6 +6414,9 @@ test_config_getinfo_config_names(void *arg)
#define CONFIG_TEST(name, flags) \
{ #name, test_config_ ## name, flags, NULL, NULL }
+#define CONFIG_TEST_SETUP(suffix, name, flags, setup, setup_data) \
+ { #name#suffix, test_config_ ## name, flags, setup, setup_data }
+
struct testcase_t config_tests[] = {
CONFIG_TEST(adding_trusted_dir_server, TT_FORK),
CONFIG_TEST(adding_fallback_dir_server, TT_FORK),
@@ -6861,8 +6427,10 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(adding_dir_servers, TT_FORK),
CONFIG_TEST(default_dir_servers, TT_FORK),
CONFIG_TEST(default_fallback_dirs, 0),
- CONFIG_TEST(find_my_address_v4, TT_FORK),
- CONFIG_TEST(find_my_address_v6, TT_FORK),
+ CONFIG_TEST_SETUP(_v4, find_my_address, TT_FORK,
+ &passthrough_setup, &addr_param_v4),
+ CONFIG_TEST_SETUP(_v6, find_my_address, TT_FORK,
+ &passthrough_setup, &addr_param_v6),
CONFIG_TEST(find_my_address_mixed, TT_FORK),
CONFIG_TEST(addressmap, 0),
CONFIG_TEST(parse_bridge_line, 0),