Remove sockaddr type structs and socklen_t from internal core APIs, update POSIX tests
diff --git a/src/core/ext/client_config/client_config_plugin.c b/src/core/ext/client_config/client_config_plugin.c
index e065d06..5e31613 100644
--- a/src/core/ext/client_config/client_config_plugin.c
+++ b/src/core/ext/client_config/client_config_plugin.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <limits.h>
 #include <stdbool.h>
 #include <string.h>
diff --git a/src/core/ext/client_config/connector.h b/src/core/ext/client_config/connector.h
index 5cf8f14..18e6605 100644
--- a/src/core/ext/client_config/connector.h
+++ b/src/core/ext/client_config/connector.h
@@ -34,13 +34,8 @@
 #ifndef GRPC_CORE_EXT_CLIENT_CONFIG_CONNECTOR_H
 #define GRPC_CORE_EXT_CLIENT_CONFIG_CONNECTOR_H
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include "src/core/lib/channel/channel_stack.h"
-#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/transport/transport.h"
 
 typedef struct grpc_connector grpc_connector;
@@ -54,7 +49,7 @@
   /** set of pollsets interested in this connection */
   grpc_pollset_set *interested_parties;
   /** address to connect to */
-  const struct sockaddr *addr;
+  const grpc_resolved_address *addr;
   size_t addr_len;
   /** initial connect string to send */
   gpr_slice initial_connect_string;
diff --git a/src/core/ext/client_config/default_initial_connect_string.c b/src/core/ext/client_config/default_initial_connect_string.c
index a70da4a..0b25137 100644
--- a/src/core/ext/client_config/default_initial_connect_string.c
+++ b/src/core/ext/client_config/default_initial_connect_string.c
@@ -32,8 +32,7 @@
  */
 
 #include <grpc/support/slice.h>
-#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 
-void grpc_set_default_initial_connect_string(struct sockaddr **addr,
-                                             size_t *addr_len,
+void grpc_set_default_initial_connect_string(grpc_resolved_address **addr,
                                              gpr_slice *initial_str) {}
diff --git a/src/core/ext/client_config/initial_connect_string.c b/src/core/ext/client_config/initial_connect_string.c
index 41580d2..61683dd 100644
--- a/src/core/ext/client_config/initial_connect_string.c
+++ b/src/core/ext/client_config/initial_connect_string.c
@@ -35,8 +35,7 @@
 
 #include <stddef.h>
 
-extern void grpc_set_default_initial_connect_string(struct sockaddr **addr,
-                                                    size_t *addr_len,
+extern void grpc_set_default_initial_connect_string(grpc_resolved_address **addr,
                                                     gpr_slice *initial_str);
 
 static grpc_set_initial_connect_string_func g_set_initial_connect_string_func =
@@ -47,7 +46,7 @@
   g_set_initial_connect_string_func = func;
 }
 
-void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
+void grpc_set_initial_connect_string(grpc_resolved_address **addr,
                                      gpr_slice *initial_str) {
-  g_set_initial_connect_string_func(addr, addr_len, initial_str);
+  g_set_initial_connect_string_func(addr, initial_str);
 }
diff --git a/src/core/ext/client_config/initial_connect_string.h b/src/core/ext/client_config/initial_connect_string.h
index 06f0767..6d5301f 100644
--- a/src/core/ext/client_config/initial_connect_string.h
+++ b/src/core/ext/client_config/initial_connect_string.h
@@ -35,16 +35,16 @@
 #define GRPC_CORE_EXT_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
 
 #include <grpc/support/slice.h>
-#include "src/core/lib/iomgr/sockaddr.h"
 
-typedef void (*grpc_set_initial_connect_string_func)(struct sockaddr **addr,
-                                                     size_t *addr_len,
+#include "src/core/lib/iomgr/resolve_address.h"
+
+typedef void (*grpc_set_initial_connect_string_func)(grpc_resolved_address **addr,
                                                      gpr_slice *initial_str);
 void grpc_test_set_initial_connect_string_function(
     grpc_set_initial_connect_string_func func);
 
 /** Set a string to be sent once connected. Optionally reset addr. */
-void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
+void grpc_set_initial_connect_string(grpc_resolved_address **addr,
                                      gpr_slice *connect_string);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H */
diff --git a/src/core/ext/client_config/parse_address.c b/src/core/ext/client_config/parse_address.c
index 7c548b1..13f1f4d 100644
--- a/src/core/ext/client_config/parse_address.c
+++ b/src/core/ext/client_config/parse_address.c
@@ -31,6 +31,7 @@
  *
  */
 
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/ext/client_config/parse_address.h"
 
 #include <stdio.h>
@@ -45,32 +46,40 @@
 #include <grpc/support/string_util.h>
 
 #ifdef GRPC_HAVE_UNIX_SOCKET
-int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len) {
-  struct sockaddr_un *un = (struct sockaddr_un *)addr;
+
+int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
+  struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
 
   un->sun_family = AF_UNIX;
   strcpy(un->sun_path, uri->path);
-  *len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
+  resolved_addr->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
 
   return 1;
 }
-#endif
 
-int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len) {
+#else /* GRPC_HAVE_UNIX_SOCKET */
+
+int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
+  abort();
+}
+
+#endif /* GRPC_HAVE_UNIX_SOCKET */
+
+int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
   const char *host_port = uri->path;
   char *host;
   char *port;
   int port_num;
   int result = 0;
-  struct sockaddr_in *in = (struct sockaddr_in *)addr;
+  struct sockaddr_in *in = (struct sockaddr_in *)resolved_addr->addr;
 
   if (*host_port == '/') ++host_port;
   if (!gpr_split_host_port(host_port, &host, &port)) {
     return 0;
   }
 
-  memset(in, 0, sizeof(*in));
-  *len = sizeof(*in);
+  memset(resolved_addr, 0, sizeof(grpc_resolved_address));
+  resolved_addr->len = sizeof(struct sockaddr_in);
   in->sin_family = AF_INET;
   if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
     gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
@@ -96,13 +105,13 @@
   return result;
 }
 
-int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len) {
+int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
   const char *host_port = uri->path;
   char *host;
   char *port;
   int port_num;
   int result = 0;
-  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
+  struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)resolved_addr->addr;
 
   if (*host_port == '/') ++host_port;
   if (!gpr_split_host_port(host_port, &host, &port)) {
@@ -110,7 +119,7 @@
   }
 
   memset(in6, 0, sizeof(*in6));
-  *len = sizeof(*in6);
+  resolved_addr->len = sizeof(*in6);
   in6->sin6_family = AF_INET6;
   if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
     gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
diff --git a/src/core/ext/client_config/parse_address.h b/src/core/ext/client_config/parse_address.h
index 16300de..a309c03 100644
--- a/src/core/ext/client_config/parse_address.h
+++ b/src/core/ext/client_config/parse_address.h
@@ -37,20 +37,18 @@
 #include <stddef.h>
 
 #include "src/core/ext/client_config/uri_parser.h"
-#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 
-#ifdef GRPC_HAVE_UNIX_SOCKET
 /** Populate \a addr and \a len from \a uri, whose path is expected to contain a
  * unix socket path. Returns true upon success. */
-int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len);
-#endif
+int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr);
 
 /** Populate /a addr and \a len from \a uri, whose path is expected to contain a
  * host:port pair. Returns true upon success. */
-int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len);
+int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr);
 
 /** Populate /a addr and \a len from \a uri, whose path is expected to contain a
  * host:port pair. Returns true upon success. */
-int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, size_t *len);
+int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CONFIG_PARSE_ADDRESS_H */
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
index 2c4364b..4acc750 100644
--- a/src/core/ext/client_config/subchannel.c
+++ b/src/core/ext/client_config/subchannel.c
@@ -94,8 +94,7 @@
   /** channel arguments */
   grpc_channel_args *args;
   /** address to connect to */
-  struct sockaddr *addr;
-  size_t addr_len;
+  grpc_resolved_address *addr;
 
   grpc_subchannel_key *key;
 
@@ -319,12 +318,10 @@
   } else {
     c->filters = NULL;
   }
-  c->addr = gpr_malloc(args->addr_len);
-  if (args->addr_len) memcpy(c->addr, args->addr, args->addr_len);
+  c->addr = gpr_malloc(sizeof(grpc_resolved_address));
+  if (args->addr->len) memcpy(c->addr, args->addr, sizeof(grpc_resolved_address));
   c->pollset_set = grpc_pollset_set_create();
-  c->addr_len = args->addr_len;
-  grpc_set_initial_connect_string(&c->addr, &c->addr_len,
-                                  &c->initial_connect_string);
+  grpc_set_initial_connect_string(&c->addr, &c->initial_connect_string);
   c->args = grpc_channel_args_copy(args->args);
   c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
       &c->root_external_state_watcher;
@@ -376,7 +373,6 @@
 
   args.interested_parties = c->pollset_set;
   args.addr = c->addr;
-  args.addr_len = c->addr_len;
   args.deadline = c->next_attempt;
   args.channel_args = c->args;
   args.initial_connect_string = c->initial_connect_string;
diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h
index ae1d96e..c51e96b 100644
--- a/src/core/ext/client_config/subchannel.h
+++ b/src/core/ext/client_config/subchannel.h
@@ -163,8 +163,7 @@
   /** Channel arguments to be supplied to the newly created channel */
   const grpc_channel_args *args;
   /** Address to connect to */
-  struct sockaddr *addr;
-  size_t addr_len;
+  grpc_resolved_address *addr;
 };
 
 /** create a subchannel given a connector */
diff --git a/src/core/ext/client_config/subchannel_index.c b/src/core/ext/client_config/subchannel_index.c
index 690cb16..0ec83fb 100644
--- a/src/core/ext/client_config/subchannel_index.c
+++ b/src/core/ext/client_config/subchannel_index.c
@@ -85,10 +85,10 @@
   } else {
     k->args.filters = NULL;
   }
