You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2020/06/29 22:43:01 UTC

[trafficserver] branch 9.0.x updated: ip_resolve - Make config variable overridable

This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 416cb64  ip_resolve - Make config variable overridable
416cb64 is described below

commit 416cb64686443f708c221fe4f39b476d18f52ee2
Author: Damian Meden <da...@verizonmedia.com>
AuthorDate: Mon May 11 18:38:02 2020 +0100

    ip_resolve - Make config variable overridable
    
    (cherry picked from commit f0f54e979a9af0478644fbdb262a99d281024347)
---
 doc/admin-guide/files/records.config.en.rst        |  1 +
 .../api/functions/TSHttpOverridableConfig.en.rst   |  1 +
 .../api/types/TSOverridableConfigKey.en.rst        |  1 +
 include/ts/apidefs.h.in                            |  1 +
 include/tscore/ink_resolver.h                      | 14 +++-
 plugins/lua/ts_lua_http_config.c                   |  2 +
 proxy/http/HttpConfig.cc                           |  3 +
 proxy/http/HttpConfig.h                            |  5 ++
 proxy/http/HttpSM.cc                               | 23 ++++---
 proxy/http/HttpTransact.cc                         | 12 +++-
 proxy/http/HttpTransact.h                          |  7 +-
 src/shared/overridable_txn_vars.cc                 |  3 +-
 src/traffic_server/InkAPI.cc                       |  9 +++
 src/traffic_server/InkAPITest.cc                   |  3 +-
 src/tscore/ink_res_mkquery.cc                      | 14 ++--
 .../gold_tests/remap/gold/remap-DNS-ipv6-200.gold  | 14 ++++
 tests/gold_tests/remap/gold/remap-ip-resolve.gold  | 14 ++++
 tests/gold_tests/remap/remap_ip_resolve.test.py    | 79 ++++++++++++++++++++++
 18 files changed, 184 insertions(+), 22 deletions(-)

diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 978cb0b..5d33652 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -2656,6 +2656,7 @@ HostDB
    of partitions
 
 .. ts:cv:: CONFIG proxy.config.hostdb.ip_resolve STRING NULL
+   :overridable:
 
    Set the host resolution style.
 
diff --git a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
index 2af73e2..0d4a2e5 100644
--- a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
+++ b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
@@ -186,6 +186,7 @@ TSOverridableConfigKey Value                                        Configuratio
 :c:macro:`TS_CONFIG_SSL_CLIENT_CERT_FILENAME`                       :ts:cv:`proxy.config.ssl.client.cert.filename`
 :c:macro:`TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME`                :ts:cv:`proxy.config.ssl.client.private_key.filename`
 :c:macro:`TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME`                    :ts:cv:`proxy.config.ssl.client.CA.cert.filename`
+:c:macro:`TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE`                :ts:cv:`proxy.config.hostdb.ip_resolve`
 ==================================================================  ====================================================================
 
 Examples
diff --git a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
index d24b1a2..a17c791 100644
--- a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
+++ b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
@@ -153,6 +153,7 @@ Enumeration Members
    .. c:macro:: TS_CONFIG_SSL_CLIENT_SNI_POLICY
    .. c:macro:: TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME
    .. c:macro:: TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME
+   .. c:macro:: TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE
 
 
 Description
diff --git a/include/ts/apidefs.h.in b/include/ts/apidefs.h.in
index 7d97601..b2bf281 100644
--- a/include/ts/apidefs.h.in
+++ b/include/ts/apidefs.h.in
@@ -800,6 +800,7 @@ typedef enum {
   TS_CONFIG_SSL_CLIENT_SNI_POLICY,
   TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME,
   TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME,
+  TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE,
   TS_CONFIG_LAST_ENTRY
 } TSOverridableConfigKey;
 
