Add proxy mapper hook.
diff --git a/BUILD b/BUILD
index bbde046..dff211d 100644
--- a/BUILD
+++ b/BUILD
@@ -669,6 +669,8 @@
         "src/core/ext/client_channel/lb_policy_factory.c",
         "src/core/ext/client_channel/lb_policy_registry.c",
         "src/core/ext/client_channel/parse_address.c",
+        "src/core/ext/client_channel/proxy_mapper.c",
+        "src/core/ext/client_channel/proxy_mapper_registry.c",
         "src/core/ext/client_channel/resolver.c",
         "src/core/ext/client_channel/resolver_factory.c",
         "src/core/ext/client_channel/resolver_registry.c",
@@ -686,6 +688,8 @@
         "src/core/ext/client_channel/lb_policy_factory.h",
         "src/core/ext/client_channel/lb_policy_registry.h",
         "src/core/ext/client_channel/parse_address.h",
+        "src/core/ext/client_channel/proxy_mapper.h",
+        "src/core/ext/client_channel/proxy_mapper_registry.h",
         "src/core/ext/client_channel/resolver.h",
         "src/core/ext/client_channel/resolver_factory.h",
         "src/core/ext/client_channel/resolver_registry.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d67736..4d0aa90 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -470,6 +470,8 @@
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -729,6 +731,8 @@
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -987,6 +991,8 @@
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -1433,6 +1439,8 @@
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
diff --git a/Makefile b/Makefile
index 184bdaf..743cd19 100644
--- a/Makefile
+++ b/Makefile
@@ -2820,6 +2820,8 @@
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -3097,6 +3099,8 @@
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -3613,6 +3617,8 @@
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -4171,6 +4177,8 @@
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
diff --git a/binding.gyp b/binding.gyp
index 479403e..dd6db14 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -773,6 +773,8 @@
         'src/core/ext/client_channel/lb_policy_factory.c',
         'src/core/ext/client_channel/lb_policy_registry.c',
         'src/core/ext/client_channel/parse_address.c',
+        'src/core/ext/client_channel/proxy_mapper.c',
+        'src/core/ext/client_channel/proxy_mapper_registry.c',
         'src/core/ext/client_channel/resolver.c',
         'src/core/ext/client_channel/resolver_factory.c',
         'src/core/ext/client_channel/resolver_registry.c',
diff --git a/build.yaml b/build.yaml
index 1072bfc..ceb4cf1 100644
--- a/build.yaml
+++ b/build.yaml
@@ -394,6 +394,8 @@
   - src/core/ext/client_channel/lb_policy_factory.h
   - src/core/ext/client_channel/lb_policy_registry.h
   - src/core/ext/client_channel/parse_address.h
+  - src/core/ext/client_channel/proxy_mapper.h
+  - src/core/ext/client_channel/proxy_mapper_registry.h
   - src/core/ext/client_channel/resolver.h
   - src/core/ext/client_channel/resolver_factory.h
   - src/core/ext/client_channel/resolver_registry.h
@@ -413,6 +415,8 @@
   - src/core/ext/client_channel/lb_policy_factory.c
   - src/core/ext/client_channel/lb_policy_registry.c
   - src/core/ext/client_channel/parse_address.c
+  - src/core/ext/client_channel/proxy_mapper.c
+  - src/core/ext/client_channel/proxy_mapper_registry.c
   - src/core/ext/client_channel/resolver.c
   - src/core/ext/client_channel/resolver_factory.c
   - src/core/ext/client_channel/resolver_registry.c
diff --git a/config.m4 b/config.m4
index 85549e5..62bd1f6 100644
--- a/config.m4
+++ b/config.m4
@@ -259,6 +259,8 @@
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 1eb1789..bd0e0e2 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -405,6 +405,8 @@
                       'src/core/ext/client_channel/lb_policy_factory.h',
                       'src/core/ext/client_channel/lb_policy_registry.h',
                       'src/core/ext/client_channel/parse_address.h',
+                      'src/core/ext/client_channel/proxy_mapper.h',
+                      'src/core/ext/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/client_channel/resolver.h',
                       'src/core/ext/client_channel/resolver_factory.h',
                       'src/core/ext/client_channel/resolver_registry.h',