-  k->args.addr_len = args->addr_len;
-  k->args.addr = gpr_malloc(args->addr_len);
-  if (k->args.addr_len > 0) {
-    memcpy(k->args.addr, args->addr, k->args.addr_len);
+  k->args.addr = gpr_malloc(sizeof(grpc_resolved_address));
+  k->args.addr->len = args->addr->len;
+  if (k->args.addr->len > 0) {
+    memcpy(k->args.addr, args->addr, sizeof(grpc_resolved_address));
   }
   k->args.args = copy_channel_args(args->args);
   return k;
@@ -107,12 +107,12 @@
                                   grpc_subchannel_key *b) {
   int c = GPR_ICMP(a->connector, b->connector);
   if (c != 0) return c;
-  c = GPR_ICMP(a->args.addr_len, b->args.addr_len);
+  c = GPR_ICMP(a->args.addr->len, b->args.addr->len);
   if (c != 0) return c;
   c = GPR_ICMP(a->args.filter_count, b->args.filter_count);
   if (c != 0) return c;
-  if (a->args.addr_len) {
-    c = memcmp(a->args.addr, b->args.addr, a->args.addr_len);
+  if (a->args.addr->len) {
+    c = memcmp(a->args.addr->addr, b->args.addr->addr, a->args.addr->len);
     if (c != 0) return c;
   }
   if (a->args.filter_count > 0) {
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index a5ab42b..7f3c461 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -96,10 +96,8 @@
  * - Implement LB service forwarding (point 2c. in the doc's diagram).
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
 #include <errno.h>
 
 #include <string.h>
@@ -115,7 +113,6 @@
 #include "src/core/ext/client_config/parse_address.h"
 #include "src/core/ext/lb_policy/grpclb/grpclb.h"
 #include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
-#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/surface/call.h"
@@ -445,7 +442,7 @@
       gpr_log(GPR_ERROR,
               "Missing LB token for backend address '%s'. The empty token will "
               "be used instead",
-              grpc_sockaddr_to_uri((struct sockaddr *)sa));
+              grpc_sockaddr_to_uri(lb_addr->resolved_address));
       lb_addr->user_data = GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY;
     }
     ++addr_idx;
@@ -593,8 +590,7 @@
    * ipvX://ip1:port1,ip2:port2,...
    * TODO(dgq): support mixed ip version */
   char **addr_strs = gpr_malloc(sizeof(char *) * args->num_addresses);
-  addr_strs[0] = grpc_sockaddr_to_uri(
-      (const struct sockaddr *)&args->addresses[0].resolved_address->addr);
+  addr_strs[0] = grpc_sockaddr_to_uri(args->addresses[0].resolved_address);
   for (size_t i = 1; i < args->num_addresses; i++) {
     if (args->addresses[i].user_data != NULL) {
       gpr_log(GPR_ERROR,
@@ -604,7 +600,7 @@
     GPR_ASSERT(
         grpc_sockaddr_to_string(
             &addr_strs[i],
-            (const struct sockaddr *)&args->addresses[i].resolved_address->addr,
+            args->addresses[i].resolved_address,
             true) == 0);
   }
   size_t uri_path_len;
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 e847464..00b9660 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <string.h>
 
 #include <grpc/support/alloc.h>
@@ -462,9 +457,7 @@
     }
 
     memset(&sc_args, 0, sizeof(grpc_subchannel_args));
-    sc_args.addr =
-        (struct sockaddr *)(args->addresses[i].resolved_address->addr);
-    sc_args.addr_len = (size_t)args->addresses[i].resolved_address->len;
+    sc_args.addr = args->addresses[i].resolved_address;
 
     grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
         exec_ctx, args->client_channel_factory, &sc_args);
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 b81df97..eee3dce 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -59,11 +59,6 @@
  *   the subchannel by the caller.
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <string.h>
 
 #include <grpc/support/alloc.h>
@@ -631,8 +626,7 @@
   size_t subchannel_idx = 0;
   for (size_t i = 0; i < p->num_addresses; i++) {
     memset(&sc_args, 0, sizeof(grpc_subchannel_args));
-    sc_args.addr = (struct sockaddr *)args->addresses[i].resolved_address->addr;
-    sc_args.addr_len = args->addresses[i].resolved_address->len;
+    sc_args.addr = args->addresses[i].resolved_address;
 
     p->user_data_pointers[i] = args->addresses[i].user_data;
 
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 462f78d..32e9de6 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <string.h>
 
 #include <grpc/support/alloc.h>
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index 23ad1ce..8229c29 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
@@ -187,7 +182,7 @@
 
 static grpc_resolver *sockaddr_create(
     grpc_resolver_args *args, const char *default_lb_policy_name,
-    int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) {
+    int parse(grpc_uri *uri, grpc_resolved_address *dst)) {
   int errors_found = 0; /* GPR_FALSE */
   sockaddr_resolver *r;
   gpr_slice path_slice;
@@ -238,9 +233,7 @@
     grpc_uri ith_uri = *args->uri;
     char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
     ith_uri.path = part_str;
-    if (!parse(&ith_uri,
-               (struct sockaddr_storage *)(&r->addresses->addrs[i].addr),
-               &r->addresses->addrs[i].len)) {
+    if (!parse(&ith_uri, &r->addresses->addrs[i])) {
       errors_found = 1; /* GPR_TRUE */
     }
     gpr_free(part_str);
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 cbaa75a..acbc813 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -149,7 +149,7 @@
   c->tcp = NULL;
   grpc_closure_init(&c->connected, connected, c);
   grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp,
-                          args->interested_parties, args->addr, args->addr_len,
+                          args->interested_parties, args->addr,
                           args->deadline);
 }
 
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 9e2bdd7..344d56f 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
@@ -209,7 +209,7 @@
   grpc_closure_init(&c->connected_closure, connected, c);
   grpc_tcp_client_connect(
       exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
-      args->interested_parties, args->addr, args->addr_len, args->deadline);
+      args->interested_parties, args->addr, args->deadline);
 }
 
 static const grpc_connector_vtable connector_vtable = {
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
index f0e0742..e4967c2 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -148,9 +148,7 @@
   const size_t naddrs = resolved->naddrs;
   errors = gpr_malloc(sizeof(*errors) * naddrs);
   for (i = 0; i < naddrs; i++) {
-    errors[i] = grpc_tcp_server_add_port(
-        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
-        resolved->addrs[i].len, &port_temp);
+    errors[i] = grpc_tcp_server_add_port(tcp, &resolved->addrs[i], &port_temp);
     if (errors[i] == GRPC_ERROR_NONE) {
       if (port_num == -1) {
         port_num = port_temp;
diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
index da3e284..3b0e9c1 100644
--- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
@@ -272,9 +272,7 @@
 
   errors = gpr_malloc(sizeof(*errors) * resolved->naddrs);
   for (i = 0; i < resolved->naddrs; i++) {
-    errors[i] = grpc_tcp_server_add_port(
-        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
-        resolved->addrs[i].len, &port_temp);
+    errors[i] = grpc_tcp_server_add_port(tcp, &resolved->addrs[i], &port_temp);
     if (errors[i] == GRPC_ERROR_NONE) {
       if (port_num == -1) {
         port_num = port_temp;
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
index 18135bc..09bdc2e 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -32,7 +32,6 @@
  */
 
 #include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/iomgr/sockaddr.h"
 
 #include <string.h>
 
@@ -126,7 +125,7 @@
     req->overall_error = GRPC_ERROR_CREATE("Failed HTTP/1 client request");
   }
   grpc_resolved_address *addr = &req->addresses->addrs[req->next_address - 1];
-  char *addr_text = grpc_sockaddr_to_uri((struct sockaddr *)addr->addr);
+  char *addr_text = grpc_sockaddr_to_uri(addr);
   req->overall_error = grpc_error_add_child(
       req->overall_error,
       grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_text));
@@ -226,7 +225,7 @@
   grpc_closure_init(&req->connected, on_connected, req);
   grpc_tcp_client_connect(
       exec_ctx, &req->connected, &req->ep, req->context->pollset_set,
-      (struct sockaddr *)&addr->addr, addr->len, req->deadline);
+      addr, req->deadline);
 }
 
 static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h
index eba6ecb..662e176 100644
--- a/src/core/lib/http/httpcli.h
+++ b/src/core/lib/http/httpcli.h
@@ -34,11 +34,6 @@
 #ifndef GRPC_CORE_LIB_HTTP_HTTPCLI_H
 #define GRPC_CORE_LIB_HTTP_HTTPCLI_H
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <stddef.h>
 
 #include <grpc/support/time.h>
diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h
index 60bb16a..fd30008 100644
--- a/src/core/lib/iomgr/port.h
+++ b/src/core/lib/iomgr/port.h
@@ -37,7 +37,7 @@
 #define GRPC_CORE_LIB_IOMGR_PORT_H
 
 #if defined(GRPC_UV)
-#include <uv.h>
+// Do nothing
 #elif defined(GPR_MANYLINUX1)
 #define GRPC_HAVE_IPV6_RECVPKTINFO 1
 #define GRPC_HAVE_IP_PKTINFO 1
diff --git a/src/core/lib/iomgr/resolve_address_posix.c b/src/core/lib/iomgr/resolve_address_posix.c
index 9bc4690..de791b2 100644
--- a/src/core/lib/iomgr/resolve_address_posix.c
+++ b/src/core/lib/iomgr/resolve_address_posix.c
@@ -34,9 +34,10 @@
 #include "src/core/lib/iomgr/port.h"
 #ifdef GRPC_POSIX_SOCKET
 
-#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 
+#include "src/core/lib/iomgr/resolve_address.h"
+
 #include <string.h>
 #include <sys/types.h>
 
@@ -49,7 +50,6 @@
 #include <grpc/support/useful.h>
 #include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
-#include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
 #include "src/core/lib/support/block_annotate.h"
 #include "src/core/lib/support/string.h"
diff --git a/src/core/lib/iomgr/resolve_address_uv.c b/src/core/lib/iomgr/resolve_address_uv.c
index 550047b..f206c63 100644
--- a/src/core/lib/iomgr/resolve_address_uv.c
+++ b/src/core/lib/iomgr/resolve_address_uv.c
@@ -45,6 +45,7 @@
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
 #include <string.h>
@@ -86,8 +87,7 @@
   {
     for (i = 0; i < (*addresses)->naddrs; i++) {
       char *buf;
-      grpc_sockaddr_to_string(
-          &buf, (struct sockaddr *)&(*addresses)->addrs[i].addr, 0);
+      grpc_sockaddr_to_string(&buf, &(*addresses)->addrs[i], 0);
       gpr_free(buf);
     }
   }
diff --git a/src/core/lib/iomgr/resolve_address_windows.c b/src/core/lib/iomgr/resolve_address_windows.c
index 460bd1f..6e94269 100644
--- a/src/core/lib/iomgr/resolve_address_windows.c
+++ b/src/core/lib/iomgr/resolve_address_windows.c
@@ -34,9 +34,10 @@
 #include "src/core/lib/iomgr/port.h"
 #ifdef GRPC_WINSOCK_SOCKET
 
-#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 
+#include "src/core/lib/iomgr/resolve_address.h"
+
 #include <string.h>
 #include <sys/types.h>
 
@@ -124,8 +125,7 @@
   {
     for (i = 0; i < (*addresses)->naddrs; i++) {
       char *buf;
-      grpc_sockaddr_to_string(
-          &buf, (struct sockaddr *)&(*addresses)->addrs[i].addr, 0);
+      grpc_sockaddr_to_string(&buf, (*addresses)->addrs[i], 0);
       gpr_free(buf);
     }
   }
diff --git a/src/core/lib/iomgr/sockaddr.h b/src/core/lib/iomgr/sockaddr.h
index 418488a..75dc532 100644
--- a/src/core/lib/iomgr/sockaddr.h
+++ b/src/core/lib/iomgr/sockaddr.h
@@ -31,6 +31,9 @@
  *
  */
 
+/* This header transitively includes other headers that care about include
+ * order, so it should be included first */
+
 #ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_H
 #define GRPC_CORE_LIB_IOMGR_SOCKADDR_H
 
diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c
index ed1dac5..0333e7a 100644
--- a/src/core/lib/iomgr/sockaddr_utils.c
+++ b/src/core/lib/iomgr/sockaddr_utils.c
@@ -42,6 +42,7 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/socket_utils.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
 #include "src/core/lib/support/string.h"
@@ -49,20 +50,23 @@
 static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0,    0,
                                           0, 0, 0, 0, 0xff, 0xff};
 
-int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in *addr4_out) {
-  GPR_ASSERT(addr != (struct sockaddr *)addr4_out);
+int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *resolved_addr,
+                              grpc_resolved_address *resolved_addr4_out) {
+  GPR_ASSERT(resolved_addr != resolved_addr4_out);
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
+  struct sockaddr_in *addr4_out = (struct sockaddr_in *)resolved_addr4_out->addr;
   if (addr->sa_family == AF_INET6) {
     const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
     if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
                sizeof(kV4MappedPrefix)) == 0) {
-      if (addr4_out != NULL) {
+      if (resolved_addr4_out != NULL) {
         /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
-        memset(addr4_out, 0, sizeof(*addr4_out));
+        memset(resolved_addr4_out, 0, sizeof(*resolved_addr4_out));
         addr4_out->sin_family = AF_INET;
         /* s6_addr32 would be nice, but it's non-standard. */
         memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
         addr4_out->sin_port = addr6->sin6_port;
+        resolved_addr4_out->len = sizeof(struct sockaddr_in);
       }
       return 1;
     }
@@ -70,26 +74,31 @@
   return 0;
 }
 
-int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in6 *addr6_out) {
-  GPR_ASSERT(addr != (struct sockaddr *)addr6_out);
+int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *resolved_addr,
+                              grpc_resolved_address *resolved_addr6_out) {
+  GPR_ASSERT(resolved_addr != resolved_addr6_out);
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
+  struct sockaddr_in6 *addr6_out = (struct sockaddr_in6 *)resolved_addr6_out->addr;
   if (addr->sa_family == AF_INET) {
     const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
-    memset(addr6_out, 0, sizeof(*addr6_out));
+    memset(resolved_addr6_out, 0, sizeof(*resolved_addr6_out));
     addr6_out->sin6_family = AF_INET6;
     memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
     memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
     addr6_out->sin6_port = addr4->sin_port;
+    resolved_addr6_out->len = sizeof(struct sockaddr_in6);
     return 1;
   }
   return 0;
 }
 
-int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out) {
-  struct sockaddr_in addr4_normalized;
-  if (grpc_sockaddr_is_v4mapped(addr, &addr4_normalized)) {
-    addr = (struct sockaddr *)&addr4_normalized;
+int grpc_sockaddr_is_wildcard(const grpc_resolved_address *resolved_addr, int *port_out) {
+  const struct sockaddr *addr;
+  grpc_resolved_address addr4_normalized;
+  if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr4_normalized)) {
+    resolved_addr = &addr4_normalized;
   }
+  addr = (const struct sockaddr *)resolved_addr->addr;
   if (addr->sa_family == AF_INET) {
     /* Check for 0.0.0.0 */
     const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
@@ -114,39 +123,45 @@
   }
 }
 
