tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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:
Msrc/app/config/resolve_addr.c | 12+++++++++---
Msrc/test/test_config.c | 622++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
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),