@@ -611,6 +613,8 @@
                       'src/core/ext/client_channel/lb_policy_factory.c',
                       'src/core/ext/client_channel/lb_policy_registry.c',
                       'src/core/ext/client_channel/parse_address.c',
+                      'src/core/ext/client_channel/proxy_mapper.c',
+                      'src/core/ext/client_channel/proxy_mapper_registry.c',
                       'src/core/ext/client_channel/resolver.c',
                       'src/core/ext/client_channel/resolver_factory.c',
                       'src/core/ext/client_channel/resolver_registry.c',
@@ -817,6 +821,8 @@
                               'src/core/ext/client_channel/lb_policy_factory.h',
                               'src/core/ext/client_channel/lb_policy_registry.h',
                               'src/core/ext/client_channel/parse_address.h',
+                              'src/core/ext/client_channel/proxy_mapper.h',
+                              'src/core/ext/client_channel/proxy_mapper_registry.h',
                               'src/core/ext/client_channel/resolver.h',
                               'src/core/ext/client_channel/resolver_factory.h',
                               'src/core/ext/client_channel/resolver_registry.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index cfc0c35..8131198 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -322,6 +322,8 @@
   s.files += %w( src/core/ext/client_channel/lb_policy_factory.h )
   s.files += %w( src/core/ext/client_channel/lb_policy_registry.h )
   s.files += %w( src/core/ext/client_channel/parse_address.h )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper.h )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper_registry.h )
   s.files += %w( src/core/ext/client_channel/resolver.h )
   s.files += %w( src/core/ext/client_channel/resolver_factory.h )
   s.files += %w( src/core/ext/client_channel/resolver_registry.h )
@@ -528,6 +530,8 @@
   s.files += %w( src/core/ext/client_channel/lb_policy_factory.c )
   s.files += %w( src/core/ext/client_channel/lb_policy_registry.c )
   s.files += %w( src/core/ext/client_channel/parse_address.c )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper.c )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper_registry.c )
   s.files += %w( src/core/ext/client_channel/resolver.c )
   s.files += %w( src/core/ext/client_channel/resolver_factory.c )
   s.files += %w( src/core/ext/client_channel/resolver_registry.c )