-void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
-                                  struct sockaddr_in6 *wild6_out) {
+void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address *wild4_out,
+                                  grpc_resolved_address *wild6_out) {
   grpc_sockaddr_make_wildcard4(port, wild4_out);
   grpc_sockaddr_make_wildcard6(port, wild6_out);
 }
 
-void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out) {
+void grpc_sockaddr_make_wildcard4(int port, grpc_resolved_address *resolved_wild_out) {
+  struct sockaddr_in *wild_out = (struct sockaddr_in *)resolved_wild_out->addr;
   GPR_ASSERT(port >= 0 && port < 65536);
-  memset(wild_out, 0, sizeof(*wild_out));
+  memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
   wild_out->sin_family = AF_INET;
   wild_out->sin_port = htons((uint16_t)port);
+  resolved_wild_out->len = sizeof(struct sockaddr_in);
 }
 
-void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out) {
+void grpc_sockaddr_make_wildcard6(int port, grpc_resolved_address *resolved_wild_out) {
+  struct sockaddr_in6 *wild_out = (struct sockaddr_in6 *)resolved_wild_out->addr;
   GPR_ASSERT(port >= 0 && port < 65536);
-  memset(wild_out, 0, sizeof(*wild_out));
+  memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
   wild_out->sin6_family = AF_INET6;
   wild_out->sin6_port = htons((uint16_t)port);
+  resolved_wild_out->len = sizeof(struct sockaddr_in6);
 }
 
-int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
+int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *resolved_addr,
                             int normalize) {
+  const struct sockaddr *addr;
   const int save_errno = errno;
-  struct sockaddr_in addr_normalized;
+  grpc_resolved_address addr_normalized;
   char ntop_buf[INET6_ADDRSTRLEN];
   const void *ip = NULL;
   int port;
   int ret;
 
   *out = NULL;
-  if (normalize && grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
-    addr = (const struct sockaddr *)&addr_normalized;
+  if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
+    resolved_addr = &addr_normalized;
   }
+  addr = (const struct sockaddr *)resolved_addr->addr;
   if (addr->sa_family == AF_INET) {
     const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
     ip = &addr4->sin_addr;
@@ -167,39 +182,43 @@
   return ret;
 }
 
-char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
+char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) {
   char *temp;
   char *result;
-  struct sockaddr_in addr_normalized;
+  grpc_resolved_address addr_normalized;
+  const struct sockaddr *addr;
 
-  if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
-    addr = (const struct sockaddr *)&addr_normalized;
+  if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
+    resolved_addr = &addr_normalized;
   }
 
+  addr = (const struct sockaddr *)resolved_addr->addr;
+
   switch (addr->sa_family) {
     case AF_INET:
-      grpc_sockaddr_to_string(&temp, addr, 0);
+      grpc_sockaddr_to_string(&temp, resolved_addr, 0);
       gpr_asprintf(&result, "ipv4:%s", temp);
       gpr_free(temp);
       return result;
     case AF_INET6:
-      grpc_sockaddr_to_string(&temp, addr, 0);
+      grpc_sockaddr_to_string(&temp, resolved_addr, 0);
       gpr_asprintf(&result, "ipv6:%s", temp);
       gpr_free(temp);
       return result;
     default:
-      return grpc_sockaddr_to_uri_unix_if_possible(addr);
+      return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
   }
 }
 
-int grpc_sockaddr_get_port(const struct sockaddr *addr) {
+int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   switch (addr->sa_family) {
     case AF_INET:
       return ntohs(((struct sockaddr_in *)addr)->sin_port);
     case AF_INET6:
       return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
     default:
-      if (grpc_is_unix_socket(addr)) {
+      if (grpc_is_unix_socket(resolved_addr)) {
         return 1;
       }
       gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
@@ -208,7 +227,8 @@
   }
 }
 
-int grpc_sockaddr_set_port(const struct sockaddr *addr, int port) {
+int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr, int port) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   switch (addr->sa_family) {
     case AF_INET:
       GPR_ASSERT(port >= 0 && port < 65536);
diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h
index 9f81992..5371e36 100644
--- a/src/core/lib/iomgr/sockaddr_utils.h
+++ b/src/core/lib/iomgr/sockaddr_utils.h
@@ -34,40 +34,40 @@
 #ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H
 #define GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H
 
-#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 
 /* Returns true if addr is an IPv4-mapped IPv6 address within the
    ::ffff:0.0.0.0/96 range, or false otherwise.
 
    If addr4_out is non-NULL, the inner IPv4 address will be copied here when
    returning true. */
-int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in *addr4_out);
+int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *addr,
+                              grpc_resolved_address *addr4_out);
 
 /* If addr is an AF_INET address, writes the corresponding ::ffff:0.0.0.0/96
    address to addr6_out and returns true.  Otherwise returns false. */
-int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
-                              struct sockaddr_in6 *addr6_out);
+int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *addr,
+                              grpc_resolved_address *addr6_out);
 
 /* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to
    *port_out (if not NULL) and returns true, otherwise returns false. */
-int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out);
+int grpc_sockaddr_is_wildcard(const grpc_resolved_address *addr, int *port_out);
 
 /* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */
-void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
-                                  struct sockaddr_in6 *wild6_out);
+void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address *wild4_out,
+                                  grpc_resolved_address *wild6_out);
 
 /* Writes 0.0.0.0:port. */
-void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out);
+void grpc_sockaddr_make_wildcard4(int port, grpc_resolved_address *wild_out);
 
 /* Writes [::]:port. */
-void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out);
+void grpc_sockaddr_make_wildcard6(int port, grpc_resolved_address *wild_out);
 
 /* Return the IP port number of a sockaddr */
-int grpc_sockaddr_get_port(const struct sockaddr *addr);
+int grpc_sockaddr_get_port(const grpc_resolved_address *addr);
 
 /* Set IP port number of a sockaddr */
-int grpc_sockaddr_set_port(const struct sockaddr *addr, int port);
+int grpc_sockaddr_set_port(const grpc_resolved_address *addr, int port);
 
 /* Converts a sockaddr into a newly-allocated human-readable string.
 
@@ -81,9 +81,9 @@
 
    In the unlikely event of an error, returns -1 and sets *out to NULL.
    The existing value of errno is always preserved. */
-int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
+int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
                             int normalize);
 
-char *grpc_sockaddr_to_uri(const struct sockaddr *addr);
+char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr);
 
 #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/core/lib/iomgr/socket_utils.h b/src/core/lib/iomgr/socket_utils.h
index b01197a..cc3ee2e 100644
--- a/src/core/lib/iomgr/socket_utils.h
+++ b/src/core/lib/iomgr/socket_utils.h
@@ -34,17 +34,9 @@
 #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H
 #define GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H
 
-#include "src/core/lib/iomgr/port.h"
-
-#if defined(GRPC_WINSOCK_SOCKET)
-#include "src/core/lib/iomgr/sockaddr_windows.h"
-#elif defined(GRPC_POSIX_SOCKET)
-#include "src/core/lib/iomgr/sockaddr_posix.h"
-#elif defined(GRPC_UV)
-#include <uv.h>
-#endif
+#include <stddef.h>
 
 /* A wrapper for inet_ntop on POSIX systems and InetNtop on Windows systems */
-const char *grpc_inet_ntop(int af, const void *src, char *dst, socklen_t size);
+const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size);
 
 #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H */
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.c b/src/core/lib/iomgr/socket_utils_common_posix.c
index aa844da..239b9b8 100644
--- a/src/core/lib/iomgr/socket_utils_common_posix.c
+++ b/src/core/lib/iomgr/socket_utils_common_posix.c
@@ -254,7 +254,7 @@
   }
 }
 