diff --git a/include/tscore/ink_resolver.h b/include/tscore/ink_resolver.h
index 0969fa7..394e121 100644
--- a/include/tscore/ink_resolver.h
+++ b/include/tscore/ink_resolver.h
@@ -185,8 +185,6 @@ extern const char *const HOST_RES_STYLE_STRING[];
 extern HostResStyle ats_host_res_from(int family,                    ///< Connection family
                                       HostResPreferenceOrder const & ///< Preference ordering.
 );
-/// Calculate the host resolution style to force a family match to @a addr.
-extern HostResStyle ats_host_res_match(sockaddr const *addr);
 
 /** Parse a host resolution configuration string.
  */
@@ -194,6 +192,18 @@ extern void parse_host_res_preference(const char *value,           ///< [in] Con
                                       HostResPreferenceOrder order /// [out] Order to update.
 );
 
+/// Configure the preference order to hold only what's from the client address.
+/// @addr[in] client's address.
+/// @order[out] Order to update
+extern void ats_force_order_by_family(sockaddr const *addr, HostResPreferenceOrder order);
+
+// Domain resolution priority for origin.
+struct HostResData {
+  HostResPreferenceOrder order;
+  // keep the configuration value to satisfy the API(TSHttpTxnConfigStringSet)
+  char *conf_value{nullptr};
+};
+
 #ifndef NS_GET16
 #define NS_GET16(s, cp)                                                  \
   do {                                                                   \
diff --git a/plugins/lua/ts_lua_http_config.c b/plugins/lua/ts_lua_http_config.c
index dd72d14..d9738be 100644
--- a/plugins/lua/ts_lua_http_config.c
+++ b/plugins/lua/ts_lua_http_config.c
@@ -136,6 +136,7 @@ typedef enum {
   TS_LUA_CONFIG_SSL_CLIENT_SNI_POLICY                         = TS_CONFIG_SSL_CLIENT_SNI_POLICY,
   TS_LUA_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME               = TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME,
   TS_LUA_CONFIG_SSL_CLIENT_CA_CERT_FILENAME                   = TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME,
+  TS_LUA_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE               = TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE,
   TS_LUA_CONFIG_LAST_ENTRY                                    = TS_CONFIG_LAST_ENTRY,
 } TSLuaOverridableConfigKey;
 
@@ -261,6 +262,7 @@ ts_lua_var_item ts_lua_http_config_vars[] = {
   TS_LUA_MAKE_VAR_ITEM(TS_CONFIG_SSL_CLIENT_SNI_POLICY),
   TS_LUA_MAKE_VAR_ITEM(TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME),
   TS_LUA_MAKE_VAR_ITEM(TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME),
+  TS_LUA_MAKE_VAR_ITEM(TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE),
   TS_LUA_MAKE_VAR_ITEM(TS_CONFIG_HTTP_SERVER_MIN_KEEP_ALIVE_CONNS),
   TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_HTTP_PER_SERVER_CONNECTION_MAX),
   TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_HTTP_PER_SERVER_CONNECTION_MATCH),
diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc
index 59adba3..5877bc5 100644
--- a/proxy/http/HttpConfig.cc
+++ b/proxy/http/HttpConfig.cc
@@ -1591,6 +1591,9 @@ HttpConfig::reconfigure()
 
   params->negative_caching_list = m_master.negative_caching_list;
 
+  params->oride.host_res_data            = m_master.oride.host_res_data;
+  params->oride.host_res_data.conf_value = ats_strdup(m_master.oride.host_res_data.conf_value);
+
   m_id = configProcessor.set(m_id, params);
 }
 
diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h
index 6ee850b..c7ba480 100644
--- a/proxy/http/HttpConfig.h
+++ b/proxy/http/HttpConfig.h
@@ -44,6 +44,7 @@
 
 #include "tscore/ink_platform.h"
 #include "tscore/ink_inet.h"
+#include "tscore/ink_resolver.h"
 #include "tscore/IpMap.h"
 #include "tscore/Regex.h"
 #include "string_view"
