diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c
index 5303e32de0c4f1e046cf28136e742f42ac293ee3..f7fa931788df38f2dfa252f590f68ae48f7653b5 100644
--- a/src/core/ext/client_config/http_connect_handshaker.c
+++ b/src/core/ext/client_config/http_connect_handshaker.c
@@ -46,7 +46,9 @@ typedef struct http_connect_handshaker {
   // Base class.  Must be first.
   grpc_handshaker base;
 
+  // These pointers are borrowed, we don't own them.
   char* proxy_server;
+  char* server_name;
 
   // State saved while performing the handshake.
   grpc_endpoint* endpoint;
@@ -67,7 +69,6 @@ typedef struct http_connect_handshaker {
 static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg,
                           grpc_error* error) {
   http_connect_handshaker* h = arg;
-  // Read HTTP CONNECT response.
   grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer,
                      &h->response_read_closure);
 }
@@ -114,7 +115,6 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx,
                                             grpc_handshaker* handshaker) {
   http_connect_handshaker* h = (http_connect_handshaker*)handshaker;
-  gpr_free(h->proxy_server);
   gpr_slice_buffer_destroy(&h->request_buffer);
   gpr_slice_buffer_destroy(&h->response_buffer);
   grpc_http_parser_destroy(&h->http_parser);
@@ -149,8 +149,7 @@ static void http_connect_handshaker_do_handshake(
   memset(&request, 0, sizeof(request));
   request.host = gpr_strdup(h->proxy_server);
   request.http.method = gpr_strdup("CONNECT");
-  // FIXME: get server name from somewhere...
-  request.http.path = gpr_strdup("");
+  request.http.path = gpr_strdup(h->server_name);
   request.handshaker = &grpc_httpcli_plaintext;
   gpr_slice request_slice = grpc_httpcli_format_connect_request(&request);
   gpr_slice_buffer_add(&h->request_buffer, request_slice);
@@ -170,17 +169,19 @@ char* grpc_get_http_connect_proxy_server_from_args(grpc_channel_args* args) {
                 GRPC_ARG_HTTP_CONNECT_PROXY_SERVER);
         break;
       }
-      return gpr_strdup(args->args[i].value.string);
+      return args->args[i].value.string;
     }
   }
   return NULL;
 }
 
-grpc_handshaker* grpc_http_connect_handshaker_create(char* proxy_server) {
+grpc_handshaker* grpc_http_connect_handshaker_create(char* proxy_server,
+                                                     char* server_name) {
   http_connect_handshaker* handshaker =
       gpr_malloc(sizeof(http_connect_handshaker));
   memset(handshaker, 0, sizeof(*handshaker));
   grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base);
   handshaker->proxy_server = proxy_server;
+  handshaker->server_name = server_name;
   return (grpc_handshaker*)handshaker;
 }
diff --git a/src/core/ext/client_config/http_connect_handshaker.h b/src/core/ext/client_config/http_connect_handshaker.h
index 6467c004ee166e13d4786a20ca713b536a352e4a..feb2ec13f0b624898af5e5d8fb9dfd06b4eaa147 100644
--- a/src/core/ext/client_config/http_connect_handshaker.h
+++ b/src/core/ext/client_config/http_connect_handshaker.h
@@ -36,10 +36,13 @@
 
 #include "src/core/lib/channel/handshaker.h"
 
-/// Caller takes ownership of returned string.
+/// Caller does NOT take ownership of returned string.
 char* grpc_get_http_connect_proxy_server_from_args(grpc_channel_args *args);
 
-/// Takes ownership of \a proxy_server.
-grpc_handshaker* grpc_http_connect_handshaker_create(char* proxy_server);
+/// Borrows references to \a proxy_server or \a server_name.
+/// The caller must ensure that they remain alive until handshaking is
+/// complete.
+grpc_handshaker* grpc_http_connect_handshaker_create(char* proxy_server,
+                                                     char* server_name);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H */
diff --git a/src/core/ext/client_config/lb_policy_factory.h b/src/core/ext/client_config/lb_policy_factory.h
index 1c89b28b59a3301dbfad3c26a3e5db67341b8005..77885ea86a7e7d0f397616a30706551d86ce01de 100644
--- a/src/core/ext/client_config/lb_policy_factory.h
+++ b/src/core/ext/client_config/lb_policy_factory.h
@@ -50,6 +50,7 @@ struct grpc_lb_policy_factory {
 };
 
 typedef struct grpc_lb_policy_args {
+  char *server_name;  // Does not own.
   grpc_resolved_addresses *addresses;
   grpc_client_channel_factory *client_channel_factory;
 } grpc_lb_policy_args;
diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h
index b6d39f5dc52556c9314c6822910839a7dd5755a9..9fbf3b61230809e19b3419deb031ee7e904c20a2 100644
--- a/src/core/ext/client_config/subchannel.h
+++ b/src/core/ext/client_config/subchannel.h
@@ -162,6 +162,8 @@ struct grpc_subchannel_args {
   size_t filter_count;
   /** Channel arguments to be supplied to the newly created channel */
   const grpc_channel_args *args;
+  /** Server name */
+  char *server_name;  // Does not own.
   /** Address to connect to */
   struct sockaddr *addr;
   size_t addr_len;
diff --git a/src/core/ext/client_config/subchannel_index.c b/src/core/ext/client_config/subchannel_index.c
index 690cb16b96f06237017603ce49ff503cde43fb76..891c066f2ca39de446984033924f309877eb846a 100644
--- a/src/core/ext/client_config/subchannel_index.c
+++ b/src/core/ext/client_config/subchannel_index.c
@@ -85,6 +85,7 @@ static grpc_subchannel_key *create_key(
   } else {
     k->args.filters = NULL;
   }
+  k->args.server_name = args->server_name;
   k->args.addr_len = args->addr_len;
   k->args.addr = gpr_malloc(args->addr_len);
   if (k->args.addr_len > 0) {
@@ -111,6 +112,8 @@ static int subchannel_key_compare(grpc_subchannel_key *a,
   if (c != 0) return c;
   c = GPR_ICMP(a->args.filter_count, b->args.filter_count);
   if (c != 0) return c;
+  c = strcmp(a->args.server_name, b->args.server_name);
+  if (c != 0) return c;
   if (a->args.addr_len) {
     c = memcmp(a->args.addr, b->args.addr, a->args.addr_len);
     if (c != 0) return c;
@@ -126,9 +129,9 @@ static int subchannel_key_compare(grpc_subchannel_key *a,
 void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
                                  grpc_subchannel_key *k) {
   grpc_connector_unref(exec_ctx, k->connector);
-  gpr_free(k->args.addr);
   gpr_free((grpc_channel_args *)k->args.filters);
   grpc_channel_args_destroy((grpc_channel_args *)k->args.args);
+  gpr_free(k->args.addr);
   gpr_free(k);
 }
 
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 9decf70692a5994e43d5e4d9bfd88fe7dc00fcd0..02b921c6bb2db6a252e3b579545534f674c6a4ac 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -455,6 +455,7 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
   size_t subchannel_idx = 0;
   for (size_t i = 0; i < args->addresses->naddrs; i++) {
     memset(&sc_args, 0, sizeof(grpc_subchannel_args));
+    sc_args.server_name = args->server_name;
     sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
     sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
 
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index 7bcf608ab9b46273efb5138a2b1368e87aafc3c7..01c6a22d3c14339c37f21384932f8402b9865b05 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -582,6 +582,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
   size_t subchannel_idx = 0;
   for (size_t i = 0; i < args->addresses->naddrs; i++) {
     memset(&sc_args, 0, sizeof(grpc_subchannel_args));
+    sc_args.server_name = args->server_name;
     sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
     sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
 
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 31ac968670f7eea1be9e3ab3f670cf230a4315ad..255448f4275da164833332a98591b882b5673577 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -66,7 +66,7 @@ typedef struct {
   /** mutex guarding the rest of the state */
   gpr_mu mu;
   /** are we currently resolving? */
-  int resolving;
+  bool resolving;
   /** which version of resolved_config have we published? */
   int published_version;
   /** which version of resolved_config is current? */
@@ -169,16 +169,17 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
   grpc_lb_policy *lb_policy;
   gpr_mu_lock(&r->mu);
   GPR_ASSERT(r->resolving);
-  r->resolving = 0;
+  r->resolving = false;
   grpc_resolved_addresses *addresses = r->addresses;
   if (addresses != NULL) {
     grpc_lb_policy_args lb_policy_args;
-    config = grpc_client_config_create();
     memset(&lb_policy_args, 0, sizeof(lb_policy_args));
+    lb_policy_args.server_name = r->name;
     lb_policy_args.addresses = addresses;
     lb_policy_args.client_channel_factory = r->client_channel_factory;
     lb_policy =
         grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
+    config = grpc_client_config_create();
     if (lb_policy != NULL) {
       grpc_client_config_set_lb_policy(config, lb_policy);
       GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
@@ -218,7 +219,7 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
                                        dns_resolver *r) {
   GRPC_RESOLVER_REF(&r->base, "dns-resolving");
   GPR_ASSERT(!r->resolving);
-  r->resolving = 1;
+  r->resolving = true;
   r->addresses = NULL;
   grpc_resolve_address(exec_ctx, r->name, r->default_port,
                        grpc_closure_create(dns_on_resolved, r), &r->addresses);
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index 1f7cce2f43a9a14976b4330143d5bdcfeb9226c9..e7c2d5c928956971840573a6446941c8d2c8a95b 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -125,6 +125,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
     grpc_client_config *cfg = grpc_client_config_create();
     grpc_lb_policy_args lb_policy_args;
     memset(&lb_policy_args, 0, sizeof(lb_policy_args));
+    lb_policy_args.server_name = "";
     lb_policy_args.addresses = r->addresses;
     lb_policy_args.client_channel_factory = r->client_channel_factory;
     grpc_lb_policy *lb_policy =
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index 800ef59de0ed8add639ae01bee34103a68e0b8f6..2df4ce1dda37c8918073865464e99a22e3bee190 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -191,7 +191,8 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
   char *proxy_server = grpc_get_http_connect_proxy_server_from_args(final_args);
   if (proxy_server != NULL) {
     grpc_handshake_manager_add(
-        grpc_http_connect_handshaker_create(proxy_server), c->handshake_mgr);
+        grpc_http_connect_handshaker_create(proxy_server, args->server_name),
+        c->handshake_mgr);
   }
   args->args = final_args;
   s = grpc_subchannel_create(exec_ctx, &c->base, args);
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index 9feae8e4091d2b96e55720d43c1590ed4856eb87..ee8f39434b4b86b2969f9260b3cfa0b47480a128 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -260,7 +260,8 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
   char *proxy_server = grpc_get_http_connect_proxy_server_from_args(final_args);
   if (proxy_server != NULL) {
     grpc_handshake_manager_add(
-        grpc_http_connect_handshaker_create(proxy_server), c->handshake_mgr);
+        grpc_http_connect_handshaker_create(proxy_server, args->server_name),
+        c->handshake_mgr);
   }
   gpr_mu_init(&c->mu);
   gpr_ref_init(&c->refs, 1);