-static grpc_error *error_for_fd(int fd, const struct sockaddr *addr) {
+static grpc_error *error_for_fd(int fd, const grpc_resolved_address *addr) {
   if (fd >= 0) return GRPC_ERROR_NONE;
   char *addr_str;
   grpc_sockaddr_to_string(&addr_str, addr, 0);
@@ -264,10 +264,12 @@
   return err;
 }
 
-grpc_error *grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
+grpc_error *grpc_create_dualstack_socket(const grpc_resolved_address *resolved_addr,
+                                         int type,
                                          int protocol,
                                          grpc_dualstack_mode *dsmode,
                                          int *newfd) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   int family = addr->sa_family;
   if (family == AF_INET6) {
     if (grpc_ipv6_loopback_available()) {
@@ -282,9 +284,9 @@
       return GRPC_ERROR_NONE;
     }
     /* If this isn't an IPv4 address, then return whatever we've got. */
-    if (!grpc_sockaddr_is_v4mapped(addr, NULL)) {
+    if (!grpc_sockaddr_is_v4mapped(resolved_addr, NULL)) {
       *dsmode = GRPC_DSMODE_IPV6;
-      return error_for_fd(*newfd, addr);
+      return error_for_fd(*newfd, resolved_addr);
     }
     /* Fall back to AF_INET. */
     if (*newfd >= 0) {
@@ -294,11 +296,12 @@
   }
   *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
   *newfd = socket(family, type, protocol);
-  return error_for_fd(*newfd, addr);
+  return error_for_fd(*newfd, resolved_addr);
 }
 
-const char *grpc_inet_ntop(int af, const void *src, char *dst, socklen_t size) {
-  return inet_ntop(af, src, dst, size);
+const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) {
+  GPR_ASSERT(size <= (socklen_t)-1);
+  return inet_ntop(af, src, dst, (socklen_t)size);
 }
 
 #endif
diff --git a/src/core/lib/iomgr/socket_utils_linux.c b/src/core/lib/iomgr/socket_utils_linux.c
index 3ebc3f1..627b9d6 100644
--- a/src/core/lib/iomgr/socket_utils_linux.c
+++ b/src/core/lib/iomgr/socket_utils_linux.c
@@ -35,17 +35,22 @@
 
 #ifdef GRPC_LINUX_SOCKETUTILS
 
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/socket_utils_posix.h"
 
+#include <grpc/support/log.h>
+
 #include <sys/socket.h>
 #include <sys/types.h>
 
-int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+int grpc_accept4(int sockfd, grpc_resolved_address *resolved_addr,
                  int nonblock, int cloexec) {
   int flags = 0;
+  GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
+  GPR_ASSERT(resolved_addr->len <= (socklen_t)-1);
   flags |= nonblock ? SOCK_NONBLOCK : 0;
   flags |= cloexec ? SOCK_CLOEXEC : 0;
-  return accept4(sockfd, addr, addrlen, flags);
+  return accept4(sockfd, (struct sockaddr *)resolved_addr->addr, (socklen_t *)&resolved_addr->len, flags);
 }
 
 #endif
diff --git a/src/core/lib/iomgr/socket_utils_posix.c b/src/core/lib/iomgr/socket_utils_posix.c
index 4f26773..0f2622e 100644
--- a/src/core/lib/iomgr/socket_utils_posix.c
+++ b/src/core/lib/iomgr/socket_utils_posix.c
@@ -42,12 +42,14 @@
 #include <unistd.h>
 
 #include <grpc/support/log.h>
+#include "src/core/lib/iomgr/sockaddr.h"
 
-int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+int grpc_accept4(int sockfd, grpc_resolved_address *resolved_addr,
                  int nonblock, int cloexec) {
   int fd, flags;
-
-  fd = accept(sockfd, addr, addrlen);
+  GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
+  GPR_ASSERT(resolved_addr->len <= (socklen_t)-1);
+  fd = accept(sockfd, (struct sockaddr *)resolved_addr->addr, (socklen_t)resolved_addr->len);
   if (fd >= 0) {
     if (nonblock) {
       flags = fcntl(fd, F_GETFL, 0);
diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h
index 7bcc221..432cba4 100644
--- a/src/core/lib/iomgr/socket_utils_posix.h
+++ b/src/core/lib/iomgr/socket_utils_posix.h
@@ -34,13 +34,15 @@
 #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H
 #define GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H
 
+#include "src/core/lib/iomgr/resolve_address.h"
+
 #include <sys/socket.h>
 #include <unistd.h>
 
 #include "src/core/lib/iomgr/error.h"
 
 /* a wrapper for accept or accept4 */
-int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+int grpc_accept4(int sockfd, grpc_resolved_address *resolved_addr,
                  int nonblock, int cloexec);
 
 /* set a socket to non blocking mode */
@@ -125,7 +127,7 @@
      IPv4, so that bind() or connect() see the correct family.
    Also, it's important to distinguish between DUALSTACK and IPV6 when
    listening on the [::] wildcard address. */
-grpc_error *grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
+grpc_error *grpc_create_dualstack_socket(const grpc_resolved_address *addr, int type,
                                          int protocol,
                                          grpc_dualstack_mode *dsmode,
                                          int *newfd);
diff --git a/src/core/lib/iomgr/socket_utils_uv.c b/src/core/lib/iomgr/socket_utils_uv.c
index 7f61384..741bf28 100644
--- a/src/core/lib/iomgr/socket_utils_uv.c
+++ b/src/core/lib/iomgr/socket_utils_uv.c
@@ -41,9 +41,8 @@
 
 #include <grpc/support/log.h>
 
-const char *grpc_inet_ntop(int af, const void *src, char *dst, socklen_t size) {
-  GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
-  uv_inet_ntop(af, src, dst, (size_t)size);
+const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) {
+  uv_inet_ntop(af, src, dst, size);
   return dst;
 }
 
diff --git a/src/core/lib/iomgr/socket_utils_windows.c b/src/core/lib/iomgr/socket_utils_windows.c
index 09dabd7..628ad4a 100644
--- a/src/core/lib/iomgr/socket_utils_windows.c
+++ b/src/core/lib/iomgr/socket_utils_windows.c
@@ -35,14 +35,14 @@
 
 #ifdef GRPC_WINDOWS_SOCKETUTILS
 
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/socket_utils.h"
 
 #include <grpc/support/log.h>
 
-const char *grpc_inet_ntop(int af, const void *src, char *dst, socklen_t size) {
-  GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
+const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) {
   /* Windows InetNtopA wants a mutable ip pointer */
-  return InetNtopA(af, (void *)src, dst, (size_t)size);
+  return InetNtopA(af, (void *)src, dst, size);
 }
 
 #endif /* GRPC_WINDOWS_SOCKETUTILS */
diff --git a/src/core/lib/iomgr/tcp_client.h b/src/core/lib/iomgr/tcp_client.h
index a07e0b9..83e6900 100644
--- a/src/core/lib/iomgr/tcp_client.h
+++ b/src/core/lib/iomgr/tcp_client.h
@@ -37,6 +37,7 @@
 #include <grpc/support/time.h>
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/pollset_set.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 
 /* Asynchronously connect to an address (specified as (addr, len)), and call
@@ -47,7 +48,7 @@
 void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_connect,
                              grpc_endpoint **endpoint,
                              grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr, size_t addr_len,
+                             const grpc_resolved_address *addr,
                              gpr_timespec deadline);
 
 #endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H */
diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c
index 4c1dcd6..eda3279 100644
--- a/src/core/lib/iomgr/tcp_client_posix.c
+++ b/src/core/lib/iomgr/tcp_client_posix.c
@@ -71,7 +71,7 @@
   grpc_closure *closure;
 } async_connect;
 
-static grpc_error *prepare_socket(const struct sockaddr *addr, int fd) {
+static grpc_error *prepare_socket(const grpc_resolved_address *addr, int fd) {
   grpc_error *err = GRPC_ERROR_NONE;
 
   GPR_ASSERT(fd >= 0);
@@ -227,14 +227,14 @@
 static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
                                     grpc_closure *closure, grpc_endpoint **ep,
                                     grpc_pollset_set *interested_parties,
-                                    const struct sockaddr *addr,
-                                    size_t addr_len, gpr_timespec deadline) {
+                                    const grpc_resolved_address *addr,
+                                    gpr_timespec deadline) {
   int fd;
   grpc_dualstack_mode dsmode;
   int err;
   async_connect *ac;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in addr4_copy;
+  grpc_resolved_address addr6_v4mapped;
+  grpc_resolved_address addr4_copy;
   grpc_fd *fdobj;
   char *name;
   char *addr_str;
@@ -244,8 +244,7 @@
 
   /* Use dualstack sockets where available. */
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
+    addr = &addr6_v4mapped;
   }
 
   error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
@@ -256,8 +255,7 @@
   if (dsmode == GRPC_DSMODE_IPV4) {
     /* If we got an AF_INET socket, map the address back to IPv4. */
     GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
-    addr = (struct sockaddr *)&addr4_copy;
-    addr_len = sizeof(addr4_copy);
+    addr = &addr4_copy;
   }
   if ((error = prepare_socket(addr, fd)) != GRPC_ERROR_NONE) {
     grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
@@ -265,8 +263,8 @@
   }
 
   do {
-    GPR_ASSERT(addr_len < ~(socklen_t)0);
-    err = connect(fd, addr, (socklen_t)addr_len);
+    GPR_ASSERT(addr->len < ~(socklen_t)0);
+    err = connect(fd, (const struct sockaddr *)addr->addr, (socklen_t)addr->len);
   } while (err < 0 && errno == EINTR);
 
   addr_str = grpc_sockaddr_to_uri(addr);
@@ -321,16 +319,16 @@
 // overridden by api_fuzzer.c
 void (*grpc_tcp_client_connect_impl)(
     grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
-    grpc_pollset_set *interested_parties, const struct sockaddr *addr,
-    size_t addr_len, gpr_timespec deadline) = tcp_client_connect_impl;
+    grpc_pollset_set *interested_parties, const grpc_resolved_address *addr,
+    gpr_timespec deadline) = tcp_client_connect_impl;
 
 void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
                              grpc_endpoint **ep,
                              grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr, size_t addr_len,
+                             const grpc_resolved_address *addr,
                              gpr_timespec deadline) {
   grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, addr,
-                               addr_len, deadline);
+                               deadline);
 }
 
 #endif
diff --git a/src/core/lib/iomgr/tcp_client_uv.c b/src/core/lib/iomgr/tcp_client_uv.c
index 7823a1d..bed64eb 100644
--- a/src/core/lib/iomgr/tcp_client_uv.c
+++ b/src/core/lib/iomgr/tcp_client_uv.c
@@ -118,8 +118,8 @@
 void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx,
                              grpc_closure *closure, grpc_endpoint **ep,
                              grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr,
-                             size_t addr_len, gpr_timespec deadline) {
+                             const grpc_resolved_address *resolved_addr,
+                             gpr_timespec deadline) {
   grpc_uv_tcp_connect *connect;
   (void)interested_parties;
   connect = gpr_malloc(sizeof(grpc_uv_tcp_connect));
@@ -128,11 +128,12 @@
   connect->endpoint = ep;
   connect->tcp_handle = gpr_malloc(sizeof(uv_tcp_t));
   gpr_log(GPR_DEBUG, "Allocated uv_tcp_t handle %p", connect->tcp_handle);
-  connect->addr_name = grpc_sockaddr_to_uri(addr);
+  connect->addr_name = grpc_sockaddr_to_uri(resolved_addr);
   uv_tcp_init(uv_default_loop(), connect->tcp_handle);
   connect->connect_req.data = connect;
   // TODO(murgatroid99): figure out what the return value here means
-  uv_tcp_connect(&connect->connect_req, connect->tcp_handle, addr,
+  uv_tcp_connect(&connect->connect_req, connect->tcp_handle,
+                 (const struct sockaddr *)resolved_addr->addr,
                  uv_tc_on_connect);
   grpc_timer_init(exec_ctx, &connect->alarm,
                   gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
diff --git a/src/core/lib/iomgr/tcp_client_windows.c b/src/core/lib/iomgr/tcp_client_windows.c
index 29775cc..c987a3c 100644
--- a/src/core/lib/iomgr/tcp_client_windows.c
+++ b/src/core/lib/iomgr/tcp_client_windows.c
@@ -129,13 +129,13 @@
 void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
                              grpc_endpoint **endpoint,
                              grpc_pollset_set *interested_parties,
-                             const struct sockaddr *addr, size_t addr_len,
+                             const grpc_resolved_address *addr,
                              gpr_timespec deadline) {
   SOCKET sock = INVALID_SOCKET;
   BOOL success;
   int status;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in6 local_address;
+  grpc_resolved_address addr6_v4mapped;
+  grpc_resolved_address local_address;
   async_connect *ac;
   grpc_winsocket *socket = NULL;
   LPFN_CONNECTEX ConnectEx;
@@ -148,8 +148,7 @@
 
   /* Use dualstack sockets where available. */
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
+    addr = &addr6_v4mapped;
   }
 
   sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
@@ -178,7 +177,7 @@
 
   grpc_sockaddr_make_wildcard6(0, &local_address);
 
-  status = bind(sock, (struct sockaddr *)&local_address, sizeof(local_address));
+  status = bind(sock, (struct sockaddr *)&local_address.addr, local_address.len);
   if (status != 0) {
     error = GRPC_WSA_ERROR(WSAGetLastError(), "bind");
     goto failure;
@@ -187,7 +186,7 @@
   socket = grpc_winsocket_create(sock, "client");
   info = &socket->write_info;
   success =
-      ConnectEx(sock, addr, (int)addr_len, NULL, 0, NULL, &info->overlapped);
+      ConnectEx(sock, (struct sockaddr *)&addr->addr, (int)addr->len, NULL, 0, NULL, &info->overlapped);
 
   /* It wouldn't be unusual to get a success immediately. But we'll still get
      an IOCP notification, so let's ignore it. */
diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h
index 5a25d39..20495e8 100644
--- a/src/core/lib/iomgr/tcp_server.h
+++ b/src/core/lib/iomgr/tcp_server.h
@@ -38,6 +38,7 @@
 
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 
 /* Forward decl of grpc_tcp_server */
 typedef struct grpc_tcp_server grpc_tcp_server;
@@ -78,8 +79,9 @@
    but not dualstack sockets. */
 /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
                   all of the multiple socket port matching logic in one place */
-grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                                     size_t addr_len, int *out_port);
+grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
+                                     const grpc_resolved_address *addr,
+                                     int *out_port);
 
 /* Number of fds at the given port_index, or 0 if port_index is out of
    bounds. */
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index c1254d4..6ef7a71 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -62,6 +62,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/socket_utils_posix.h"
 #include "src/core/lib/iomgr/tcp_posix.h"
@@ -79,11 +80,14 @@
   int fd;
   grpc_fd *emfd;
   grpc_tcp_server *server;
+  grpc_resolved_address addr;
+  /*
   union {
     uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE];
     struct sockaddr sockaddr;
   } addr;
   size_t addr_len;
+  */
   int port;
   unsigned port_index;
   unsigned fd_index;
@@ -235,7 +239,7 @@
   if (s->head) {
     grpc_tcp_listener *sp;
     for (sp = s->head; sp; sp = sp->next) {
-      grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
+      grpc_unlink_if_unix_domain_socket(&sp->addr);
       sp->destroyed_closure.cb = destroyed_port;
       sp->destroyed_closure.cb_arg = s;
       grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
@@ -301,11 +305,9 @@
 }
 
 /* Prepare a recently-created socket for listening. */
-static grpc_error *prepare_socket(int fd, const struct sockaddr *addr,
-                                  size_t addr_len, bool so_reuseport,
-                                  int *port) {
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
+static grpc_error *prepare_socket(int fd, const grpc_resolved_address *addr,
+                                  bool so_reuseport, int *port) {
+  grpc_resolved_address sockname_temp;
   grpc_error *err = GRPC_ERROR_NONE;
 
   GPR_ASSERT(fd >= 0);
@@ -328,8 +330,8 @@
   err = grpc_set_socket_no_sigpipe_if_possible(fd);
   if (err != GRPC_ERROR_NONE) goto error;
 
-  GPR_ASSERT(addr_len < ~(socklen_t)0);
-  if (bind(fd, addr, (socklen_t)addr_len) < 0) {
+  GPR_ASSERT(addr->len < ~(socklen_t)0);
+  if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) {
     err = GRPC_OS_ERROR(errno, "bind");
     goto error;
   }
@@ -339,13 +341,14 @@
     goto error;
   }
 
-  sockname_len = sizeof(sockname_temp);
-  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
+  sockname_temp.len = sizeof(struct sockaddr_storage);
+
+  if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, (socklen_t *)&sockname_temp.len) < 0) {
     err = GRPC_OS_ERROR(errno, "getsockname");
     goto error;
   }
 
-  *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+  *port = grpc_sockaddr_get_port(&sockname_temp);
   return GRPC_ERROR_NONE;
 
 error:
@@ -379,13 +382,13 @@
 
   /* loop until accept4 returns EAGAIN, and then re-arm notification */
   for (;;) {
-    struct sockaddr_storage addr;
-    socklen_t addrlen = sizeof(addr);
+    grpc_resolved_address addr;
     char *addr_str;
     char *name;
+    addr.len = sizeof(struct sockaddr_storage);
     /* Note: If we ever decide to return this address to the user, remember to
        strip off the ::ffff:0.0.0.0/96 prefix first. */
-    int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
+    int fd = grpc_accept4(sp->fd, &addr, 1, 1);
     if (fd < 0) {
       switch (errno) {
         case EINTR:
@@ -401,7 +404,7 @@
 
     grpc_set_socket_no_sigpipe_if_possible(fd);
 
-    addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
+    addr_str = grpc_sockaddr_to_uri(&addr);
     gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
 
     if (grpc_tcp_trace) {
@@ -439,8 +442,8 @@
 }
 
 static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
-                                        const struct sockaddr *addr,
-                                        size_t addr_len, unsigned port_index,
+                                        const grpc_resolved_address *addr,
+                                        unsigned port_index,
                                         unsigned fd_index,
                                         grpc_tcp_listener **listener) {
   grpc_tcp_listener *sp = NULL;
@@ -448,10 +451,10 @@
   char *addr_str;
   char *name;
 
-  grpc_error *err = prepare_socket(fd, addr, addr_len, s->so_reuseport, &port);
+  grpc_error *err = prepare_socket(fd, addr, s->so_reuseport, &port);
   if (err == GRPC_ERROR_NONE) {
     GPR_ASSERT(port > 0);
-    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
+    grpc_sockaddr_to_string(&addr_str, addr, 1);
     gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
     gpr_mu_lock(&s->mu);
     s->nports++;
@@ -467,8 +470,7 @@
     sp->server = s;
     sp->fd = fd;
     sp->emfd = grpc_fd_create(fd, name);
-    memcpy(sp->addr.untyped, addr, addr_len);
-    sp->addr_len = addr_len;
+    memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
     sp->port = port;
     sp->port_index = port_index;
     sp->fd_index = fd_index;
@@ -501,14 +503,13 @@
     int fd = -1;
     int port = -1;
     grpc_dualstack_mode dsmode;
-    err = grpc_create_dualstack_socket(&listener->addr.sockaddr, SOCK_STREAM, 0,
+    err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0,
                                        &dsmode, &fd);
     if (err != GRPC_ERROR_NONE) return err;
-    err = prepare_socket(fd, &listener->addr.sockaddr, listener->addr_len, true,
-                         &port);
+    err = prepare_socket(fd, &listener->addr, true, &port);
     if (err != GRPC_ERROR_NONE) return err;
     listener->server->nports++;
-    grpc_sockaddr_to_string(&addr_str, &listener->addr.sockaddr, 1);
+    grpc_sockaddr_to_string(&addr_str, &listener->addr, 1);
     gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i);
     sp = gpr_malloc(sizeof(grpc_tcp_listener));
     sp->next = listener->next;
@@ -521,8 +522,7 @@
     sp->server = listener->server;
     sp->fd = fd;
     sp->emfd = grpc_fd_create(fd, name);
-    memcpy(sp->addr.untyped, listener->addr.untyped, listener->addr_len);
-    sp->addr_len = listener->addr_len;
+    memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address));
     sp->port = port;
     sp->port_index = listener->port_index;
     sp->fd_index = listener->fd_index + count - i;
@@ -537,19 +537,19 @@
   return GRPC_ERROR_NONE;
 }
 
-grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                                     size_t addr_len, int *out_port) {
+grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
+                                     const grpc_resolved_address *addr,
+                                     int *out_port) {
   grpc_tcp_listener *sp;
   grpc_tcp_listener *sp2 = NULL;
   int fd;
   grpc_dualstack_mode dsmode;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in wild4;
-  struct sockaddr_in6 wild6;
-  struct sockaddr_in addr4_copy;
-  struct sockaddr *allocated_addr = NULL;
-  struct sockaddr_storage sockname_temp;
-  socklen_t sockname_len;
+  grpc_resolved_address addr6_v4mapped;
+  grpc_resolved_address wild4;
+  grpc_resolved_address wild6;
+  grpc_resolved_address addr4_copy;
+  grpc_resolved_address *allocated_addr = NULL;
+  grpc_resolved_address sockname_temp;
   int port;
   unsigned port_index = 0;
   unsigned fd_index = 0;
@@ -557,19 +557,19 @@
   if (s->tail != NULL) {
     port_index = s->tail->port_index + 1;
   }
-  grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);
+  grpc_unlink_if_unix_domain_socket(addr);
 
   /* Check if this is a wildcard port, and if so, try to keep the port the same
      as some previously created listener. */
   if (grpc_sockaddr_get_port(addr) == 0) {
     for (sp = s->head; sp; sp = sp->next) {
-      sockname_len = sizeof(sockname_temp);
-      if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
-                           &sockname_len)) {
-        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+      sockname_temp.len = sizeof(struct sockaddr_storage);
+      if (0 == getsockname(sp->fd, (struct sockaddr *)sockname_temp.addr,
+                           (socklen_t *)&sockname_temp.len)) {
+        port = grpc_sockaddr_get_port(&sockname_temp);
         if (port > 0) {
-          allocated_addr = gpr_malloc(addr_len);
-          memcpy(allocated_addr, addr, addr_len);
+          allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
+          memcpy(allocated_addr, addr, addr->len);
           grpc_sockaddr_set_port(allocated_addr, port);
           addr = allocated_addr;
           break;
@@ -581,8 +581,7 @@
   sp = NULL;
 
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
+    addr = &addr6_v4mapped;
   }
 
   /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
@@ -590,12 +589,10 @@
     grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
 
     /* Try listening on IPv6 first. */
-    addr = (struct sockaddr *)&wild6;
-    addr_len = sizeof(wild6);
+    addr = &wild6;
     errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
     if (errs[0] == GRPC_ERROR_NONE) {
-      errs[0] = add_socket_to_server(s, fd, addr, addr_len, port_index,
-                                     fd_index, &sp);
+      errs[0] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
       if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
         goto done;
       }
@@ -604,23 +601,20 @@
       }
       /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
       if (port == 0 && sp != NULL) {
-        grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
+        grpc_sockaddr_set_port(&wild4, sp->port);
       }
     }