@@ -685,6 +686,9 @@ struct OverridableHttpConfigParams {
   char *ssl_client_cert_filename        = nullptr;
   char *ssl_client_private_key_filename = nullptr;
   char *ssl_client_ca_cert_filename     = nullptr;
+
+  // Host Resolution order
+  HostResData host_res_data;
 };
 
 /////////////////////////////////////////////////////////////
@@ -864,6 +868,7 @@ inline HttpConfigParams::~HttpConfigParams()
   ats_free(reverse_proxy_no_host_redirect);
   ats_free(redirect_actions_string);
   ats_free(oride.ssl_client_sni_policy);
+  ats_free(oride.host_res_data.conf_value);
 
   delete connect_ports;
   delete redirect_actions_map;
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 105180b..775a6f9 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -496,11 +496,15 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc, IOBufferReader *buffe
     debug_on = true;
   }
 
+  t_state.setup_per_txn_configs();
+
   ink_assert(ua_txn->get_proxy_ssn());
   ink_assert(ua_txn->get_proxy_ssn()->accept_options);
-  // default the upstream IP style host resolution from inbound
-  t_state.dns_info.host_res_style =
-    ats_host_res_from(netvc->get_local_addr()->sa_family, ua_txn->get_proxy_ssn()->accept_options->host_res_preference);
+
+  // default the upstream IP style host resolution order from inbound
+  std::copy(std::begin(ua_txn->get_proxy_ssn()->accept_options->host_res_preference),
+            std::end(ua_txn->get_proxy_ssn()->accept_options->host_res_preference),
+            std::begin(t_state.my_txn_conf().host_res_data.order));
 
   start_sub_sm();
 
@@ -2237,7 +2241,6 @@ int
 HttpSM::state_hostdb_lookup(int event, void *data)
 {
   STATE_ENTER(&HttpSM::state_hostdb_lookup, event);
-
   //    ink_assert (m_origin_server_vc == 0);
   // REQ_FLAVOR_SCHEDULED_UPDATE can be transformed into
   // REQ_FLAVOR_REVPROXY
@@ -2260,7 +2263,7 @@ HttpSM::state_hostdb_lookup(int event, void *data)
     opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing) ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS :
                                                                                  HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD;
     opt.timeout        = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
-    opt.host_res_style = t_state.dns_info.host_res_style;
+    opt.host_res_style = ats_host_res_from(ua_txn->get_netvc()->get_local_addr()->sa_family, t_state.txn_conf->host_res_data.order);
 
     Action *dns_lookup_action_handle =
       hostDBProcessor.getbyname_imm(this, (cb_process_result_pfn)&HttpSM::process_hostdb_info, host_name, 0, opt);
@@ -4087,8 +4090,9 @@ HttpSM::do_hostdb_lookup()
                                                             t_state.hdr_info.client_request.port_get();
       opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing) ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS :
                                                                                    HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD;
-      opt.timeout        = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
-      opt.host_res_style = t_state.dns_info.host_res_style;
+      opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
+      opt.host_res_style =
+        ats_host_res_from(ua_txn->get_netvc()->get_local_addr()->sa_family, t_state.txn_conf->host_res_data.order);
 
       Action *dns_lookup_action_handle =
         hostDBProcessor.getbyname_imm(this, (cb_process_result_pfn)&HttpSM::process_hostdb_info, host_name, 0, opt);
@@ -4122,8 +4126,9 @@ HttpSM::do_hostdb_lookup()
     opt.port  = server_port;
     opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing) ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS :
                                                                                  HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD;
-    opt.timeout        = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
-    opt.host_res_style = t_state.dns_info.host_res_style;
+    opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
+
+    opt.host_res_style = ats_host_res_from(ua_txn->get_netvc()->get_local_addr()->sa_family, t_state.txn_conf->host_res_data.order);
 
     Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this, (cb_process_result_pfn)&HttpSM::process_hostdb_info,
                                                                      t_state.dns_info.lookup_name, 0, opt);
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 710d822..241d90e 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -46,6 +46,16 @@
 #include "../IPAllow.h"
 #include "I_Machine.h"
 
