Browse Source

Merge remote-tracking branch 'tor-github/pr/1393' into maint-0.4.2

Nick Mathewson 4 years ago
parent
commit
eebd2d44a1

+ 5 - 0
changes/ticket31841

@@ -0,0 +1,5 @@
+  o Minor features (testing):
+    - When running tests that attempt to look up hostname, replace the libc
+      name lookup functions with ones that do not actually touch the network.
+      This way, the tests complete more quickly in the presence of a slow or
+      missing DNS resolver. Closes ticket 31841.

+ 13 - 16
src/lib/net/resolve.c

@@ -8,6 +8,7 @@
  * \brief Use the libc DNS resolver to convert hostnames into addresses.
  **/
 
+#define RESOLVE_PRIVATE
 #include "lib/net/resolve.h"
 
 #include "lib/net/address.h"
@@ -70,10 +71,10 @@ tor_lookup_hostname,(const char *name, uint32_t *addr))
  *
  * See tor_addr_lookup() for details.
  */
-static int
-tor_addr_lookup_host_getaddrinfo(const char *name,
-                                 uint16_t family,
-                                 tor_addr_t *addr)
+MOCK_IMPL(STATIC int,
+tor_addr_lookup_host_impl,(const char *name,
+                          uint16_t family,
+                          tor_addr_t *addr))
 {
   int err;
   struct addrinfo *res=NULL, *res_p;
@@ -120,15 +121,17 @@ tor_addr_lookup_host_getaddrinfo(const char *name,
 
 #else /* !defined(HAVE_GETADDRINFO) */
 
-/* Host lookup helper for tor_addr_lookup(), which calls getaddrinfo().
- * Used when gethostbyname() is not available on this system.
+/* Host lookup helper for tor_addr_lookup(), which calls gethostbyname().
+ * Used when getaddrinfo() is not available on this system.
  *
  * See tor_addr_lookup() for details.
  */
-static int
-tor_addr_lookup_host_gethostbyname(const char *name,
-                                   tor_addr_t *addr)
+MOCK_IMPL(STATIC int,
+tor_addr_lookup_host_impl,(const char *name,
+                          uint16_t family,
+                           tor_addr_t *addr))
 {
+  (void) family;
   struct hostent *ent;
   int err;
 #ifdef HAVE_GETHOSTBYNAME_R_6_ARG
@@ -170,7 +173,6 @@ tor_addr_lookup_host_gethostbyname(const char *name,
   return (err == TRY_AGAIN) ? 1 : -1;
 #endif
 }
-
 #endif /* defined(HAVE_GETADDRINFO) */
 
 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
@@ -215,13 +217,8 @@ tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
   } else {
     /* Clear the address after a failed tor_addr_parse(). */
     memset(addr, 0, sizeof(tor_addr_t));
-#ifdef HAVE_GETADDRINFO
-    result = tor_addr_lookup_host_getaddrinfo(name, family, addr);
+    result = tor_addr_lookup_host_impl(name, family, addr);
     goto done;
-#else /* !(defined(HAVE_GETADDRINFO)) */
-    result = tor_addr_lookup_host_gethostbyname(name, addr);
-    goto done;
-#endif /* defined(HAVE_GETADDRINFO) */
   }
 
  /* If we weren't successful, and haven't already set the result,

+ 15 - 0
src/lib/net/resolve.h

@@ -24,12 +24,18 @@
 
 struct tor_addr_t;
 
+/*
+ * Primary lookup functions.
+ */
 MOCK_DECL(int, tor_lookup_hostname,(const char *name, uint32_t *addr));
 MOCK_DECL(int, tor_addr_lookup,(const char *name, uint16_t family,
                                 struct tor_addr_t *addr_out));
 int tor_addr_port_lookup(const char *s, struct tor_addr_t *addr_out,
                          uint16_t *port_out);
 
+/*
+ * Sandbox helpers
+ */
 struct addrinfo;
 #ifdef USE_SANDBOX_GETADDRINFO
 /** Pre-calls getaddrinfo in order to pre-record result. */
@@ -55,4 +61,13 @@ void tor_free_getaddrinfo_cache(void);
 void sandbox_disable_getaddrinfo_cache(void);
 void tor_make_getaddrinfo_cache_active(void);
 
+/*
+ * Internal resolver wrapper; exposed for mocking.
+ */
+#ifdef RESOLVE_PRIVATE
+MOCK_DECL(STATIC int, tor_addr_lookup_host_impl, (const char *name,
+                                                  uint16_t family,
+                                                  struct tor_addr_t *addr));
+#endif
+
 #endif /* !defined(TOR_RESOLVE_H) */

+ 2 - 0
src/test/include.am

@@ -102,6 +102,7 @@ src_test_test_SOURCES += \
 	src/test/log_test_helpers.c \
 	src/test/hs_test_helpers.c \
 	src/test/rend_test_helpers.c \
+	src/test/resolve_test_helpers.c \
 	src/test/rng_test_helpers.c \
 	src/test/test.c \
 	src/test/test_accounting.c \
@@ -341,6 +342,7 @@ noinst_HEADERS+= \
 	src/test/hs_test_helpers.h \
 	src/test/log_test_helpers.h \
 	src/test/rend_test_helpers.h \
+	src/test/resolve_test_helpers.h \
 	src/test/rng_test_helpers.h \
 	src/test/test.h \
 	src/test/ptr_helpers.h \

+ 85 - 0
src/test/resolve_test_helpers.c

@@ -0,0 +1,85 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file resolve_test_helpers.c
+ * @brief Helper functions for mocking libc's blocking hostname lookup
+ *   facilities.
+ **/
+
+#define RESOLVE_PRIVATE
+#include "orconfig.h"
+#include "test/resolve_test_helpers.h"
+#include "lib/net/address.h"
+#include "lib/net/resolve.h"
+#include "test/test.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * Mock replacement for our getaddrinfo/gethostbyname wrapper.
+ **/
+static int
+replacement_host_lookup(const char *name, uint16_t family, tor_addr_t *addr)
+{
+  static const struct lookup_table_ent {
+    const char *name;
+    const char *ipv4;
+    const char *ipv6;
+  } entries[] = {
+    { "localhost", "127.0.0.1", "::1" },
+    { "torproject.org", "198.51.100.6", "2001:DB8::700" },
+    { NULL, NULL, NULL },
+  };
+
+  int r = -1;
+
+  for (unsigned i = 0; entries[i].name != NULL; ++i) {
+    if (!strcasecmp(name, entries[i].name)) {
+      if (family == AF_INET6) {
+        int s = tor_addr_parse(addr, entries[i].ipv6);
+        tt_int_op(s, OP_EQ, AF_INET6);
+      } else {
+        int s = tor_addr_parse(addr, entries[i].ipv4);
+        tt_int_op(s, OP_EQ, AF_INET);
+      }
+      r = 0;
+      break;
+    }
+  }
+
+  log_debug(LD_GENERAL, "resolve(%s,%d) => %s",
+            name, family, r == 0 ? fmt_addr(addr) : "-1");
+
+  return r;
+ done:
+  return -1;
+}
+
+/**
+ * Set up a mock replacement for our wrapper on libc's resolver code.
+ *
+ * According to our replacement, only "localhost" and "torproject.org"
+ * are real addresses; everything else doesn't exist.
+ *
+ * Use this function to avoid using the DNS resolver during unit tests;
+ * call unmock_hostname_resolver() when you're done.
+ **/
+void
+mock_hostname_resolver(void)
+{
+  MOCK(tor_addr_lookup_host_impl, replacement_host_lookup);
+}
+
+/**
+ * Unmock our wrappers for libc's blocking hostname resolver code.
+ **/
+void
+unmock_hostname_resolver(void)
+{
+  UNMOCK(tor_addr_lookup_host_impl);
+}

+ 18 - 0
src/test/resolve_test_helpers.h

@@ -0,0 +1,18 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file resolve_test_helpers.h
+ * @brief Header for test/resolve_test_helpers.c
+ **/
+
+#ifndef TOR_TEST_RESOLVE_TEST_HELPERS_H
+#define TOR_TEST_RESOLVE_TEST_HELPERS_H
+
+void mock_hostname_resolver(void);
+void unmock_hostname_resolver(void);
+
+#endif /* !defined(TOR_TEST_RESOLVE_TEST_HELPERS_H) */

+ 5 - 1
src/test/test_addr.c

@@ -12,6 +12,7 @@
 #include "test/log_test_helpers.h"
 #include "lib/net/resolve.h"
 #include "test/rng_test_helpers.h"
+#include "test/resolve_test_helpers.h"
 
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
@@ -1160,6 +1161,7 @@ test_addr_parse_canonical(void *arg)
 static void
 test_addr_parse(void *arg)
 {
+
   int r;
   tor_addr_t addr;
   uint16_t port;
@@ -1169,6 +1171,8 @@ test_addr_parse(void *arg)
 
   (void)arg;
 
+  mock_hostname_resolver();
+
   /* IPv6-mapped IPv4 addresses. Tor doesn't really use these. */
   TEST_ADDR_V6_PARSE("11:22:33:44:55:66:1.2.3.4", 0,
                      "11:22:33:44:55:66:102:304");
@@ -1273,7 +1277,7 @@ test_addr_parse(void *arg)
                            "11:22::88",99);
 
  done:
-  ;
+  unmock_hostname_resolver();
 }
 
 static void

+ 4 - 0
src/test/test_config.c

@@ -45,6 +45,7 @@
 #include "app/config/statefile.h"
 
 #include "test/test_helpers.h"
+#include "test/resolve_test_helpers.h"
 
 #include "feature/dirclient/dir_server_st.h"
 #include "core/or/port_cfg_st.h"
@@ -4068,6 +4069,8 @@ test_config_parse_port_config__ports__ports_given(void *data)
 
   slout = smartlist_new();
 
+  mock_hostname_resolver();
+
   // Test error when encounters an invalid Port specification
   config_port_invalid = mock_config_line("DNSPort", "");
   ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
@@ -4764,6 +4767,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
 #endif /* defined(_WIN32) */
 
  done:
+  unmock_hostname_resolver();
   if (slout)
     SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
   smartlist_free(slout);

+ 5 - 3
src/test/test_hs_config.c

@@ -12,6 +12,7 @@
 #include "test/test.h"
 #include "test/test_helpers.h"
 #include "test/log_test_helpers.h"
+#include "test/resolve_test_helpers.h"
 
 #include "app/config/config.h"
 #include "feature/hs/hs_common.h"
@@ -272,6 +273,7 @@ test_valid_service_v2(void *arg)
   int ret;
 
   (void) arg;
+  mock_hostname_resolver();
 
   /* Valid complex configuration. Basic client authorization. */
   {
@@ -314,7 +316,7 @@ test_valid_service_v2(void *arg)
   }
 
  done:
-  ;
+  unmock_hostname_resolver();
 }
 
 static void
