commit 538b25241e9f2112e3a56449ba07c08f265f22f9
parent f152d5b15f50972c69021f386a806587d91a0654
Author: Nick Mathewson <nickm@torproject.org>
Date: Wed, 1 Jul 2020 16:27:12 -0400
Merge remote-tracking branch 'dgoulet/ticket33235_045_01'
Diffstat:
2 files changed, 629 insertions(+), 5 deletions(-)
diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c
@@ -193,6 +193,10 @@ get_address_from_config(const or_options_t *options, int warn_severity,
explicit_ip = true;
num_valid_addr++;
continue;
+ } else if (af != -1) {
+ /* Parsable address but just not the one from the family we want. Skip
+ * it so we don't attempt a resolve. */
+ continue;
}
/* Not an IP address. Considering this value a hostname and attempting to
@@ -208,7 +212,7 @@ get_address_from_config(const or_options_t *options, int warn_severity,
/* Hostname that can't be resolved, this is a fatal error. */
log_fn(warn_severity, LD_CONFIG,
"Could not resolve local Address '%s'. Failing.", cfg->value);
- return FN_RET_BAIL;
+ continue;
}
}
@@ -216,8 +220,10 @@ get_address_from_config(const or_options_t *options, int warn_severity,
log_fn(warn_severity, LD_CONFIG,
"No Address option found for family %s in configuration.",
fmt_af_family(family));
- /* No Address statement for family, inform caller to try next method. */
- return FN_RET_NEXT;
+ /* No Address statement for family but one exists since Address is not
+ * NULL thus we have to stop now and not attempt to send back a guessed
+ * address. */
+ return FN_RET_BAIL;
}
if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
diff --git a/src/test/test_config.c b/src/test/test_config.c
@@ -1004,7 +1004,13 @@ tor_addr_lookup_01010101(const char *name, uint16_t family, tor_addr_t *addr)
if (name && addr) {
tor_addr_from_ipv4h(addr, 0x01010101);
}
+ } else if (family == AF_INET6) {
+ if (name && addr) {
+ int ret = tor_addr_parse(addr, "0101::0101");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ }
}
+ done:
return 0;
}
@@ -1024,7 +1030,13 @@ tor_addr_lookup_localhost(const char *name, uint16_t family, tor_addr_t *addr)
if (name && addr) {
tor_addr_from_ipv4h(addr, 0x7f000001);
}
+ } else if (family == AF_INET6) {
+ if (name && addr) {
+ int ret = tor_addr_parse(addr, "::1");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ }
}
+ done:
return 0;
}
@@ -1046,6 +1058,46 @@ tor_addr_lookup_failure(const char *name, uint16_t family, tor_addr_t *addr)
return -1;
}
+/** Mock function for tor_addr_lookup().
+ *
+ * Depending on the given hostname and family, resolve either to IPv4 or IPv6.
+ *
+ * If the requested hostname family is not the same as the family provided, an
+ * error is returned.
+ *
+ * Possible hostnames:
+ * - www.torproject.org.v4 for IPv4 -> 1.1.1.1
+ * - www.torproject.org.v6 for IPv6 -> [0101::0101]
+ */
+static int
+tor_addr_lookup_mixed(const char *name, uint16_t family, tor_addr_t *addr)
+{
+ tt_assert(addr);
+ tt_assert(name);
+
+ if (!strcmp(name, "www.torproject.org.v4")) {
+ if (family == AF_INET) {
+ tor_addr_from_ipv4h(addr, 0x01010101);
+ return 0;
+ }
+ /* Resolving AF_INET but the asked family is different. Failure. */
+ return -1;
+ }
+
+ if (!strcmp(name, "www.torproject.org.v6")) {
+ if (family == AF_INET6) {
+ int ret = tor_addr_parse(addr, "0101::0101");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ return 0;
+ }
+ /* Resolving AF_INET6 but the asked family is not. Failure. */
+ return -1;
+ }
+
+ done:
+ return 0;
+}
+
static int n_gethostname_replacement = 0;
/** This mock function is meant to replace tor_gethostname(). It
@@ -1119,7 +1171,13 @@ get_interface_address6_08080808(int severity, sa_family_t family,
if (addr) {
tor_addr_from_ipv4h(addr, 0x08080808);
}
+ } else if (family == AF_INET6) {
+ if (addr) {
+ int ret = tor_addr_parse(addr, "0808::0808");
+ tt_int_op(ret, OP_EQ, AF_INET6);
+ }
}
+ done:
return 0;
}
@@ -1169,8 +1227,566 @@ get_interface_address6_failure(int severity, sa_family_t family,
return -1;
}
+/** Helper macro: to validate the returned value from find_my_address() so we
+ * don't copy those all the time. */
+#undef VALIDATE_FOUND_ADDRESS
+#define VALIDATE_FOUND_ADDRESS(ret, method, hostname) \
+ do { \
+ tt_int_op(retval, OP_EQ, ret); \
+ if (method == NULL) tt_assert(!method_used); \
+ else tt_str_op(method_used, OP_EQ, method); \
+ if (hostname == NULL) tt_assert(!hostname_out); \
+ else tt_str_op(hostname_out, OP_EQ, hostname); \
+ if (ret == true) { \
+ tt_assert(tor_addr_eq(&resolved_addr, &test_addr)); \
+ } \
+ } while (0)
+
+/** Helper macro: Cleanup the address and variables used after a
+ * find_my_address() call. */
+#undef CLEANUP_FOUND_ADDRESS
+#define CLEANUP_FOUND_ADDRESS \
+ do { \
+ config_free_lines(options->Address); \
+ tor_free(options->DirAuthorities); \
+ tor_free(hostname_out); \
+ tor_addr_make_unspec(&resolved_addr); \
+ tor_addr_make_unspec(&test_addr); \
+ } while (0)
+
+/** Test both IPv4 and IPv6 coexisting together in the configuration. */
+static void
+test_config_find_my_address_mixed(void *arg)
+{
+ or_options_t *options;
+ tor_addr_t resolved_addr, test_addr;
+ const char *method_used;
+ char *hostname_out = NULL;
+ bool retval;
+
+ (void)arg;
+
+ options = options_new();
+
+ options_init(options);
+
+ /*
+ * CASE 1: Only IPv6 address. Accepted.
+ */
+ 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");
+
+ /* IPv4 address not guessed since one Address statement exists. */
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
+ /* IPv6 address should be found and considered configured. */
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+
+ CLEANUP_FOUND_ADDRESS;
+
+ /*
+ * Case 2: IPv4 _and_ IPv6 given. Accepted.
+ */
+ config_line_append(&options->Address, "Address",
+ "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
+ config_line_append(&options->Address, "Address", "1.1.1.1");
+ tor_addr_parse(&test_addr, "1.1.1.1");
+
+ /* IPv4 address should be found and considered configured. */
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+
+ /* IPv6 address should be found and considered configured. */
+ tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+
+ CLEANUP_FOUND_ADDRESS;
+
+ /*
+ * Case 3: Two hostnames, IPv4 and IPv6.
+ */
+ config_line_append(&options->Address, "Address", "www.torproject.org.v4");
+ config_line_append(&options->Address, "Address", "www.torproject.org.v6");
+
+ /* Looks at specific hostname to learn which address family to use. */
+ MOCK(tor_addr_lookup, tor_addr_lookup_mixed);
+
+ /* IPv4 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "1.1.1.1");
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "RESOLVED", "www.torproject.org.v4");
+
+ /* IPv6 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "0101::0101");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "RESOLVED", "www.torproject.org.v6");
+
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(tor_addr_lookup);
+
+ /*
+ * Case 4: IPv4 address and a hostname resolving to IPV6.
+ */
+ config_line_append(&options->Address, "Address", "1.1.1.1");
+ config_line_append(&options->Address, "Address", "www.torproject.org.v6");
+
+ /* Looks at specific hostname to learn which address family to use. */
+ MOCK(tor_addr_lookup, tor_addr_lookup_mixed);
+
+ /* IPv4 address should be found and configured. */
+ tor_addr_parse(&test_addr, "1.1.1.1");
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+
+ /* IPv6 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "0101::0101");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "RESOLVED", "www.torproject.org.v6");
+
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(tor_addr_lookup);
+
+ /*
+ * Case 5: Hostname resolving to IPv4 and an IPv6 address.
+ */
+ config_line_append(&options->Address, "Address", "0101::0101");
+ config_line_append(&options->Address, "Address", "www.torproject.org.v4");
+
+ /* Looks at specific hostname to learn which address family to use. */
+ MOCK(tor_addr_lookup, tor_addr_lookup_mixed);
+
+ /* IPv4 address should be found and resolved. */
+ tor_addr_parse(&test_addr, "1.1.1.1");
+ retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "RESOLVED", "www.torproject.org.v4");
+
+ /* IPv6 address should be found and considered resolved. */
+ tor_addr_parse(&test_addr, "0101::0101");
+ retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
+ &method_used, &hostname_out);
+ VALIDATE_FOUND_ADDRESS(true, "CONFIGURED", NULL);
+
+ CLEANUP_FOUND_ADDRESS;
+ UNMOCK(tor_addr_lookup);
+
+ done:
+ config_free_lines(options->Address);
+ or_options_free(options);
+ tor_free(hostname_out);
+
+ UNMOCK(tor_addr_lookup);
+}
+
+static void
+test_config_find_my_address_v6(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 IPv6 address string, we want
+ * the corresponding address to be parsed and returned.
+ */
+ 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");
+
+ retval = find_my_address(options, AF_INET6, 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, "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);
+
+ 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,
+ &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);
+ 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_INET6, 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, "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,
+ &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);
+
+ prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
+ prev_n_gethostname_replacement = n_gethostname_replacement;
+
+ retval = find_my_address(options, AF_INET6, 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_INET6,.) 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_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;
+
+ retval = find_my_address(options, AF_INET6, 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);
+
+ 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_INET6, 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
+ *
+ * We want resolve_my_addr() to succeed with method "INTERFACE"
+ * and address from step 6.
+ */
+
+ config_free_lines(options->Address);
+ options->Address = NULL;
+ tor_addr_parse(&test_addr, "0808::0808");
+
+ 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,
+ &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.
+ */
+
+ 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_INET6, 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_INET6, 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
-test_config_find_my_address(void *arg)
+test_config_find_my_address_v4(void *arg)
{
or_options_t *options;
tor_addr_t resolved_addr, test_addr;
@@ -6245,7 +6861,9 @@ 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, TT_FORK),
+ CONFIG_TEST(find_my_address_v4, TT_FORK),
+ CONFIG_TEST(find_my_address_v6, TT_FORK),
+ CONFIG_TEST(find_my_address_mixed, TT_FORK),
CONFIG_TEST(addressmap, 0),
CONFIG_TEST(parse_bridge_line, 0),
CONFIG_TEST(parse_transport_options_line, 0),