+// Support ip_resolve override.
+const MgmtConverter HttpTransact::HOST_RES_CONV{[](const void *data) -> std::string_view {
+                                                  const HostResData *host_res_data = static_cast<const HostResData *>(data);
+                                                  return host_res_data->conf_value;
+                                                },
+                                                [](void *data, std::string_view src) -> void {
+                                                  HostResData *res_data = static_cast<HostResData *>(data);
+                                                  parse_host_res_preference(src.data(), res_data->order);
+                                                }};
+
 static char range_type[] = "multipart/byteranges; boundary=RANGE_SEPARATOR";
 #define RANGE_NUMBERS_LENGTH 60
 
@@ -3750,7 +3760,7 @@ HttpTransact::handle_response_from_server(State *s)
         // Force host resolution to have the same family as the client.
         // Because this is a transparent connection, we can't switch address
         // families - that is locked in by the client source address.
-        s->dns_info.host_res_style = ats_host_res_match(&s->current.server->dst_addr.sa);
+        ats_force_order_by_family(&s->current.server->dst_addr.sa, s->my_txn_conf().host_res_data.order);
         return CallOSDNSLookup(s);
       } else if ((s->dns_info.srv_lookup_success || s->host_db_info.is_rr_elt()) &&
                  (s->txn_conf->connect_attempts_rr_retries > 0) &&
diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h
index a6380c7..526ffb0 100644
--- a/proxy/http/HttpTransact.h
+++ b/proxy/http/HttpTransact.h
@@ -41,6 +41,7 @@
 #include "UrlMapping.h"
 #include "records/I_RecHttp.h"
 #include "ProxySession.h"
+#include "MgmtDefs.h"
 
 #define HTTP_RELEASE_ASSERT(X) ink_release_assert(X)
 
@@ -621,8 +622,7 @@ public:
       OS_ADDR_USE_CLIENT   ///< Use client target addr, no fallback.
     };
 
-    OS_Addr os_addr_style       = OS_Addr::OS_ADDR_TRY_DEFAULT;
-    HostResStyle host_res_style = HOST_RES_IPV4;
+    OS_Addr os_addr_style = OS_Addr::OS_ADDR_TRY_DEFAULT;
 
     bool lookup_success         = false;
     char *lookup_name           = nullptr;
@@ -640,6 +640,9 @@ public:
     _DNSLookupInfo() {}
   } DNSLookupInfo;
 