@@ -392,6 +394,7 @@ test_valid_service_v3(void *arg)
   int ret;
 
   (void) arg;
+  mock_hostname_resolver();
 
   /* Valid complex configuration. */
   {
@@ -448,7 +451,7 @@ test_valid_service_v3(void *arg)
   }
 
  done:
-  ;
+  unmock_hostname_resolver();
 }
 
 static void
@@ -623,4 +626,3 @@ struct testcase_t hs_config_tests[] = {
 
   END_OF_TESTCASES
 };
-

+ 3 - 0
src/test/test_options.c

@@ -14,6 +14,7 @@
 #include "feature/nodelist/routerset.h"
 #include "core/mainloop/mainloop.h"
 #include "test/log_test_helpers.h"
+#include "test/resolve_test_helpers.h"
 
 #include "lib/sandbox/sandbox.h"
 #include "lib/memarea/memarea.h"
@@ -241,6 +242,7 @@ test_options_validate(void *arg)
   (void)arg;
   setup_log_callback();
   sandbox_disable_getaddrinfo_cache();
+  mock_hostname_resolver();
 
   WANT_ERR("ExtORPort 500000", "Invalid ExtORPort", PH_VALIDATE);
 
@@ -282,6 +284,7 @@ test_options_validate(void *arg)
 
   close_temp_logs();
   clear_log_messages();
+  unmock_hostname_resolver();
   return;
 }