diff --git a/package.xml b/package.xml
index aa1894f..fce06ce 100644
--- a/package.xml
+++ b/package.xml
@@ -331,6 +331,8 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/parse_address.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" />
@@ -537,6 +539,8 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_registry.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/parse_address.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper_registry.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" />
diff --git a/src/core/ext/client_channel/proxy_mapper.c b/src/core/ext/client_channel/proxy_mapper.c
new file mode 100644
index 0000000..11ce06b
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper.c
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/client_channel/proxy_mapper.h"
+
+void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
+                            grpc_proxy_mapper* mapper) {
+  mapper->vtable = vtable;
+}
+
+bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+                           const grpc_resolved_address* address,
+                           const grpc_channel_args* args,
+                           grpc_resolved_address** new_address,
+                           grpc_channel_args** new_args) {
+  return mapper->vtable->map(exec_ctx, mapper, address, args, new_address,
+                             new_args);
+}
+
+void grpc_proxy_mapper_destroy(grpc_exec_ctx* exec_ctx,
+                               grpc_proxy_mapper* mapper) {
+  mapper->vtable->destroy(exec_ctx, mapper);
+}
diff --git a/src/core/ext/client_channel/proxy_mapper.h b/src/core/ext/client_channel/proxy_mapper.h
new file mode 100644
index 0000000..a47a2f6
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H
+
+#include <stdbool.h>
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/lib/iomgr/resolve_address.h"
+
+typedef struct grpc_proxy_mapper grpc_proxy_mapper;
+
+typedef struct {
+  /// Determines the proxy address to use to contact \a address.
+  /// If no proxy is needed, returns false.
+  /// Otherwise, sets \a new_address, optionally sets \a new_args, and
+  /// returns true.
+  bool (*map)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+              const grpc_resolved_address* address,
+              const grpc_channel_args* args,
+              grpc_resolved_address** new_address,
+              grpc_channel_args** new_args);
+  /// Destroys \a mapper.
+  void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper);
+} grpc_proxy_mapper_vtable;
+
+struct grpc_proxy_mapper {
+  const grpc_proxy_mapper_vtable* vtable;
+};
+
+void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
+                            grpc_proxy_mapper* mapper);
+
+bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+                           const grpc_resolved_address* address,
+                           const grpc_channel_args* args,
+                           grpc_resolved_address** new_address,
+                           grpc_channel_args** new_args);
+void grpc_proxy_mapper_destroy(grpc_exec_ctx* exec_ctx,
+                               grpc_proxy_mapper* mapper);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.c b/src/core/ext/client_channel/proxy_mapper_registry.c
new file mode 100644
index 0000000..ad453f2
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper_registry.c
@@ -0,0 +1,110 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+//
+// grpc_proxy_mapper_list
+//
+
+typedef struct {
+  grpc_proxy_mapper** list;
+  size_t num_mappers;
+} grpc_proxy_mapper_list;
+
+static void grpc_proxy_mapper_list_register(
+    grpc_proxy_mapper_list* list, bool at_start, grpc_proxy_mapper* mapper) {
+  list->list = gpr_realloc(
+      list->list, (list->num_mappers + 1) * sizeof(grpc_proxy_mapper*));
+  if (at_start) {
+    memmove(list->list + 1, list->list,
+            sizeof(grpc_proxy_mapper*) * list->num_mappers);
+    list->list[0] = mapper;
+  } else {
+    list->list[list->num_mappers] = mapper;
+  }
+  ++list->num_mappers;
+}
+
+static bool grpc_proxy_mapper_list_map(
+    grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list,
+    const grpc_resolved_address* address, const grpc_channel_args* args,
+    grpc_resolved_address** new_address, grpc_channel_args** new_args) {
+  for (size_t i = 0; i < list->num_mappers; ++i) {
+    if (grpc_proxy_mapper_map(exec_ctx, list->list[i], address, args,
+                              new_address, new_args)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static void grpc_proxy_mapper_list_destroy(
+    grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list) {
+  for (size_t i = 0; i < list->num_mappers; ++i) {
+    grpc_proxy_mapper_destroy(exec_ctx, list->list[i]);
+  }
+  gpr_free(list->list);
+}
+
+//
+// plugin
+//
+
+static grpc_proxy_mapper_list g_proxy_mapper_list;
+
+void grpc_proxy_mapper_registry_init() {
+  memset(&g_proxy_mapper_list, 0, sizeof(g_proxy_mapper_list));
+}
+
+void grpc_proxy_mapper_registry_shutdown(grpc_exec_ctx* exec_ctx) {
+  grpc_proxy_mapper_list_destroy(exec_ctx, &g_proxy_mapper_list);
+}
+
+void grpc_proxy_mapper_factory_register(bool at_start,
+                                        grpc_proxy_mapper* mapper) {
+  grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
+}
+
+bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
+                            const grpc_resolved_address* address,
+                            const grpc_channel_args* args,
+                            grpc_resolved_address** new_address,
+                            grpc_channel_args** new_args) {
+  return grpc_proxy_mapper_list_map(exec_ctx, &g_proxy_mapper_list, address,
+                                    args, new_address, new_args);
+}
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.h b/src/core/ext/client_channel/proxy_mapper_registry.h
new file mode 100644
index 0000000..4a4840d
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper_registry.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H
+
+#include "src/core/ext/client_channel/proxy_mapper.h"
+
+void grpc_proxy_mapper_registry_init();
+void grpc_proxy_mapper_registry_shutdown(grpc_exec_ctx* exec_ctx);
+
+/// Registers a new proxy mapper.  Takes ownership.
+/// If \a at_start is true, the new factory will be at the beginning of
+/// the list.  Otherwise, it will be added to the end.
+void grpc_proxy_mapper_factory_register(bool at_start,
+                                        grpc_proxy_mapper* mapper);
+
+bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
+                            const grpc_resolved_address* address,
+                            const grpc_channel_args* args,
+                            grpc_resolved_address** new_address,
+                            grpc_channel_args** new_args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index 8bd2845..ff82a77 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -43,6 +43,7 @@
 #include "src/core/ext/client_channel/client_channel.h"
 #include "src/core/ext/client_channel/initial_connect_string.h"
 #include "src/core/ext/client_channel/parse_address.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/subchannel_index.h"
 #include "src/core/ext/client_channel/uri_parser.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -332,13 +333,24 @@
   grpc_resolved_address *addr = gpr_malloc(sizeof(*addr));
   grpc_get_subchannel_address_arg(args->args, addr);
   grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
-  static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
-  grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
+  grpc_resolved_address *new_address = NULL;
+  grpc_channel_args *new_args = NULL;
+  if (grpc_proxy_mappers_map(exec_ctx, c->addr, args->args, &new_address,
+                             &new_args)) {
+    GPR_ASSERT(new_address != NULL);
+    gpr_free(addr);
+    addr = new_address;
+    if (new_args != NULL) c->args = new_args;
+  }
+  if (c->args == NULL) {
+    static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
+    grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
+    c->args = grpc_channel_args_copy_and_add_and_remove(
+        args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg,
+        1);
+    gpr_free(new_arg.value.string);
+  }
   gpr_free(addr);
-  c->args = grpc_channel_args_copy_and_add_and_remove(
-      args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
-  gpr_free(new_arg.value.string);
-
   c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
       &c->root_external_state_watcher;
   grpc_closure_init(&c->connected, subchannel_connected, c,
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index e27e9e1..e8f5bf9 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -253,6 +253,8 @@
   'src/core/ext/client_channel/lb_policy_factory.c',
   'src/core/ext/client_channel/lb_policy_registry.c',
   'src/core/ext/client_channel/parse_address.c',
+  'src/core/ext/client_channel/proxy_mapper.c',
+  'src/core/ext/client_channel/proxy_mapper_registry.c',
   'src/core/ext/client_channel/resolver.c',
   'src/core/ext/client_channel/resolver_factory.c',
   'src/core/ext/client_channel/resolver_registry.c',
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 4591aa5..64ec0d4 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -906,6 +906,10 @@
 src/core/ext/client_channel/lb_policy_registry.h \
 src/core/ext/client_channel/parse_address.c \
 src/core/ext/client_channel/parse_address.h \
+src/core/ext/client_channel/proxy_mapper.c \
+src/core/ext/client_channel/proxy_mapper.h \
+src/core/ext/client_channel/proxy_mapper_registry.c \
+src/core/ext/client_channel/proxy_mapper_registry.h \
 src/core/ext/client_channel/resolver.c \
 src/core/ext/client_channel/resolver.h \
 src/core/ext/client_channel/resolver_factory.c \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 1a3345c..4005284 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -7122,6 +7122,8 @@
       "src/core/ext/client_channel/lb_policy_factory.h", 
       "src/core/ext/client_channel/lb_policy_registry.h", 
       "src/core/ext/client_channel/parse_address.h", 
+      "src/core/ext/client_channel/proxy_mapper.h", 
+      "src/core/ext/client_channel/proxy_mapper_registry.h", 
       "src/core/ext/client_channel/resolver.h", 
       "src/core/ext/client_channel/resolver_factory.h", 
       "src/core/ext/client_channel/resolver_registry.h", 
@@ -7154,6 +7156,10 @@
       "src/core/ext/client_channel/lb_policy_registry.h", 
       "src/core/ext/client_channel/parse_address.c", 
       "src/core/ext/client_channel/parse_address.h", 
+      "src/core/ext/client_channel/proxy_mapper.c", 
+      "src/core/ext/client_channel/proxy_mapper.h", 
+      "src/core/ext/client_channel/proxy_mapper_registry.c", 
+      "src/core/ext/client_channel/proxy_mapper_registry.h", 
       "src/core/ext/client_channel/resolver.c", 
       "src/core/ext/client_channel/resolver.h", 
       "src/core/ext/client_channel/resolver_factory.c", 
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index c159db6..50f1a94 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -454,6 +454,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
@@ -841,6 +843,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 1e099f3..86f0f3c 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -538,6 +538,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -1211,6 +1217,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index dcb943a..8f22782 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -421,6 +421,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
@@ -761,6 +763,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index ac84e01..da2df3a 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -469,6 +469,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -1055,6 +1061,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>