+  // Conversion handling for DNS host resolution type.
+  static const MgmtConverter HOST_RES_CONV;
+
   typedef struct _HeaderInfo {
     HTTPHdr client_request;
     HTTPHdr client_response;
diff --git a/src/shared/overridable_txn_vars.cc b/src/shared/overridable_txn_vars.cc
index 3be8970..3eb2a8d 100644
--- a/src/shared/overridable_txn_vars.cc
+++ b/src/shared/overridable_txn_vars.cc
@@ -159,4 +159,5 @@ const std::unordered_map<std::string_view, std::tuple<const TSOverridableConfigK
      {"proxy.config.ssl.client.cert.filename", {TS_CONFIG_SSL_CLIENT_CERT_FILENAME, TS_RECORDDATATYPE_STRING}},
      {"proxy.config.ssl.client.cert.path", {TS_CONFIG_SSL_CERT_FILEPATH, TS_RECORDDATATYPE_STRING}},
      {"proxy.config.ssl.client.private_key.filename", {TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME, TS_RECORDDATATYPE_STRING}},
-     {"proxy.config.ssl.client.CA.cert.filename", {TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME, TS_RECORDDATATYPE_STRING}}});
+     {"proxy.config.ssl.client.CA.cert.filename", {TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME, TS_RECORDDATATYPE_STRING}},
+     {"proxy.config.hostdb.ip_resolve", {TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE, TS_RECORDDATATYPE_STRING}}});
diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc
index edbed0f..da597e0 100644
--- a/src/traffic_server/InkAPI.cc
+++ b/src/traffic_server/InkAPI.cc
@@ -8611,6 +8611,10 @@ _conf_to_memberp(TSOverridableConfigKey conf, OverridableHttpConfigParams *overr
     ret  = &overridableHttpConfig->outbound_conntrack.match;
     conv = &OutboundConnTrack::MATCH_CONV;
     break;
+  case TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE:
+    ret  = &overridableHttpConfig->host_res_data;
+    conv = &HttpTransact::HOST_RES_CONV;
+    break;
   // This helps avoiding compiler warnings, yet detect unhandled enum members.
   case TS_CONFIG_NULL:
   case TS_CONFIG_LAST_ENTRY:
@@ -8798,6 +8802,11 @@ TSHttpTxnConfigStringSet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char
   case TS_CONFIG_SSL_CERT_FILEPATH:
     /* noop */
     break;
+  case TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE:
+    if (value && length > 0) {
+      s->t_state.my_txn_conf().host_res_data.conf_value = const_cast<char *>(value);
+    }
+    [[fallthrough]];
   default: {
     MgmtConverter const *conv;
     void *dest = _conf_to_memberp(conf, &(s->t_state.my_txn_conf()), conv);
diff --git a/src/traffic_server/InkAPITest.cc b/src/traffic_server/InkAPITest.cc
index 685da74..e1273c2 100644
--- a/src/traffic_server/InkAPITest.cc
+++ b/src/traffic_server/InkAPITest.cc
@@ -8660,7 +8660,8 @@ std::array<std::string_view, TS_CONFIG_LAST_ENTRY> SDK_Overridable_Configs = {
    "proxy.config.ssl.client.verify.server.properties",
    "proxy.config.ssl.client.sni_policy",
    "proxy.config.ssl.client.private_key.filename",
-   "proxy.config.ssl.client.CA.cert.filename"}};
+   "proxy.config.ssl.client.CA.cert.filename",
+   "proxy.config.hostdb.ip_resolve"}};
 
 REGRESSION_TEST(SDK_API_OVERRIDABLE_CONFIGS)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
 {
diff --git a/src/tscore/ink_res_mkquery.cc b/src/tscore/ink_res_mkquery.cc
index 7bfe95b..85af97f 100644
--- a/src/tscore/ink_res_mkquery.cc
+++ b/src/tscore/ink_res_mkquery.cc
@@ -545,14 +545,16 @@ ats_host_res_from(int family, HostResPreferenceOrder const &order)
   return HOST_RES_NONE;
 }
 
-HostResStyle
-ats_host_res_match(sockaddr const *addr)
+void
+ats_force_order_by_family(sockaddr const *addr, HostResPreferenceOrder order)
 {
-  HostResStyle zret = HOST_RES_NONE;
+  int pos{0};
   if (ats_is_ip6(addr)) {
-    zret = HOST_RES_IPV6_ONLY;
+    order[pos++] = HOST_RES_PREFER_IPV6;
   } else if (ats_is_ip4(addr)) {
-    zret = HOST_RES_IPV4_ONLY;
+    order[pos++] = HOST_RES_PREFER_IPV4;
+  }
+  for (; pos < N_HOST_RES_PREFERENCE_ORDER; pos++) {
+    order[pos] = HOST_RES_PREFER_NONE;
   }
-  return zret;
 }
