[tor-commits] [tor/master] test: Unit tests for find_my_address() IPv6

nickm at torproject.org nickm at torproject.org
Wed Jul 1 20:27:24 UTC 2020


commit fe6b049651c3b3e968e339756e621815f4ae702c
Author: David Goulet <dgoulet at torproject.org>
Date:   Tue Jun 30 10:22:01 2020 -0400

    test: Unit tests for find_my_address() IPv6
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/test/test_config.c | 415 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 415 insertions(+)

diff --git a/src/test/test_config.c b/src/test/test_config.c
index fe102eea9..616145667 100644
--- 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;
 }
 
@@ -1119,7 +1131,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,6 +1187,402 @@ get_interface_address6_failure(int severity, sa_family_t family,
    return -1;
 }
 
+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_v4(void *arg)
 {
@@ -6246,6 +6660,7 @@ struct testcase_t config_tests[] = {
   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(addressmap, 0),
   CONFIG_TEST(parse_bridge_line, 0),
   CONFIG_TEST(parse_transport_options_line, 0),





More information about the tor-commits mailing list