-    addr = (struct sockaddr *)&wild4;
-    addr_len = sizeof(wild4);
+    addr = &wild4;
   }
 
   errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
   if (errs[1] == GRPC_ERROR_NONE) {
     if (dsmode == GRPC_DSMODE_IPV4 &&
         grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
-      addr = (struct sockaddr *)&addr4_copy;
-      addr_len = sizeof(addr4_copy);
+      addr = &addr4_copy;
     }
     sp2 = sp;
-    errs[1] =
-        add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index, &sp);
+    errs[1] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
     if (sp2 != NULL && sp != NULL) {
       sp2->sibling = sp;
       sp->is_sibling = 1;
@@ -695,7 +689,7 @@
   s->pollset_count = pollset_count;
   sp = s->head;
   while (sp != NULL) {
-    if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr.sockaddr) &&
+    if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr) &&
         pollset_count > 1) {
       GPR_ASSERT(GRPC_LOG_IF_ERROR(
           "clone_port", clone_port(sp, (unsigned)(pollset_count - 1))));
diff --git a/src/core/lib/iomgr/tcp_server_uv.c b/src/core/lib/iomgr/tcp_server_uv.c
index b69e708..2d57715 100644
--- a/src/core/lib/iomgr/tcp_server_uv.c
+++ b/src/core/lib/iomgr/tcp_server_uv.c
@@ -42,6 +42,7 @@
 
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/tcp_server.h"
 #include "src/core/lib/iomgr/tcp_uv.h"
@@ -171,8 +172,7 @@
   uv_tcp_t *client;
   grpc_endpoint *ep = NULL;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  struct sockaddr_storage peer_name;
-  int peer_name_len = sizeof(peer_name);
+  grpc_resolved_address peer_name;
   char *peer_name_string;
   int err;
 
@@ -189,10 +189,12 @@
   // UV documentation says this is guaranteed to succeed
   uv_accept((uv_stream_t *)server, (uv_stream_t *)client);
   peer_name_string = NULL;
-  err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name,
-                           &peer_name_len);
+  memset(&peer_name, 0, sizeof(grpc_resolved_address));
+  peer_name.len = sizeof(struct sockaddr_storage);
+  err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name.addr,
+                           (int*)&peer_name.len);
   if (err == 0) {
-    peer_name_string = grpc_sockaddr_to_uri((struct sockaddr *)&peer_name);
+    peer_name_string = grpc_sockaddr_to_uri(&peer_name);
   } else {
     gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s",
             uv_strerror(status));
@@ -206,18 +208,17 @@
 
 static grpc_error *add_socket_to_server(grpc_tcp_server *s,
                                         uv_tcp_t *handle,
-                                        struct sockaddr *addr,
-                                        size_t addr_len, unsigned port_index,
+                                        const grpc_resolved_address *addr,
+                                        unsigned port_index,
                                         grpc_tcp_listener **listener) {
   grpc_tcp_listener *sp = NULL;
   int port = -1;
   int status;
   grpc_error *error;
-  struct sockaddr_storage sockname_temp;
-  int sockname_len;
+  grpc_resolved_address sockname_temp;
 
   // The last argument to uv_tcp_bind is flags
-  status = uv_tcp_bind(handle, addr, 0);
+  status = uv_tcp_bind(handle, (struct sockaddr *)addr->addr, 0);
   if (status != 0) {
     error = GRPC_ERROR_CREATE("Failed to bind to port");
     error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
@@ -225,9 +226,9 @@
     return error;
   }
 
-  sockname_len = (int)sizeof(sockname_temp);
-  status = uv_tcp_getsockname(handle, (struct sockaddr *)&sockname_temp,
-                              &sockname_len);
+  sockname_temp.len = (int)sizeof(struct sockaddr_storage);
+  status = uv_tcp_getsockname(handle, (struct sockaddr *)&sockname_temp.addr,
+                              (int *)&sockname_temp.len);
   if (status != 0) {
     error = GRPC_ERROR_CREATE("getsockname failed");
     error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
@@ -235,7 +236,7 @@
     return error;
   }
 
-  port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+  port = grpc_sockaddr_get_port(&sockname_temp);
 
   GPR_ASSERT(port >= 0);
   GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
@@ -259,16 +260,16 @@
   return GRPC_ERROR_NONE;
 }
 
-grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                                     size_t addr_len, int *port) {
+grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
+                                     const grpc_resolved_address *addr,
+                                     int *port) {
   // This function is mostly copied from tcp_server_windows.c
   grpc_tcp_listener *sp = NULL;
   uv_tcp_t *handle;
-  struct sockaddr_in6 addr6_v4mapped;
-  struct sockaddr_in6 wildcard;
-  struct sockaddr *allocated_addr = NULL;
-  struct sockaddr_storage sockname_temp;
-  int sockname_len;
+  grpc_resolved_address addr6_v4mapped;
+  grpc_resolved_address wildcard;
+  grpc_resolved_address *allocated_addr = NULL;
+  grpc_resolved_address sockname_temp;
   unsigned port_index = 0;
   int status;
   grpc_error *error = GRPC_ERROR_NONE;
@@ -281,13 +282,13 @@
      as some previously created listener. */
   if (grpc_sockaddr_get_port(addr) == 0) {
     for (sp = s->head; sp; sp = sp->next) {
-      sockname_len = sizeof(sockname_temp);
-      if (0 == uv_tcp_getsockname(sp->handle, (struct sockaddr *)&sockname_temp,
-                                  &sockname_len)) {
-        *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+      sockname_temp.len = sizeof(struct sockaddr_storage);
+      if (0 == uv_tcp_getsockname(sp->handle, (struct sockaddr *)&sockname_temp.addr,
+                                  (int *)&sockname_temp.len)) {
+        *port = grpc_sockaddr_get_port(&sockname_temp);
         if (*port > 0) {
-          allocated_addr = gpr_malloc(addr_len);
-          memcpy(allocated_addr, addr, addr_len);
+          allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
+          memcpy(allocated_addr, addr, sizeof(grpc_resolved_address));
           grpc_sockaddr_set_port(allocated_addr, *port);
           addr = allocated_addr;
           break;
@@ -297,24 +298,21 @@
   }
 
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
-    addr = (const struct sockaddr *)&addr6_v4mapped;
-    addr_len = sizeof(addr6_v4mapped);
+    addr = &addr6_v4mapped;
   }
 
   /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
   if (grpc_sockaddr_is_wildcard(addr, port)) {
     grpc_sockaddr_make_wildcard6(*port, &wildcard);
 
-    addr = (struct sockaddr *)&wildcard;
-    addr_len = sizeof(wildcard);
+    addr = &wildcard;
   }
 
   handle = gpr_malloc(sizeof(uv_tcp_t));
   gpr_log(GPR_DEBUG, "Allocating uv_tcp_t handle %p", handle);
   status = uv_tcp_init(uv_default_loop(), handle);
   if (status == 0) {
-    error = add_socket_to_server(s, handle, (struct sockaddr *)addr, addr_len,
-                                 port_index, &sp);
+    error = add_socket_to_server(s, handle, addr, port_index, &sp);
   } else {
     error = GRPC_ERROR_CREATE("Failed to initialize UV tcp handle");
     error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
diff --git a/src/core/lib/iomgr/timer_uv.c b/src/core/lib/iomgr/timer_uv.c
index ffeb08c..d280c8b 100644
--- a/src/core/lib/iomgr/timer_uv.c
+++ b/src/core/lib/iomgr/timer_uv.c
@@ -68,6 +68,7 @@
                      gpr_timespec deadline, grpc_iomgr_cb_func timer_cb,
                      void *timer_cb_arg, gpr_timespec now) {
   uint64_t timeout;
+  uv_timer_t *uv_timer;
   grpc_closure_init(&timer->closure, timer_cb, timer_cb_arg);
   if (gpr_time_cmp(deadline, now) <= 0) {
     timer->triggered = 1;
@@ -77,10 +78,11 @@
   timer->triggered = 0;
   timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
   gpr_log(GPR_DEBUG, "Setting timer %p: %lu", timer, timeout);
-  timer->uv_timer = gpr_malloc(sizeof(uv_timer_t));
-  uv_timer_init(uv_default_loop(), timer->uv_timer);
-  timer->uv_timer->data = timer;
-  uv_timer_start(timer->uv_timer, run_expired_timer, timeout, 0);
+  uv_timer = gpr_malloc(sizeof(uv_timer_t));
+  uv_timer_init(uv_default_loop(), uv_timer);
+  uv_timer->data = timer;
+  timer->uv_timer = uv_timer;
+  uv_timer_start(uv_timer, run_expired_timer, timeout, 0);
 }
 
 void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
@@ -88,7 +90,7 @@
     gpr_log(GPR_DEBUG, "Running cancelled timer callback");
     timer->triggered = 1;
     grpc_exec_ctx_sched(exec_ctx, &timer->closure, GRPC_ERROR_CANCELLED, NULL);
-    stop_uv_timer(timer->uv_timer);
+    stop_uv_timer((uv_timer_t*)timer->uv_timer);
   }
 }
 
diff --git a/src/core/lib/iomgr/timer_uv.h b/src/core/lib/iomgr/timer_uv.h
index d78d6a6..b64291b 100644
--- a/src/core/lib/iomgr/timer_uv.h
+++ b/src/core/lib/iomgr/timer_uv.h
@@ -34,13 +34,13 @@
 #ifndef GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H
 #define GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H
 
-#include <uv.h>
-
 #include "src/core/lib/iomgr/exec_ctx.h"
 
 struct grpc_timer {
   grpc_closure closure;
-  uv_timer_t *uv_timer;
+  /* This is actually a uv_timer_t*, but we want to keep platform-specific
+     types out of headers */
+  void *uv_timer;
   int triggered;
 };
 
diff --git a/src/core/lib/iomgr/unix_sockets_posix.c b/src/core/lib/iomgr/unix_sockets_posix.c
index 33082a2..830a0c9 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.c
+++ b/src/core/lib/iomgr/unix_sockets_posix.c
@@ -34,6 +34,8 @@
 
 #ifdef GRPC_HAVE_UNIX_SOCKET
 
+#include "src/core/lib/iomgr/sockaddr.h"
+
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -62,15 +64,17 @@
   return GRPC_ERROR_NONE;
 }
 
-int grpc_is_unix_socket(const struct sockaddr *addr) {
+int grpc_is_unix_socket(const grpc_resolved_address *resolved_addr) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   return addr->sa_family == AF_UNIX;
 }
 
-void grpc_unlink_if_unix_domain_socket(const struct sockaddr *addr) {
+void grpc_unlink_if_unix_domain_socket(const grpc_resolved_address *resolved_addr) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   if (addr->sa_family != AF_UNIX) {
     return;
   }
-  struct sockaddr_un *un = (struct sockaddr_un *)addr;
+  struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
   struct stat st;
 
   if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
@@ -78,13 +82,15 @@
   }
 }
 
-char *grpc_sockaddr_to_uri_unix_if_possible(const struct sockaddr *addr) {
+char *grpc_sockaddr_to_uri_unix_if_possible(const grpc_resolved_address *resolved_addr) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   if (addr->sa_family != AF_UNIX) {
     return NULL;
   }
 
   char *result;
-  gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
+  gpr_asprintf(&result, "unix:%s",
+               ((struct sockaddr_un *)addr)->sun_path);
   return result;
 }
 
diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h
index 5458f6a..0ce4831 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.h
+++ b/src/core/lib/iomgr/unix_sockets_posix.h
@@ -39,17 +39,16 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/iomgr/resolve_address.h"
-#include "src/core/lib/iomgr/sockaddr.h"
 
 void grpc_create_socketpair_if_unix(int sv[2]);
 
 grpc_error *grpc_resolve_unix_domain_address(
     const char *name, grpc_resolved_addresses **addresses);
 
-int grpc_is_unix_socket(const struct sockaddr *addr);
+int grpc_is_unix_socket(const grpc_resolved_address *resolved_addr);
 
-void grpc_unlink_if_unix_domain_socket(const struct sockaddr *addr);
+void grpc_unlink_if_unix_domain_socket(const grpc_resolved_address *resolved_addr);
 
-char *grpc_sockaddr_to_uri_unix_if_possible(const struct sockaddr *addr);
+char *grpc_sockaddr_to_uri_unix_if_possible(const grpc_resolved_address *resolved_addr);
 
 #endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */
diff --git a/src/core/lib/iomgr/unix_sockets_posix_noop.c b/src/core/lib/iomgr/unix_sockets_posix_noop.c
index 82f008d..1daf515 100644
--- a/src/core/lib/iomgr/unix_sockets_posix_noop.c
+++ b/src/core/lib/iomgr/unix_sockets_posix_noop.c
@@ -50,11 +50,11 @@
   return GRPC_ERROR_CREATE("Unix domain sockets are not supported on Windows");
 }
 
-int grpc_is_unix_socket(const struct sockaddr *addr) { return false; }
+int grpc_is_unix_socket(const grpc_resolved_address *addr) { return false; }
 
-void grpc_unlink_if_unix_domain_socket(const struct sockaddr *addr) {}
+void grpc_unlink_if_unix_domain_socket(const grpc_resolved_address *addr) {}
 
-char *grpc_sockaddr_to_uri_unix_if_possible(const struct sockaddr *addr) {
+char *grpc_sockaddr_to_uri_unix_if_possible(const grpc_resolved_address *addr) {
   return NULL;
 }
 
diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c
index 45e259e..2204fad 100644
--- a/src/core/lib/security/context/security_context.c
+++ b/src/core/lib/security/context/security_context.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <string.h>
 
 #include "src/core/lib/security/context/security_context.h"
diff --git a/src/core/lib/security/context/security_context.h b/src/core/lib/security/context/security_context.h
index a55153b..1e131a0 100644
--- a/src/core/lib/security/context/security_context.h
+++ b/src/core/lib/security/context/security_context.h
@@ -34,11 +34,6 @@
 #ifndef GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H
 #define GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include "src/core/lib/iomgr/pollset.h"
 #include "src/core/lib/security/credentials/credentials.h"
 
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index bfdfcb6..8e9d842 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -34,11 +34,6 @@
 #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H
 #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 #include <grpc/support/sync.h>
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index e9638c5..c22ea5c 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
 
 #include <string.h>
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 34d8a13..b2c6815 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <string.h>
 
 #include "src/core/lib/security/context/security_context.h"
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 65a9822..3f09359 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include <assert.h>
 #include <limits.h>
 #include <stdio.h>
diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c
index 9a9342f..7ee7b51 100644
--- a/src/core/lib/surface/init_secure.c
+++ b/src/core/lib/surface/init_secure.c
@@ -31,11 +31,6 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
-
 #include "src/core/lib/surface/init.h"
 
 #include <limits.h>
diff --git a/src/core/lib/tsi/ssl_transport_security.c b/src/core/lib/tsi/ssl_transport_security.c
index 116b66a..e59b661 100644
--- a/src/core/lib/tsi/ssl_transport_security.c
+++ b/src/core/lib/tsi/ssl_transport_security.c
@@ -31,10 +31,7 @@
  *
  */
 
-/* We currently need this at the top of the file if we import some iomgr
-   headers because if we are building with libuv, those headers will include
-   uv.h, which needs to be included before other system headers */
-#include "src/core/lib/iomgr/port.h"
+#include "src/core/lib/iomgr/sockaddr.h"
 
 #include "src/core/lib/tsi/ssl_transport_security.h"
 #include "src/core/lib/iomgr/socket_utils.h"
diff --git a/test/core/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c
index 1b51424..dcff859 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -93,15 +93,14 @@
   grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
 }
 