diff --git a/tests/gold_tests/remap/gold/remap-DNS-ipv6-200.gold b/tests/gold_tests/remap/gold/remap-DNS-ipv6-200.gold
new file mode 100644
index 0000000..8250185
--- /dev/null
+++ b/tests/gold_tests/remap/gold/remap-DNS-ipv6-200.gold
@@ -0,0 +1,14 @@
+``
+> GET http://testDNS2.com``
+> Host: testDNS2.com``
+> User-Agent: curl/``
+> Accept: */*
+``
+< HTTP/1.1 200 OK
+< Date: ``
+< Age: ``
+< Transfer-Encoding: chunked
+< Proxy-Connection: keep-alive
+< Server: ATS/``
+< 
+``
diff --git a/tests/gold_tests/remap/gold/remap-ip-resolve.gold b/tests/gold_tests/remap/gold/remap-ip-resolve.gold
new file mode 100644
index 0000000..c83df3f
--- /dev/null
+++ b/tests/gold_tests/remap/gold/remap-ip-resolve.gold
@@ -0,0 +1,14 @@
+``
+> GET http://testDNS.com/``
+> Host: testDNS.com``
+> User-Agent: curl/``
+> Accept: */*
+``
+< HTTP/1.1 200 OK
+< Server: ATS/``
+< Date: ``
+< Age: ``
+< Transfer-Encoding: chunked
+< Proxy-Connection: keep-alive
+<
+``
diff --git a/tests/gold_tests/remap/remap_ip_resolve.test.py b/tests/gold_tests/remap/remap_ip_resolve.test.py
new file mode 100644
index 0000000..a740275
--- /dev/null
+++ b/tests/gold_tests/remap/remap_ip_resolve.test.py
@@ -0,0 +1,79 @@
+
+'''
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+Test.Summary = '''
+Test a basic ip_resolve override using an ipv6 server
+'''
+
+Test.ContinueOnFail = True
+# Define default ATS
+ts = Test.MakeATSProcess("ts")
+server = Test.MakeOriginServer("server")
+server_v6 = Test.MakeOriginServer("server_v6", None, None, '::1', 0)
+
+dns = Test.MakeDNServer("dns")
+
+Test.testName = ""
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
+                  "timestamp": "1469733493.993", "body": ""}
+# expected response from the origin server
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n",
+                   "timestamp": "1469733493.993", "body": ""}
+
+# add response to the server dictionary
+server.addResponse("sessionfile.log", request_header, response_header)
+server_v6.addResponse("sessionfile.log", request_header, response_header)
+ts.Disk.records_config.update({
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'http.*|dns|conf_remap',
+    'proxy.config.http.referer_filter': 1,
+    'proxy.config.dns.nameservers': '127.0.0.1:{0}'.format(dns.Variables.Port),
+    'proxy.config.dns.resolv_conf': 'NULL',
+    'proxy.config.hostdb.ip_resolve': 'ipv4'
+})
+
+
+ts.Disk.remap_config.AddLine(
+    'map http://testDNS.com http://test.ipv4.only.com:{0}  @plugin=conf_remap.so @pparam=proxy.config.hostdb.ip_resolve=ipv6;ipv4;client'.format(server.Variables.Port)
+)
+ts.Disk.remap_config.AddLine(
+    'map http://testDNS2.com http://test.ipv6.only.com:{0}  @plugin=conf_remap.so @pparam=proxy.config.hostdb.ip_resolve=ipv6;only'.format(server_v6.Variables.Port)
+)
+
+
+dns.addRecords(records={"test.ipv4.only.com.": ["127.0.0.1"]})
+dns.addRecords(records={"test.ipv6.only.com": ["127.0.0.1","::1"]})
+
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = 'curl  --proxy 127.0.0.1:{0} "http://testDNS.com" --verbose'.format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(dns)
+tr.Processes.Default.StartBefore(Test.Processes.ts)
+tr.Processes.Default.Streams.stderr = "gold/remap-DNS-200.gold"
+tr.StillRunningAfter=server
+
+
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = 'curl  --proxy 127.0.0.1:{0} "http://testDNS2.com" --verbose'.format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.StartBefore(server_v6)
+tr.Processes.Default.Streams.stderr = "gold/remap-DNS-ipv6-200.gold"
+tr.StillRunningAfter=server_v6
+