-static void set_magic_initial_string(struct sockaddr **addr, size_t *addr_len,
+static void set_magic_initial_string(grpc_resolved_address **addr,
                                      gpr_slice *connect_string) {
   GPR_ASSERT(addr);
-  GPR_ASSERT(addr_len);
+  GPR_ASSERT((*addr)->len);
   *connect_string = gpr_slice_from_copied_string(magic_connect_string);
 }
 
-static void reset_addr_and_set_magic_string(struct sockaddr **addr,
-                                            size_t *addr_len,
+static void reset_addr_and_set_magic_string(grpc_resolved_address **addr,
                                             gpr_slice *connect_string) {
   struct sockaddr_in target;
   *connect_string = gpr_slice_from_copied_string(magic_connect_string);
@@ -109,9 +108,9 @@
   target.sin_family = AF_INET;
   target.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
   target.sin_port = htons((uint16_t)server_port);
-  *addr_len = sizeof(target);
-  *addr = (struct sockaddr *)gpr_malloc(sizeof(target));
-  memcpy(*addr, &target, sizeof(target));
+  (*addr)->len = sizeof(target);
+  *addr = (grpc_resolved_address *)gpr_malloc(sizeof(grpc_resolved_address));
+  memcpy((*addr)->addr, &target, sizeof(target));
 }
 
 static gpr_timespec n_sec_deadline(int seconds) {
diff --git a/test/core/end2end/fixtures/h2_full+trace.c b/test/core/end2end/fixtures/h2_full+trace.c
index e25b5e3..46582e3 100644
--- a/test/core/end2end/fixtures/h2_full+trace.c
+++ b/test/core/end2end/fixtures/h2_full+trace.c
@@ -34,6 +34,7 @@
 #include "test/core/end2end/end2end_tests.h"
 
 #include <string.h>
+#include <unistd.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index d0925e5..356a359 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -34,6 +34,7 @@
 #include "test/core/end2end/end2end_tests.h"
 
 #include <string.h>
+#include <unistd.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
diff --git a/test/core/iomgr/sockaddr_utils_test.c b/test/core/iomgr/sockaddr_utils_test.c
index a330314..1f89f59 100644
--- a/test/core/iomgr/sockaddr_utils_test.c
+++ b/test/core/iomgr/sockaddr_utils_test.c
@@ -31,6 +31,7 @@
  *
  */
 
+#include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
 #include <errno.h>
@@ -41,24 +42,28 @@
 #include <grpc/support/port_platform.h>
 #include "test/core/util/test_config.h"
 
-static struct sockaddr_in make_addr4(const uint8_t *data, size_t data_len) {
-  struct sockaddr_in addr4;
-  memset(&addr4, 0, sizeof(addr4));
-  addr4.sin_family = AF_INET;
-  GPR_ASSERT(data_len == sizeof(addr4.sin_addr.s_addr));
-  memcpy(&addr4.sin_addr.s_addr, data, data_len);
-  addr4.sin_port = htons(12345);
-  return addr4;
+static grpc_resolved_address make_addr4(const uint8_t *data, size_t data_len) {
+  grpc_resolved_address resolved_addr4;
+  struct sockaddr_in *addr4 = (struct sockaddr_in *)resolved_addr4.addr;
+  memset(&resolved_addr4, 0, sizeof(resolved_addr4));
+  addr4->sin_family = AF_INET;
+  GPR_ASSERT(data_len == sizeof(addr4->sin_addr.s_addr));
+  memcpy(&addr4->sin_addr.s_addr, data, data_len);
+  addr4->sin_port = htons(12345);
+  resolved_addr4.len = sizeof(struct sockaddr_in);
+  return resolved_addr4;
 }
 
-static struct sockaddr_in6 make_addr6(const uint8_t *data, size_t data_len) {
-  struct sockaddr_in6 addr6;
-  memset(&addr6, 0, sizeof(addr6));
-  addr6.sin6_family = AF_INET6;
-  GPR_ASSERT(data_len == sizeof(addr6.sin6_addr.s6_addr));
-  memcpy(&addr6.sin6_addr.s6_addr, data, data_len);
-  addr6.sin6_port = htons(12345);
-  return addr6;
+static grpc_resolved_address make_addr6(const uint8_t *data, size_t data_len) {
+  grpc_resolved_address resolved_addr6;
+  struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)resolved_addr6.addr;
+  memset(&resolved_addr6, 0, sizeof(resolved_addr6));
+  addr6->sin6_family = AF_INET6;
+  GPR_ASSERT(data_len == sizeof(addr6->sin6_addr.s6_addr));
+  memcpy(&addr6->sin6_addr.s6_addr, data, data_len);
+  addr6->sin6_port = htons(12345);
+  resolved_addr6.len = sizeof(struct sockaddr_in6);
+  return resolved_addr6;
 }
 
 static const uint8_t kMapped[] = {0, 0, 0,    0,    0,   0, 0, 0,
@@ -72,102 +77,96 @@
                                 0,    0,    0,    0,    0, 0, 0, 1};
 
 static void test_sockaddr_is_v4mapped(void) {
-  struct sockaddr_in input4;
-  struct sockaddr_in6 input6;
-  struct sockaddr_in output4;
-  struct sockaddr_in expect4;
+  grpc_resolved_address input4;
+  grpc_resolved_address input6;
+  grpc_resolved_address output4;
+  grpc_resolved_address expect4;
 
   gpr_log(GPR_INFO, "%s", "test_sockaddr_is_v4mapped");
 
   /* v4mapped input should succeed. */
   input6 = make_addr6(kMapped, sizeof(kMapped));
-  GPR_ASSERT(grpc_sockaddr_is_v4mapped((const struct sockaddr *)&input6, NULL));
-  GPR_ASSERT(
-      grpc_sockaddr_is_v4mapped((const struct sockaddr *)&input6, &output4));
+  GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, NULL));
+  GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, &output4));
   expect4 = make_addr4(kIPv4, sizeof(kIPv4));
   GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0);
 
   /* Non-v4mapped input should fail. */
   input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped));
-  GPR_ASSERT(
-      !grpc_sockaddr_is_v4mapped((const struct sockaddr *)&input6, NULL));
-  GPR_ASSERT(
-      !grpc_sockaddr_is_v4mapped((const struct sockaddr *)&input6, &output4));
+  GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, NULL));
+  GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, &output4));
   /* Output is unchanged. */
   GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0);
 
   /* Plain IPv4 input should also fail. */
   input4 = make_addr4(kIPv4, sizeof(kIPv4));
-  GPR_ASSERT(
-      !grpc_sockaddr_is_v4mapped((const struct sockaddr *)&input4, NULL));
+  GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input4, NULL));
 }
 
 static void test_sockaddr_to_v4mapped(void) {
-  struct sockaddr_in input4;
-  struct sockaddr_in6 input6;
-  struct sockaddr_in6 output6;
-  struct sockaddr_in6 expect6;
+  grpc_resolved_address input4;
+  grpc_resolved_address input6;
+  grpc_resolved_address output6;
+  grpc_resolved_address expect6;
 
   gpr_log(GPR_INFO, "%s", "test_sockaddr_to_v4mapped");
 
   /* IPv4 input should succeed. */
   input4 = make_addr4(kIPv4, sizeof(kIPv4));
-  GPR_ASSERT(
-      grpc_sockaddr_to_v4mapped((const struct sockaddr *)&input4, &output6));
+  GPR_ASSERT(grpc_sockaddr_to_v4mapped(&input4, &output6));
   expect6 = make_addr6(kMapped, sizeof(kMapped));
   GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0);
 
   /* IPv6 input should fail. */
   input6 = make_addr6(kIPv6, sizeof(kIPv6));
-  GPR_ASSERT(
-      !grpc_sockaddr_to_v4mapped((const struct sockaddr *)&input6, &output6));
+  GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6));
   /* Output is unchanged. */
   GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0);
 
   /* Already-v4mapped input should also fail. */
   input6 = make_addr6(kMapped, sizeof(kMapped));
-  GPR_ASSERT(
-      !grpc_sockaddr_to_v4mapped((const struct sockaddr *)&input6, &output6));
+  GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6));
 }
 
 static void test_sockaddr_is_wildcard(void) {
-  struct sockaddr_in wild4;
-  struct sockaddr_in6 wild6;
-  struct sockaddr_in6 wild_mapped;
-  struct sockaddr dummy;
+  grpc_resolved_address wild4;
+  grpc_resolved_address wild6;
+  grpc_resolved_address wild_mapped;
+  grpc_resolved_address dummy;
+  struct sockaddr_in *wild4_addr;
+  struct sockaddr_in6 *wild6_addr;
+  struct sockaddr_in6 *wild_mapped_addr;
   int port;
 
   gpr_log(GPR_INFO, "%s", "test_sockaddr_is_wildcard");
 
   /* Generate wildcards. */
   grpc_sockaddr_make_wildcards(555, &wild4, &wild6);
-  GPR_ASSERT(
-      grpc_sockaddr_to_v4mapped((const struct sockaddr *)&wild4, &wild_mapped));
+  GPR_ASSERT(grpc_sockaddr_to_v4mapped(&wild4, &wild_mapped));
 
   /* Test 0.0.0.0:555 */
   port = -1;
-  GPR_ASSERT(grpc_sockaddr_is_wildcard((const struct sockaddr *)&wild4, &port));
+  GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild4, &port));
   GPR_ASSERT(port == 555);
-  memset(&wild4.sin_addr.s_addr, 0xbd, 1);
-  GPR_ASSERT(
-      !grpc_sockaddr_is_wildcard((const struct sockaddr *)&wild4, &port));
+  wild4_addr = (struct sockaddr_in *)&wild4.addr;
+  memset(&wild4_addr->sin_addr.s_addr, 0xbd, 1);
+  GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild4, &port));
 
   /* Test [::]:555 */
   port = -1;
-  GPR_ASSERT(grpc_sockaddr_is_wildcard((const struct sockaddr *)&wild6, &port));
+  GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild6, &port));
   GPR_ASSERT(port == 555);
-  memset(&wild6.sin6_addr.s6_addr, 0xbd, 1);
-  GPR_ASSERT(
-      !grpc_sockaddr_is_wildcard((const struct sockaddr *)&wild6, &port));
+  wild6_addr = (struct sockaddr_in6 *)&wild6.addr;
+  memset(&wild6_addr->sin6_addr.s6_addr, 0xbd, 1);
+  GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild6, &port));
 
   /* Test [::ffff:0.0.0.0]:555 */
   port = -1;
-  GPR_ASSERT(
-      grpc_sockaddr_is_wildcard((const struct sockaddr *)&wild_mapped, &port));
+  GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild_mapped, &port));
   GPR_ASSERT(port == 555);
-  memset(&wild_mapped.sin6_addr.s6_addr, 0xbd, 1);
-  GPR_ASSERT(
-      !grpc_sockaddr_is_wildcard((const struct sockaddr *)&wild_mapped, &port));
+  wild_mapped_addr = (struct sockaddr_in6 *)&wild_mapped.addr;
+  memset(&wild_mapped_addr->sin6_addr.s6_addr, 0xbd, 1);
+  GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild_mapped, &port));
 
   /* Test AF_UNSPEC. */
   port = -1;
@@ -176,12 +175,12 @@
   GPR_ASSERT(port == -1);
 }
 
-static void expect_sockaddr_str(const char *expected, void *addr,
+static void expect_sockaddr_str(const char *expected, grpc_resolved_address *addr,
                                 int normalize) {
   int result;
   char *str;
   gpr_log(GPR_INFO, "  expect_sockaddr_str(%s)", expected);
-  result = grpc_sockaddr_to_string(&str, (struct sockaddr *)addr, normalize);
+  result = grpc_sockaddr_to_string(&str, addr, normalize);
   GPR_ASSERT(str != NULL);
   GPR_ASSERT(result >= 0);
   GPR_ASSERT((size_t)result == strlen(str));
@@ -189,19 +188,20 @@
   gpr_free(str);
 }
 
-static void expect_sockaddr_uri(const char *expected, void *addr) {
+static void expect_sockaddr_uri(const char *expected, grpc_resolved_address *addr) {
   char *str;
   gpr_log(GPR_INFO, "  expect_sockaddr_uri(%s)", expected);
-  str = grpc_sockaddr_to_uri((struct sockaddr *)addr);
+  str = grpc_sockaddr_to_uri(addr);
   GPR_ASSERT(str != NULL);
   GPR_ASSERT(strcmp(expected, str) == 0);
   gpr_free(str);
 }
 
 static void test_sockaddr_to_string(void) {
-  struct sockaddr_in input4;
-  struct sockaddr_in6 input6;
-  struct sockaddr dummy;
+  grpc_resolved_address input4;
+  grpc_resolved_address input6;
+  grpc_resolved_address dummy;
+  struct sockaddr *dummy_addr;
 
   gpr_log(GPR_INFO, "%s", "test_sockaddr_to_string");
 
@@ -228,7 +228,8 @@
   expect_sockaddr_uri("ipv6:[::fffe:c000:263]:12345", &input6);
 
   memset(&dummy, 0, sizeof(dummy));
-  dummy.sa_family = 123;
+  dummy_addr = (struct sockaddr *)dummy.addr;
+  dummy_addr->sa_family = 123;
   expect_sockaddr_str("(sockaddr family=123)", &dummy, 0);
   expect_sockaddr_str("(sockaddr family=123)", &dummy, 1);
   GPR_ASSERT(grpc_sockaddr_to_uri(&dummy) == NULL);
@@ -237,24 +238,26 @@
 }
 
 static void test_sockaddr_set_get_port(void) {
-  struct sockaddr_in input4;
-  struct sockaddr_in6 input6;
-  struct sockaddr dummy;
+  grpc_resolved_address input4;
+  grpc_resolved_address input6;
+  grpc_resolved_address dummy;
+  struct sockaddr *dummy_addr;
 
   gpr_log(GPR_DEBUG, "test_sockaddr_set_get_port");
 
   input4 = make_addr4(kIPv4, sizeof(kIPv4));
-  GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input4) == 12345);
-  GPR_ASSERT(grpc_sockaddr_set_port((struct sockaddr *)&input4, 54321));
-  GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input4) == 54321);
+  GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 12345);
+  GPR_ASSERT(grpc_sockaddr_set_port(&input4, 54321));
+  GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 54321);
 
   input6 = make_addr6(kIPv6, sizeof(kIPv6));
-  GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input6) == 12345);
-  GPR_ASSERT(grpc_sockaddr_set_port((struct sockaddr *)&input6, 54321));
-  GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input6) == 54321);
+  GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 12345);
+  GPR_ASSERT(grpc_sockaddr_set_port(&input6, 54321));
+  GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 54321);
 
   memset(&dummy, 0, sizeof(dummy));
-  dummy.sa_family = 123;
+  dummy_addr = (struct sockaddr *)dummy.addr;
+  dummy_addr->sa_family = 123;
   GPR_ASSERT(grpc_sockaddr_get_port(&dummy) == 0);
   GPR_ASSERT(grpc_sockaddr_set_port(&dummy, 1234) == 0);
 }
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index d0c1047..07aa55b 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -85,8 +85,8 @@
 }
 
 void test_succeeds(void) {
-  struct sockaddr_in addr;
-  socklen_t addr_len = sizeof(addr);
+  grpc_resolved_address resolved_addr;
+  struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
   int svr_fd;
   int r;
   int connections_complete_before;
@@ -95,13 +95,14 @@
 
   gpr_log(GPR_DEBUG, "test_succeeds");
 
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
+  memset(&resolved_addr, 0, sizeof(resolved_addr));
+  resolved_addr.len = sizeof(struct sockaddr_in);
+  addr->sin_family = AF_INET;
 
   /* create a dummy server */
   svr_fd = socket(AF_INET, SOCK_STREAM, 0);
   GPR_ASSERT(svr_fd >= 0);
-  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len));
+  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)addr, (socklen_t)resolved_addr.len));
   GPR_ASSERT(0 == listen(svr_fd, 1));
 
   gpr_mu_lock(g_mu);
@@ -109,16 +110,15 @@
   gpr_mu_unlock(g_mu);
 
   /* connect to it */
-  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0);
+  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)addr, (socklen_t *)&resolved_addr.len) == 0);
   grpc_closure_init(&done, must_succeed, NULL);
   grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set,
-                          (struct sockaddr *)&addr, addr_len,
-                          gpr_inf_future(GPR_CLOCK_REALTIME));
+                          &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME));
 
   /* await the connection */
   do {
-    addr_len = sizeof(addr);
-    r = accept(svr_fd, (struct sockaddr *)&addr, &addr_len);
+    resolved_addr.len = sizeof(addr);
+    r = accept(svr_fd, addr, (socklen_t *)&resolved_addr.len);
   } while (r == -1 && errno == EINTR);
   GPR_ASSERT(r >= 0);
   close(r);
@@ -143,16 +143,17 @@
 }
 
 void test_fails(void) {
-  struct sockaddr_in addr;
-  socklen_t addr_len = sizeof(addr);
+  grpc_resolved_address resolved_addr;
+  struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
   int connections_complete_before;
   grpc_closure done;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   gpr_log(GPR_DEBUG, "test_fails");
 
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
+  memset(&resolved_addr, 0, sizeof(resolved_addr));
+  resolved_addr.len = sizeof(struct sockaddr_in);
+  addr->sin_family = AF_INET;
 
   gpr_mu_lock(g_mu);
   connections_complete_before = g_connections_complete;
@@ -161,8 +162,7 @@
   /* connect to a broken address */
   grpc_closure_init(&done, must_fail, NULL);
   grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set,
-                          (struct sockaddr *)&addr, addr_len,
-                          gpr_inf_future(GPR_CLOCK_REALTIME));
+                          &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME));
 
   gpr_mu_lock(g_mu);
 
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 6e2d1d0..9e8dff6 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -46,6 +46,7 @@
 #include <grpc/support/time.h>
 
 #include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -146,15 +147,17 @@
 
 static void test_no_op_with_port(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  struct sockaddr_in addr;
+  grpc_resolved_address resolved_addr;
+  struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
   grpc_tcp_server *s;
   GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, NULL, &s));
   LOG_TEST("test_no_op_with_port");
 
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
+  memset(&resolved_addr, 0, sizeof(resolved_addr));
+  resolved_addr.len = sizeof(struct sockaddr_in);
+  addr->sin_family = AF_INET;
   int port;
-  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr),
+  GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr,
                                       &port) == GRPC_ERROR_NONE &&
              port > 0);
 
@@ -164,15 +167,17 @@
 
 static void test_no_op_with_port_and_start(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  struct sockaddr_in addr;
+  grpc_resolved_address resolved_addr;
+  struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
   grpc_tcp_server *s;
   GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, NULL, &s));
   LOG_TEST("test_no_op_with_port_and_start");
   int port;
 
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr),
+  memset(&resolved_addr, 0, sizeof(resolved_addr));
+  resolved_addr.len = sizeof(struct sockaddr_in);
+  addr->sin_family = AF_INET;
+  GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr,
                                       &port) == GRPC_ERROR_NONE &&
              port > 0);
 
@@ -218,9 +223,10 @@
    the same port should be tested. */
 static void test_connect(unsigned n) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  struct sockaddr_storage addr;
-  struct sockaddr_storage addr1;
-  socklen_t addr_len = sizeof(addr);
+  grpc_resolved_address resolved_addr;
+  grpc_resolved_address resolved_addr1;
+  struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr;
+  struct sockaddr_storage *addr1 = (struct sockaddr_storage *)resolved_addr1.addr;
   unsigned svr_fd_count;
   int svr_port;
   unsigned svr1_fd_count;
@@ -232,18 +238,19 @@
   server_weak_ref_init(&weak_ref);
   LOG_TEST("test_connect");
   gpr_log(GPR_INFO, "clients=%d", n);
-  memset(&addr, 0, sizeof(addr));
-  memset(&addr1, 0, sizeof(addr1));
-  addr.ss_family = addr1.ss_family = AF_INET;
+  memset(&resolved_addr, 0, sizeof(resolved_addr));
+  memset(&resolved_addr1, 0, sizeof(resolved_addr1));
+  resolved_addr.len = sizeof(struct sockaddr_storage);
+  resolved_addr1.len = sizeof(struct sockaddr_storage);
+  addr->ss_family = addr1->ss_family = AF_INET;
   GPR_ASSERT(GRPC_ERROR_NONE ==
-             grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len,
-                                      &svr_port));
+             grpc_tcp_server_add_port(s, &resolved_addr, &svr_port));
   GPR_ASSERT(svr_port > 0);
   /* Cannot use wildcard (port==0), because add_port() will try to reuse the
      same port as a previous add_port(). */
   svr1_port = grpc_pick_unused_port_or_die();
-  grpc_sockaddr_set_port((struct sockaddr *)&addr1, svr1_port);
-  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr1, addr_len,
+  grpc_sockaddr_set_port(&resolved_addr1, svr1_port);
+  GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1,
                                       &svr_port) == GRPC_ERROR_NONE &&
              svr_port == svr1_port);
 
@@ -265,16 +272,16 @@
     int fd = grpc_tcp_server_port_fd(s, 0, i);
     GPR_ASSERT(fd >= 0);
     if (i == 0) {
-      GPR_ASSERT(getsockname(fd, (struct sockaddr *)&addr, &addr_len) == 0);
-      GPR_ASSERT(addr_len <= sizeof(addr));
+      GPR_ASSERT(getsockname(fd, (struct sockaddr *)addr, (socklen_t *)&resolved_addr.len) == 0);
+      GPR_ASSERT(resolved_addr.len <= sizeof(*addr));
     }
   }
   for (i = 0; i < svr1_fd_count; ++i) {
     int fd = grpc_tcp_server_port_fd(s, 1, i);
     GPR_ASSERT(fd >= 0);
     if (i == 0) {
-      GPR_ASSERT(getsockname(fd, (struct sockaddr *)&addr1, &addr_len) == 0);
-      GPR_ASSERT(addr_len <= sizeof(addr1));
+      GPR_ASSERT(getsockname(fd, (struct sockaddr *)addr1, (socklen_t *)&resolved_addr1.len) == 0);
+      GPR_ASSERT(resolved_addr1.len <= sizeof(*addr1));
     }
   }
 
@@ -284,7 +291,7 @@
     on_connect_result result;
     int svr_fd;
     on_connect_result_init(&result);
-    tcp_connect(&exec_ctx, (struct sockaddr *)&addr, addr_len, &result);
+    tcp_connect(&exec_ctx, (struct sockaddr *)addr, (socklen_t)resolved_addr.len, &result);
     GPR_ASSERT(result.server_fd >= 0);
     svr_fd = result.server_fd;
     GPR_ASSERT(grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) ==
@@ -298,7 +305,7 @@
     grpc_tcp_server_unref(&exec_ctx, result.server);
 
     on_connect_result_init(&result);
-    tcp_connect(&exec_ctx, (struct sockaddr *)&addr1, addr_len, &result);
+    tcp_connect(&exec_ctx, (struct sockaddr *)addr1, (socklen_t)resolved_addr1.len, &result);
     GPR_ASSERT(result.server_fd >= 0);
     GPR_ASSERT(result.server_fd != svr_fd);
     GPR_ASSERT(grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) ==
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index f7567f3..537fdf7 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -31,6 +31,8 @@
  *
  */
 
+#include "src/core/lib/iomgr/sockaddr.h"
+
 #include <memory.h>
 #include <stdio.h>
 
@@ -42,6 +44,7 @@
 
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/tcp_server.h"
 
@@ -109,16 +112,16 @@
   struct server_thread_args *args = (struct server_thread_args *)vargs;
 
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  struct sockaddr_storage addr;
-  socklen_t addr_len = sizeof(addr);
+  grpc_resolved_address resolved_addr;
+  struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr;
   int port;
   grpc_tcp_server *s;
   grpc_error *error = grpc_tcp_server_create(NULL, NULL, &s);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
-  memset(&addr, 0, sizeof(addr));
-  addr.ss_family = AF_INET;
+  memset(&resolved_addr, 0, sizeof(resolved_addr));
+  addr->ss_family = AF_INET;
   error =
-      grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len, &port);
+      grpc_tcp_server_add_port(s, &resolved_addr, &port);
   GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error));
   GPR_ASSERT(port > 0);
   gpr_asprintf(&args->addr, "localhost:%d", port);
diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c
index 8a0b393..ee2de56 100644
--- a/test/core/util/test_tcp_server.c
+++ b/test/core/util/test_tcp_server.c
@@ -31,6 +31,8 @@
  *
  */
 
+#include "src/core/lib/iomgr/sockaddr.h"
+
 #include "test/core/util/test_tcp_server.h"
 
 #include <grpc/grpc.h>
@@ -41,7 +43,7 @@
 #include <grpc/support/time.h>
 #include <string.h>
 #include "src/core/lib/iomgr/endpoint.h"
-#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/tcp_server.h"
 #include "test/core/util/port.h"
 
@@ -64,18 +66,19 @@
 }
 
 void test_tcp_server_start(test_tcp_server *server, int port) {
-  struct sockaddr_in addr;
+  grpc_resolved_address resolved_addr;
+  struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr;
   int port_added;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
-  addr.sin_family = AF_INET;
-  addr.sin_port = htons((uint16_t)port);
-  memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
+  addr->sin_family = AF_INET;
+  addr->sin_port = htons((uint16_t)port);
+  memset(&addr->sin_addr, 0, sizeof(addr->sin_addr));
 
   grpc_error *error = grpc_tcp_server_create(&server->shutdown_complete, NULL,
                                              &server->tcp_server);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
-  error = grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr),
+  error = grpc_tcp_server_add_port(server->tcp_server, &resolved_addr,
                                    &port_added);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(port_added == port);