Blame SOURCES/gdb-rhbz881849-ipv6-1of3.patch

190f2a
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
190f2a
From: Sergio Durigan Junior <sergiodj@redhat.com>
190f2a
Date: Fri, 18 May 2018 01:29:24 -0400
190f2a
Subject: gdb-rhbz881849-ipv6-1of3.patch
190f2a
190f2a
;; Implement IPv6 support for GDB/gdbserver (RH BZ 881849, Sergio Durigan Junior).
190f2a
190f2a
Implement IPv6 support for GDB/gdbserver
190f2a
190f2a
This patch implements IPv6 support for both GDB and gdbserver.  Based
190f2a
on my research, it is the fourth attempt to do that since 2006.  Since
190f2a
I used ideas from all of the previous patches, I also added their
190f2a
authors's names on the ChangeLogs as a way to recognize their
190f2a
efforts.  For reference sake, you can find the previous attempts at:
190f2a
190f2a
  https://sourceware.org/ml/gdb-patches/2006-09/msg00192.html
190f2a
190f2a
  https://sourceware.org/ml/gdb-patches/2014-02/msg00248.html
190f2a
190f2a
  https://sourceware.org/ml/gdb-patches/2016-02/msg00226.html
190f2a
190f2a
The basic idea behind the patch is to start using the new
190f2a
'getaddrinfo'/'getnameinfo' calls, which are responsible for
190f2a
translating names and addresses in a protocol-independent way.  This
190f2a
means that if we ever have a new version of the IP protocol, we won't
190f2a
need to change the code again (or, at least, won't have to change the
190f2a
majority of the code).
190f2a
190f2a
The function 'getaddrinfo' returns a linked list of possible addresses
190f2a
to connect to.  Dealing with multiple addresses proved to be a hard
190f2a
task with the current TCP auto-retry mechanism implemented on
190f2a
ser-tcp:net_open.  For example, when gdbserver listened only on an
190f2a
IPv4 socket:
190f2a
190f2a
  $ ./gdbserver --once 127.0.0.1:1234 ./a.out
190f2a
190f2a
and GDB was instructed to try to connect to both IPv6 and IPv4
190f2a
sockets:
190f2a
190f2a
  $ ./gdb -ex 'target extended-remote localhost:1234' ./a.out
190f2a
190f2a
the user would notice a somewhat big delay before GDB was able to
190f2a
connect to the IPv4 socket.  This happened because GDB was trying to
190f2a
connect to the IPv6 socket first, and had to wait until the connection
190f2a
timed out before it tried to connect to the IPv4 socket.
190f2a
190f2a
For that reason, I had to rewrite the main loop and implement a new
190f2a
method for handling multiple connections.  After some discussion,
190f2a
Pedro and I agreed on the following algorithm:
190f2a
190f2a
  1) For each entry returned by 'getaddrinfo', we try to open a socket
190f2a
  and connect to it.
190f2a
190f2a
  2.a) If we have a successful 'connect', we just use that connection.
190f2a
190f2a
  2.b) If we don't have a successfull 'connect', but if we've got a
190f2a
  ECONNREFUSED (meaning the the connection was refused), we keep track
190f2a
  of this fact by using a flag.
190f2a
190f2a
  2.c) If we don't have a successfull 'connect', but if we've got a
190f2a
  EINPROGRESS (meaning that the connection is in progress), we perform
190f2a
  a 'select' call on the socket until we have a result (either a
190f2a
  successful connection, or an error on the socket).
190f2a
190f2a
  3) If tcp_auto_retry is true, and we haven't gotten a successful
190f2a
  connection, and at least one of our attempts failed with
190f2a
  ECONNREFUSED, then we wait a little bit (i.e., call
190f2a
  'wait_for_connect'), check to see if there was a
190f2a
  timeout/interruption (in which case we bail out), and then go back
190f2a
  to (1).
190f2a
190f2a
After multiple tests, I was able to connect without delay on the
190f2a
scenario described above, and was also able to connect in all other
190f2a
types of scenarios.
190f2a
190f2a
I also implemented some hostname parsing functions (along with their
190f2a
corresponding unit tests) which are used to help GDB and gdbserver to
190f2a
parse hostname strings provided by the user.  These new functions are
190f2a
living inside common/netstuff.[ch].  I've had to do that since IPv6
190f2a
introduces a new URL scheme, which defines that square brackets can be
190f2a
used to enclose the host part and differentiate it from the
190f2a
port (e.g., "[::1]:1234" means "host ::1, port 1234").  I spent some
190f2a
time thinking about a reasonable way to interpret what the user wants,
190f2a
and I came up with the following:
190f2a
190f2a
  - If the user has provided a prefix that doesn't specify the protocol
190f2a
    version (i.e., "tcp:" or "udp:"), or if the user has not provided
190f2a
    any prefix, don't make any assumptions (i.e., assume AF_UNSPEC when
190f2a
    dealing with 'getaddrinfo') *unless* the host starts with "[" (in
190f2a
    which case, assume it's an IPv6 host).
190f2a
190f2a
  - If the user has provided a prefix that does specify the protocol
190f2a
    version (i.e., "tcp4:", "tcp6:", "udp4:" or "udp6:"), then respect
190f2a
    that.
190f2a
190f2a
This method doesn't follow strictly what RFC 2732 proposes (that
190f2a
literal IPv6 addresses should be provided enclosed in "[" and "]")
190f2a
because IPv6 addresses still can be provided without square brackets
190f2a
in our case, but since we have prefixes to specify protocol versions I
190f2a
think this is not an issue.
190f2a
190f2a
Another thing worth mentioning is the new 'GDB_TEST_SOCKETHOST'
190f2a
testcase parameter, which makes it possible to specify the
190f2a
hostname (without the port) to be used when testing GDB and
190f2a
gdbserver.  For example, to run IPv6 tests:
190f2a
190f2a
  $ make check-gdb RUNTESTFLAGS='GDB_TEST_SOCKETHOST=tcp6:[::1]'
190f2a
190f2a
Or, to run IPv4 tests:
190f2a
190f2a
  $ make check-gdb RUNTESTFLAGS='GDB_TEST_SOCKETHOST=tcp4:127.0.0.1'
190f2a
190f2a
This required a few changes on the gdbserver-base.exp, and also a
190f2a
minimal adjustment on gdb.server/run-without-local-binary.exp.
190f2a
190f2a
Finally, I've implemented a new testcase,
190f2a
gdb.server/server-connect.exp, which is supposed to run on the native
190f2a
host and perform various "smoke tests" using different connection
190f2a
methods.
190f2a
190f2a
This patch has been regression-tested on BuildBot and locally, and
190f2a
also built using a x86_64-w64-mingw32 GCC, and no problems were found.
190f2a
190f2a
gdb/ChangeLog:
190f2a
2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
	    Paul Fertser  <fercerpav@gmail.com>
190f2a
	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
	    Pedro Alves  <palves@redhat.com>
190f2a
190f2a
	* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
190f2a
	'unittests/parse-connection-spec-selftests.c'.
190f2a
	(COMMON_SFILES): Add 'common/netstuff.c'.
190f2a
	(HFILES_NO_SRCDIR): Add 'common/netstuff.h'.
190f2a
	* NEWS (Changes since GDB 8.2): Mention IPv6 support.
190f2a
	* common/netstuff.c: New file.
190f2a
	* common/netstuff.h: New file.
190f2a
	* ser-tcp.c: Include 'netstuff.h' and 'wspiapi.h'.
190f2a
	(wait_for_connect): Update comment.  New parameter
190f2a
	'gdb::optional<int> sock' instead of 'struct serial *scb'.
190f2a
	Use 'sock' directly instead of 'scb->fd'.
190f2a
	(try_connect): New function, with code from 'net_open'.
190f2a
	(net_open): Rewrite main loop to deal with multiple
190f2a
	sockets/addresses.  Handle IPv6-style hostnames; implement
190f2a
	support for IPv6 connections.
190f2a
	* unittests/parse-connection-spec-selftests.c: New file.
190f2a
190f2a
gdb/gdbserver/ChangeLog:
190f2a
2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
	    Paul Fertser  <fercerpav@gmail.com>
190f2a
	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
190f2a
	* Makefile.in (SFILES): Add '$(srcdir)/common/netstuff.c'.
190f2a
	(OBS): Add 'common/netstuff.o'.
190f2a
	(GDBREPLAY_OBS): Likewise.
190f2a
	* gdbreplay.c: Include 'wspiapi.h' and 'netstuff.h'.
190f2a
	(remote_open): Implement support for IPv6
190f2a
	connections.
190f2a
	* remote-utils.c: Include 'netstuff.h', 'filestuff.h'
190f2a
	and 'wspiapi.h'.
190f2a
	(handle_accept_event): Accept connections from IPv6 sources.
190f2a
	(remote_prepare): Handle IPv6-style hostnames; implement
190f2a
	support for IPv6 connections.
190f2a
	(remote_open): Implement support for printing connections from
190f2a
	IPv6 sources.
190f2a
190f2a
gdb/testsuite/ChangeLog:
190f2a
2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
	    Paul Fertser  <fercerpav@gmail.com>
190f2a
	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
190f2a
	* README (Testsuite Parameters): Mention new 'GDB_TEST_SOCKETHOST'
190f2a
	parameter.
190f2a
	* boards/native-extended-gdbserver.exp: Do not set 'sockethost'
190f2a
	by default.
190f2a
	* boards/native-gdbserver.exp: Likewise.
190f2a
	* gdb.server/run-without-local-binary.exp: Improve regexp used
190f2a
	for detecting when a remote debugging connection succeeds.
190f2a
	* gdb.server/server-connect.exp: New file.
190f2a
	* lib/gdbserver-support.exp (gdbserver_default_get_comm_port):
190f2a
	Do not prefix the port number with ":".
190f2a
	(gdbserver_start): New global GDB_TEST_SOCKETHOST.  Implement
190f2a
	support for detecting and using it.  Add '$debughost_gdbserver'
190f2a
	to the list of arguments used to start gdbserver.  Handle case
190f2a
	when gdbserver cannot resolve a network name.
190f2a
190f2a
gdb/doc/ChangeLog:
190f2a
2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
	    Paul Fertser  <fercerpav@gmail.com>
190f2a
	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
190f2a
	* gdb.texinfo (Remote Connection Commands): Add explanation
190f2a
	about new IPv6 support.  Add new connection prefixes.
190f2a
190f2a
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
190f2a
--- a/gdb/Makefile.in
190f2a
+++ b/gdb/Makefile.in
190f2a
@@ -430,6 +430,7 @@ SUBDIR_UNITTESTS_SRCS = \
190f2a
 	unittests/offset-type-selftests.c \
190f2a
 	unittests/observable-selftests.c \
190f2a
 	unittests/optional-selftests.c \
190f2a
+	unittests/parse-connection-spec-selftests.c \
190f2a
 	unittests/ptid-selftests.c \
190f2a
 	unittests/rsp-low-selftests.c \
190f2a
 	unittests/scoped_fd-selftests.c \
190f2a
@@ -967,6 +968,7 @@ COMMON_SFILES = \
190f2a
 	common/job-control.c \
190f2a
 	common/gdb_tilde_expand.c \
190f2a
 	common/gdb_vecs.c \
190f2a
+	common/netstuff.c \
190f2a
 	common/new-op.c \
190f2a
 	common/pathstuff.c \
190f2a
 	common/print-utils.c \
190f2a
@@ -1448,6 +1450,7 @@ HFILES_NO_SRCDIR = \
190f2a
 	common/gdb_vecs.h \
190f2a
 	common/gdb_wait.h \
190f2a
 	common/common-inferior.h \
190f2a
+	common/netstuff.h \
190f2a
 	common/host-defs.h \
190f2a
 	common/pathstuff.h \
190f2a
 	common/print-utils.h \
190f2a
diff --git a/gdb/NEWS b/gdb/NEWS
190f2a
--- a/gdb/NEWS
190f2a
+++ b/gdb/NEWS
190f2a
@@ -1,6 +1,12 @@
190f2a
 		What has changed in GDB?
190f2a
 	     (Organized release by release)
190f2a
 
190f2a
+*** Changes since GDB 8.2
190f2a
+
190f2a
+* GDB and GDBserver now support IPv6 connections.  IPv6 addresses
190f2a
+  can be passed using the '[ADDRESS]:PORT' notation, or the regular
190f2a
+  'ADDRESS:PORT' method.
190f2a
+
190f2a
 *** Changes in GDB 8.2
190f2a
 
190f2a
 * The 'set disassembler-options' command now supports specifying options
190f2a
diff --git a/gdb/common/netstuff.c b/gdb/common/netstuff.c
190f2a
new file mode 100644
190f2a
--- /dev/null
190f2a
+++ b/gdb/common/netstuff.c
190f2a
@@ -0,0 +1,155 @@
190f2a
+/* Operations on network stuff.
190f2a
+   Copyright (C) 2018 Free Software Foundation, Inc.
190f2a
+
190f2a
+   This file is part of GDB.
190f2a
+
190f2a
+   This program is free software; you can redistribute it and/or modify
190f2a
+   it under the terms of the GNU General Public License as published by
190f2a
+   the Free Software Foundation; either version 3 of the License, or
190f2a
+   (at your option) any later version.
190f2a
+
190f2a
+   This program is distributed in the hope that it will be useful,
190f2a
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
190f2a
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
190f2a
+   GNU General Public License for more details.
190f2a
+
190f2a
+   You should have received a copy of the GNU General Public License
190f2a
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
190f2a
+
190f2a
+#include "common-defs.h"
190f2a
+#include "netstuff.h"
190f2a
+#include <algorithm>
190f2a
+
190f2a
+#ifdef USE_WIN32API
190f2a
+#include <winsock2.h>
190f2a
+#include <wspiapi.h>
190f2a
+#else
190f2a
+#include <netinet/in.h>
190f2a
+#include <arpa/inet.h>
190f2a
+#include <netdb.h>
190f2a
+#include <sys/socket.h>
190f2a
+#include <netinet/tcp.h>
190f2a
+#endif
190f2a
+
190f2a
+/* See common/netstuff.h.  */
190f2a
+
190f2a
+scoped_free_addrinfo::~scoped_free_addrinfo ()
190f2a
+{
190f2a
+  freeaddrinfo (m_res);
190f2a
+}
190f2a
+
190f2a
+/* See common/netstuff.h.  */
190f2a
+
190f2a
+parsed_connection_spec
190f2a
+parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
190f2a
+{
190f2a
+  parsed_connection_spec ret;
190f2a
+  size_t last_colon_pos = 0;
190f2a
+  /* We're dealing with IPv6 if:
190f2a
+
190f2a
+     - ai_family is AF_INET6, or
190f2a
+     - ai_family is not AF_INET, and
190f2a
+       - spec[0] is '[', or
190f2a
+       - the number of ':' on spec is greater than 1.  */
190f2a
+  bool is_ipv6 = (hint->ai_family == AF_INET6
190f2a
+		  || (hint->ai_family != AF_INET
190f2a
+		      && (spec[0] == '['
190f2a
+			  || std::count (spec.begin (),
190f2a
+					 spec.end (), ':') > 1)));
190f2a
+
190f2a
+  if (is_ipv6)
190f2a
+    {
190f2a
+      if (spec[0] == '[')
190f2a
+	{
190f2a
+	  /* IPv6 addresses can be written as '[ADDR]:PORT', and we
190f2a
+	     support this notation.  */
190f2a
+	  size_t close_bracket_pos = spec.find_first_of (']');
190f2a
+
190f2a
+	  if (close_bracket_pos == std::string::npos)
190f2a
+	    error (_("Missing close bracket in hostname '%s'"),
190f2a
+		   spec.c_str ());
190f2a
+
190f2a
+	  hint->ai_family = AF_INET6;
190f2a
+
190f2a
+	  const char c = spec[close_bracket_pos + 1];
190f2a
+
190f2a
+	  if (c == '\0')
190f2a
+	    last_colon_pos = std::string::npos;
190f2a
+	  else if (c != ':')
190f2a
+	    error (_("Invalid cruft after close bracket in '%s'"),
190f2a
+		   spec.c_str ());
190f2a
+
190f2a
+	  /* Erase both '[' and ']'.  */
190f2a
+	  spec.erase (0, 1);
190f2a
+	  spec.erase (close_bracket_pos - 1, 1);
190f2a
+	}
190f2a
+      else if (spec.find_first_of (']') != std::string::npos)
190f2a
+	error (_("Missing open bracket in hostname '%s'"),
190f2a
+	       spec.c_str ());
190f2a
+    }
190f2a
+
190f2a
+  if (last_colon_pos == 0)
190f2a
+    last_colon_pos = spec.find_last_of (':');
190f2a
+
190f2a
+  /* The length of the hostname part.  */
190f2a
+  size_t host_len;
190f2a
+
190f2a
+  if (last_colon_pos != std::string::npos)
190f2a
+    {
190f2a
+      /* The user has provided a port.  */
190f2a
+      host_len = last_colon_pos;
190f2a
+      ret.port_str = spec.substr (last_colon_pos + 1);
190f2a
+    }
190f2a
+  else
190f2a
+    host_len = spec.size ();
190f2a
+
190f2a
+  ret.host_str = spec.substr (0, host_len);
190f2a
+
190f2a
+  /* Default hostname is localhost.  */
190f2a
+  if (ret.host_str.empty ())
190f2a
+    ret.host_str = "localhost";
190f2a
+
190f2a
+  return ret;
190f2a
+}
190f2a
+
190f2a
+/* See common/netstuff.h.  */
190f2a
+
190f2a
+parsed_connection_spec
190f2a
+parse_connection_spec (const char *spec, struct addrinfo *hint)
190f2a
+{
190f2a
+  /* Struct to hold the association between valid prefixes, their
190f2a
+     family and socktype.  */
190f2a
+  struct host_prefix
190f2a
+    {
190f2a
+      /* The prefix.  */
190f2a
+      const char *prefix;
190f2a
+
190f2a
+      /* The 'ai_family'.  */
190f2a
+      int family;
190f2a
+
190f2a
+      /* The 'ai_socktype'.  */
190f2a
+      int socktype;
190f2a
+    };
190f2a
+  static const struct host_prefix prefixes[] =
190f2a
+    {
190f2a
+      { "udp:",  AF_UNSPEC, SOCK_DGRAM },
190f2a
+      { "tcp:",  AF_UNSPEC, SOCK_STREAM },
190f2a
+      { "udp4:", AF_INET,   SOCK_DGRAM },
190f2a
+      { "tcp4:", AF_INET,   SOCK_STREAM },
190f2a
+      { "udp6:", AF_INET6,  SOCK_DGRAM },
190f2a
+      { "tcp6:", AF_INET6,  SOCK_STREAM },
190f2a
+    };
190f2a
+
190f2a
+  for (const host_prefix prefix : prefixes)
190f2a
+    if (startswith (spec, prefix.prefix))
190f2a
+      {
190f2a
+	spec += strlen (prefix.prefix);
190f2a
+	hint->ai_family = prefix.family;
190f2a
+	hint->ai_socktype = prefix.socktype;
190f2a
+	hint->ai_protocol
190f2a
+	  = hint->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
190f2a
+	break;
190f2a
+      }
190f2a
+
190f2a
+  return parse_connection_spec_without_prefix (spec, hint);
190f2a
+}
190f2a
diff --git a/gdb/common/netstuff.h b/gdb/common/netstuff.h
190f2a
new file mode 100644
190f2a
--- /dev/null
190f2a
+++ b/gdb/common/netstuff.h
190f2a
@@ -0,0 +1,76 @@
190f2a
+/* Operations on network stuff.
190f2a
+   Copyright (C) 2018 Free Software Foundation, Inc.
190f2a
+
190f2a
+   This file is part of GDB.
190f2a
+
190f2a
+   This program is free software; you can redistribute it and/or modify
190f2a
+   it under the terms of the GNU General Public License as published by
190f2a
+   the Free Software Foundation; either version 3 of the License, or
190f2a
+   (at your option) any later version.
190f2a
+
190f2a
+   This program is distributed in the hope that it will be useful,
190f2a
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
190f2a
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
190f2a
+   GNU General Public License for more details.
190f2a
+
190f2a
+   You should have received a copy of the GNU General Public License
190f2a
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
190f2a
+
190f2a
+#ifndef NETSTUFF_H
190f2a
+#define NETSTUFF_H
190f2a
+
190f2a
+#include <string>
190f2a
+
190f2a
+/* Like NI_MAXHOST/NI_MAXSERV, but enough for numeric forms.  */
190f2a
+#define GDB_NI_MAX_ADDR 64
190f2a
+#define GDB_NI_MAX_PORT 16
190f2a
+
190f2a
+/* Helper class to guarantee that we always call 'freeaddrinfo'.  */
190f2a
+
190f2a
+class scoped_free_addrinfo
190f2a
+{
190f2a
+public:
190f2a
+  /* Default constructor.  */
190f2a
+  explicit scoped_free_addrinfo (struct addrinfo *ainfo)
190f2a
+    : m_res (ainfo)
190f2a
+  {
190f2a
+  }
190f2a
+
190f2a
+  /* Destructor responsible for free'ing M_RES by calling
190f2a
+     'freeaddrinfo'.  */
190f2a
+  ~scoped_free_addrinfo ();
190f2a
+
190f2a
+  DISABLE_COPY_AND_ASSIGN (scoped_free_addrinfo);
190f2a
+
190f2a
+private:
190f2a
+  /* The addrinfo resource.  */
190f2a
+  struct addrinfo *m_res;
190f2a
+};
190f2a
+
190f2a
+/* The struct we return after parsing the connection spec.  */
190f2a
+
190f2a
+struct parsed_connection_spec
190f2a
+{
190f2a
+  /* The hostname.  */
190f2a
+  std::string host_str;
190f2a
+
190f2a
+  /* The port, if any.  */
190f2a
+  std::string port_str;
190f2a
+};
190f2a
+
190f2a
+
190f2a
+/* Parse SPEC (which is a string in the form of "ADDR:PORT") and
190f2a
+   return a 'parsed_connection_spec' structure with the proper fields
190f2a
+   filled in.  Also adjust HINT accordingly.  */
190f2a
+extern parsed_connection_spec
190f2a
+  parse_connection_spec_without_prefix (std::string spec,
190f2a
+					struct addrinfo *hint);
190f2a
+
190f2a
+/* Parse SPEC (which is a string in the form of
190f2a
+   "[tcp[6]:|udp[6]:]ADDR:PORT") and return a 'parsed_connection_spec'
190f2a
+   structure with the proper fields filled in.  Also adjust HINT
190f2a
+   accordingly.  */
190f2a
+extern parsed_connection_spec parse_connection_spec (const char *spec,
190f2a
+						     struct addrinfo *hint);
190f2a
+
190f2a
+#endif /* ! NETSTUFF_H */
190f2a
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
190f2a
--- a/gdb/doc/ChangeLog
190f2a
+++ b/gdb/doc/ChangeLog
190f2a
@@ -1,3 +1,11 @@
190f2a
+2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
+	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
+	    Paul Fertser  <fercerpav@gmail.com>
190f2a
+	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
+
190f2a
+	* gdb.texinfo (Remote Connection Commands): Add explanation
190f2a
+	about new IPv6 support.  Add new connection prefixes.
190f2a
+
190f2a
 2018-08-21  Alan Hayward  <alan.hayward@arm.com>
190f2a
 
190f2a
 	* gdb.texinfo (AArch64 SVE): New subsubsection.
190f2a
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
190f2a
--- a/gdb/doc/gdb.texinfo
190f2a
+++ b/gdb/doc/gdb.texinfo
190f2a
@@ -20548,16 +20548,27 @@ If you're using a serial line, you may want to give @value{GDBN} the
190f2a
 @code{target} command.
190f2a
 
190f2a
 @item target remote @code{@var{host}:@var{port}}
190f2a
+@itemx target remote @code{@var{[host]}:@var{port}}
190f2a
 @itemx target remote @code{tcp:@var{host}:@var{port}}
190f2a
+@itemx target remote @code{tcp:@var{[host]}:@var{port}}
190f2a
+@itemx target remote @code{tcp4:@var{host}:@var{port}}
190f2a
+@itemx target remote @code{tcp6:@var{host}:@var{port}}
190f2a
+@itemx target remote @code{tcp6:@var{[host]}:@var{port}}
190f2a
 @itemx target extended-remote @code{@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{@var{[host]}:@var{port}}
190f2a
 @itemx target extended-remote @code{tcp:@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{tcp:@var{[host]}:@var{port}}
190f2a
+@itemx target extended-remote @code{tcp4:@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{tcp6:@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{tcp6:@var{[host]}:@var{port}}
190f2a
 @cindex @acronym{TCP} port, @code{target remote}
190f2a
 Debug using a @acronym{TCP} connection to @var{port} on @var{host}.
190f2a
-The @var{host} may be either a host name or a numeric @acronym{IP}
190f2a
-address; @var{port} must be a decimal number.  The @var{host} could be
190f2a
-the target machine itself, if it is directly connected to the net, or
190f2a
-it might be a terminal server which in turn has a serial line to the
190f2a
-target.
190f2a
+The @var{host} may be either a host name, a numeric @acronym{IPv4}
190f2a
+address, or a numeric @acronym{IPv6} address (with or without the
190f2a
+square brackets to separate the address from the port); @var{port}
190f2a
+must be a decimal number.  The @var{host} could be the target machine
190f2a
+itself, if it is directly connected to the net, or it might be a
190f2a
+terminal server which in turn has a serial line to the target.
190f2a
 
190f2a
 For example, to connect to port 2828 on a terminal server named
190f2a
 @code{manyfarms}:
190f2a
@@ -20566,6 +20577,28 @@ For example, to connect to port 2828 on a terminal server named
190f2a
 target remote manyfarms:2828
190f2a
 @end smallexample
190f2a
 
190f2a
+To connect to port 2828 on a terminal server whose address is
190f2a
+@code{2001:0db8:85a3:0000:0000:8a2e:0370:7334}, you can either use the
190f2a
+square bracket syntax:
190f2a
+
190f2a
+@smallexample
190f2a
+target remote [2001:0db8:85a3:0000:0000:8a2e:0370:7334]:2828
190f2a
+@end smallexample
190f2a
+
190f2a
+@noindent
190f2a
+or explicitly specify the @acronym{IPv6} protocol:
190f2a
+
190f2a
+@smallexample
190f2a
+target remote tcp6:2001:0db8:85a3:0000:0000:8a2e:0370:7334:2828
190f2a
+@end smallexample
190f2a
+
190f2a
+This last example may be confusing to the reader, because there is no
190f2a
+visible separation between the hostname and the port number.
190f2a
+Therefore, we recommend the user to provide @acronym{IPv6} addresses
190f2a
+using square brackets for clarity.  However, it is important to
190f2a
+mention that for @value{GDBN} there is no ambiguity: the number after
190f2a
+the last colon is considered to be the port number.
190f2a
+
190f2a
 If your remote target is actually running on the same machine as your
190f2a
 debugger session (e.g.@: a simulator for your target running on the
190f2a
 same host), you can omit the hostname.  For example, to connect to
190f2a
@@ -20579,7 +20612,15 @@ target remote :1234
190f2a
 Note that the colon is still required here.
190f2a
 
190f2a
 @item target remote @code{udp:@var{host}:@var{port}}
190f2a
+@itemx target remote @code{udp:@var{[host]}:@var{port}}
190f2a
+@itemx target remote @code{udp4:@var{host}:@var{port}}
190f2a
+@itemx target remote @code{udp6:@var{[host]}:@var{port}}
190f2a
+@itemx target extended-remote @code{udp:@var{host}:@var{port}}
190f2a
 @itemx target extended-remote @code{udp:@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{udp:@var{[host]}:@var{port}}
190f2a
+@itemx target extended-remote @code{udp4:@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{udp6:@var{host}:@var{port}}
190f2a
+@itemx target extended-remote @code{udp6:@var{[host]}:@var{port}}
190f2a
 @cindex @acronym{UDP} port, @code{target remote}
190f2a
 Debug using @acronym{UDP} packets to @var{port} on @var{host}.  For example, to
190f2a
 connect to @acronym{UDP} port 2828 on a terminal server named @code{manyfarms}:
190f2a
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
190f2a
--- a/gdb/gdbserver/ChangeLog
190f2a
+++ b/gdb/gdbserver/ChangeLog
190f2a
@@ -1,3 +1,22 @@
190f2a
+2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
+	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
+	    Paul Fertser  <fercerpav@gmail.com>
190f2a
+	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
+
190f2a
+	* Makefile.in (SFILES): Add '$(srcdir)/common/netstuff.c'.
190f2a
+	(OBS): Add 'common/netstuff.o'.
190f2a
+	(GDBREPLAY_OBS): Likewise.
190f2a
+	* gdbreplay.c: Include 'wspiapi.h' and 'netstuff.h'.
190f2a
+	(remote_open): Implement support for IPv6
190f2a
+	connections.
190f2a
+	* remote-utils.c: Include 'netstuff.h', 'filestuff.h'
190f2a
+	and 'wspiapi.h'.
190f2a
+	(handle_accept_event): Accept connections from IPv6 sources.
190f2a
+	(remote_prepare): Handle IPv6-style hostnames; implement
190f2a
+	support for IPv6 connections.
190f2a
+	(remote_open): Implement support for printing connections from
190f2a
+	IPv6 sources.
190f2a
+
190f2a
 2018-08-26  Simon Marchi  <simon.marchi@ericsson.com>
190f2a
 
190f2a
 	PR gdb/23374
190f2a
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
190f2a
--- a/gdb/gdbserver/Makefile.in
190f2a
+++ b/gdb/gdbserver/Makefile.in
190f2a
@@ -211,6 +211,7 @@ SFILES = \
190f2a
 	$(srcdir)/common/job-control.c \
190f2a
 	$(srcdir)/common/gdb_tilde_expand.c \
190f2a
 	$(srcdir)/common/gdb_vecs.c \
190f2a
+	$(srcdir)/common/netstuff.c \
190f2a
 	$(srcdir)/common/new-op.c \
190f2a
 	$(srcdir)/common/pathstuff.c \
190f2a
 	$(srcdir)/common/print-utils.c \
190f2a
@@ -254,6 +255,7 @@ OBS = \
190f2a
 	common/format.o \
190f2a
 	common/gdb_tilde_expand.o \
190f2a
 	common/gdb_vecs.o \
190f2a
+	common/netstuff.o \
190f2a
 	common/new-op.o \
190f2a
 	common/pathstuff.o \
190f2a
 	common/print-utils.o \
190f2a
@@ -290,6 +292,7 @@ GDBREPLAY_OBS = \
190f2a
 	common/common-exceptions.o \
190f2a
 	common/common-utils.o \
190f2a
 	common/errors.o \
190f2a
+	common/netstuff.o \
190f2a
 	common/print-utils.o \
190f2a
 	gdbreplay.o \
190f2a
 	utils.o \
190f2a
diff --git a/gdb/gdbserver/gdbreplay.c b/gdb/gdbserver/gdbreplay.c
190f2a
--- a/gdb/gdbserver/gdbreplay.c
190f2a
+++ b/gdb/gdbserver/gdbreplay.c
190f2a
@@ -46,8 +46,11 @@
190f2a
 
190f2a
 #if USE_WIN32API
190f2a
 #include <winsock2.h>
190f2a
+#include <wspiapi.h>
190f2a
 #endif
190f2a
 
190f2a
+#include "netstuff.h"
190f2a
+
190f2a
 #ifndef HAVE_SOCKLEN_T
190f2a
 typedef int socklen_t;
190f2a
 #endif
190f2a
@@ -142,56 +145,108 @@ remote_close (void)
190f2a
 static void
190f2a
 remote_open (char *name)
190f2a
 {
190f2a
-  if (!strchr (name, ':'))
190f2a
+  char *last_colon = strrchr (name, ':');
190f2a
+
190f2a
+  if (last_colon == NULL)
190f2a
     {
190f2a
       fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
190f2a
       fflush (stderr);
190f2a
       exit (1);
190f2a
     }
190f2a
-  else
190f2a
-    {
190f2a
+
190f2a
 #ifdef USE_WIN32API
190f2a
-      static int winsock_initialized;
190f2a
+  static int winsock_initialized;
190f2a
 #endif
190f2a
-      char *port_str;
190f2a
-      int port;
190f2a
-      struct sockaddr_in sockaddr;
190f2a
-      socklen_t tmp;
190f2a
-      int tmp_desc;
190f2a
+  char *port_str;
190f2a
+  int tmp;
190f2a
+  int tmp_desc;
190f2a
+  struct addrinfo hint;
190f2a
+  struct addrinfo *ainfo;
190f2a
 
190f2a
-      port_str = strchr (name, ':');
190f2a
+  memset (&hint, 0, sizeof (hint));
190f2a
+  /* Assume no prefix will be passed, therefore we should use
190f2a
+     AF_UNSPEC.  */
190f2a
+  hint.ai_family = AF_UNSPEC;
190f2a
+  hint.ai_socktype = SOCK_STREAM;
190f2a
+  hint.ai_protocol = IPPROTO_TCP;
190f2a
 
190f2a
-      port = atoi (port_str + 1);
190f2a
+  parsed_connection_spec parsed = parse_connection_spec (name, &hint);
190f2a
+
190f2a
+  if (parsed.port_str.empty ())
190f2a
+    error (_("Missing port on hostname '%s'"), name);
190f2a
 
190f2a
 #ifdef USE_WIN32API
190f2a
-      if (!winsock_initialized)
190f2a
-	{
190f2a
-	  WSADATA wsad;
190f2a
+  if (!winsock_initialized)
190f2a
+    {
190f2a
+      WSADATA wsad;
190f2a
 
190f2a
-	  WSAStartup (MAKEWORD (1, 0), &wsad);
190f2a
-	  winsock_initialized = 1;
190f2a
-	}
190f2a
+      WSAStartup (MAKEWORD (1, 0), &wsad);
190f2a
+      winsock_initialized = 1;
190f2a
+    }
190f2a
 #endif
190f2a
 
190f2a
-      tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
190f2a
-      if (tmp_desc == -1)
190f2a
-	perror_with_name ("Can't open socket");
190f2a
+  int r = getaddrinfo (parsed.host_str.c_str (), parsed.port_str.c_str (),
190f2a
+		       &hint, &ainfo);
190f2a
 
190f2a
-      /* Allow rapid reuse of this port. */
190f2a
-      tmp = 1;
190f2a
-      setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
190f2a
-		  sizeof (tmp));
190f2a
+  if (r != 0)
190f2a
+    {
190f2a
+      fprintf (stderr, "%s:%s: cannot resolve name: %s\n",
190f2a
+	       parsed.host_str.c_str (), parsed.port_str.c_str (),
190f2a
+	       gai_strerror (r));
190f2a
+      fflush (stderr);
190f2a
+      exit (1);
190f2a
+    }
190f2a
+
190f2a
+  scoped_free_addrinfo free_ainfo (ainfo);
190f2a
+
190f2a
+  struct addrinfo *p;
190f2a
+
190f2a
+  for (p = ainfo; p != NULL; p = p->ai_next)
190f2a
+    {
190f2a
+      tmp_desc = socket (p->ai_family, p->ai_socktype, p->ai_protocol);
190f2a
 
190f2a
-      sockaddr.sin_family = PF_INET;
190f2a
-      sockaddr.sin_port = htons (port);
190f2a
-      sockaddr.sin_addr.s_addr = INADDR_ANY;
190f2a
+      if (tmp_desc >= 0)
190f2a
+	break;
190f2a
+    }
190f2a
+
190f2a
+  if (p == NULL)
190f2a
+    perror_with_name ("Cannot open socket");
190f2a
 
190f2a
-      if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
190f2a
-	  || listen (tmp_desc, 1))
190f2a
-	perror_with_name ("Can't bind address");
190f2a
+  /* Allow rapid reuse of this port. */
190f2a
+  tmp = 1;
190f2a
+  setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
190f2a
+	      sizeof (tmp));
190f2a
+
190f2a
+  switch (p->ai_family)
190f2a
+    {
190f2a
+    case AF_INET:
190f2a
+      ((struct sockaddr_in *) p->ai_addr)->sin_addr.s_addr = INADDR_ANY;
190f2a
+      break;
190f2a
+    case AF_INET6:
190f2a
+      ((struct sockaddr_in6 *) p->ai_addr)->sin6_addr = in6addr_any;
190f2a
+      break;
190f2a
+    default:
190f2a
+      fprintf (stderr, "Invalid 'ai_family' %d\n", p->ai_family);
190f2a
+      exit (1);
190f2a
+    }
190f2a
+
190f2a
+  if (bind (tmp_desc, p->ai_addr, p->ai_addrlen) != 0)
190f2a
+    perror_with_name ("Can't bind address");
190f2a
+
190f2a
+  if (p->ai_socktype == SOCK_DGRAM)
190f2a
+    remote_desc = tmp_desc;
190f2a
+  else
190f2a
+    {
190f2a
+      struct sockaddr_storage sockaddr;
190f2a
+      socklen_t sockaddrsize = sizeof (sockaddr);
190f2a
+      char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
190f2a
+
190f2a
+      if (listen (tmp_desc, 1) != 0)
190f2a
+	perror_with_name ("Can't listen on socket");
190f2a
+
190f2a
+      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr,
190f2a
+			    &sockaddrsize);
190f2a
 
190f2a
-      tmp = sizeof (sockaddr);
190f2a
-      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
190f2a
       if (remote_desc == -1)
190f2a
 	perror_with_name ("Accept failed");
190f2a
 
190f2a
@@ -206,6 +261,16 @@ remote_open (char *name)
190f2a
       setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
190f2a
 		  (char *) &tmp, sizeof (tmp));
190f2a
 
190f2a
+      if (getnameinfo ((struct sockaddr *) &sockaddr, sockaddrsize,
190f2a
+		       orig_host, sizeof (orig_host),
190f2a
+		       orig_port, sizeof (orig_port),
190f2a
+		       NI_NUMERICHOST | NI_NUMERICSERV) == 0)
190f2a
+	{
190f2a
+	  fprintf (stderr, "Remote debugging from host %s, port %s\n",
190f2a
+		   orig_host, orig_port);
190f2a
+	  fflush (stderr);
190f2a
+	}
190f2a
+
190f2a
 #ifndef USE_WIN32API
190f2a
       close (tmp_desc);		/* No longer need this */
190f2a
 
190f2a
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
190f2a
--- a/gdb/gdbserver/remote-utils.c
190f2a
+++ b/gdb/gdbserver/remote-utils.c
190f2a
@@ -26,6 +26,8 @@
190f2a
 #include "dll.h"
190f2a
 #include "rsp-low.h"
190f2a
 #include "gdbthread.h"
190f2a
+#include "netstuff.h"
190f2a
+#include "filestuff.h"
190f2a
 #include <ctype.h>
190f2a
 #if HAVE_SYS_IOCTL_H
190f2a
 #include <sys/ioctl.h>
190f2a
@@ -63,6 +65,7 @@
190f2a
 
190f2a
 #if USE_WIN32API
190f2a
 #include <winsock2.h>
190f2a
+#include <wspiapi.h>
190f2a
 #endif
190f2a
 
190f2a
 #if __QNX__
190f2a
@@ -151,19 +154,18 @@ enable_async_notification (int fd)
190f2a
 static int
190f2a
 handle_accept_event (int err, gdb_client_data client_data)
190f2a
 {
190f2a
-  struct sockaddr_in sockaddr;
190f2a
-  socklen_t tmp;
190f2a
+  struct sockaddr_storage sockaddr;
190f2a
+  socklen_t len = sizeof (sockaddr);
190f2a
 
190f2a
   if (debug_threads)
190f2a
     debug_printf ("handling possible accept event\n");
190f2a
 
190f2a
-  tmp = sizeof (sockaddr);
190f2a
-  remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &tmp);
190f2a
+  remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &len;;
190f2a
   if (remote_desc == -1)
190f2a
     perror_with_name ("Accept failed");
190f2a
 
190f2a
   /* Enable TCP keep alive process. */
190f2a
-  tmp = 1;
190f2a
+  socklen_t tmp = 1;
190f2a
   setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE,
190f2a
 	      (char *) &tmp, sizeof (tmp));
190f2a
 
190f2a
@@ -192,8 +194,19 @@ handle_accept_event (int err, gdb_client_data client_data)
190f2a
   delete_file_handler (listen_desc);
190f2a
 
190f2a
   /* Convert IP address to string.  */
190f2a
-  fprintf (stderr, "Remote debugging from host %s\n",
190f2a
-	   inet_ntoa (sockaddr.sin_addr));
190f2a
+  char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
190f2a
+
190f2a
+  int r = getnameinfo ((struct sockaddr *) &sockaddr, len,
190f2a
+		       orig_host, sizeof (orig_host),
190f2a
+		       orig_port, sizeof (orig_port),
190f2a
+		       NI_NUMERICHOST | NI_NUMERICSERV);
190f2a
+
190f2a
+  if (r != 0)
190f2a
+    fprintf (stderr, _("Could not obtain remote address: %s\n"),
190f2a
+	     gai_strerror (r));
190f2a
+  else
190f2a
+    fprintf (stderr, _("Remote debugging from host %s, port %s\n"),
190f2a
+	     orig_host, orig_port);
190f2a
 
190f2a
   enable_async_notification (remote_desc);
190f2a
 
190f2a
@@ -222,10 +235,7 @@ remote_prepare (const char *name)
190f2a
 #ifdef USE_WIN32API
190f2a
   static int winsock_initialized;
190f2a
 #endif
190f2a
-  int port;
190f2a
-  struct sockaddr_in sockaddr;
190f2a
   socklen_t tmp;
190f2a
-  char *port_end;
190f2a
 
190f2a
   remote_is_stdio = 0;
190f2a
   if (strcmp (name, STDIO_CONNECTION_NAME) == 0)
190f2a
@@ -238,17 +248,25 @@ remote_prepare (const char *name)
190f2a
       return;
190f2a
     }
190f2a
 
190f2a
-  port_str = strchr (name, ':');
190f2a
-  if (port_str == NULL)
190f2a
+  struct addrinfo hint;
190f2a
+  struct addrinfo *ainfo;
190f2a
+
190f2a
+  memset (&hint, 0, sizeof (hint));
190f2a
+  /* Assume no prefix will be passed, therefore we should use
190f2a
+     AF_UNSPEC.  */
190f2a
+  hint.ai_family = AF_UNSPEC;
190f2a
+  hint.ai_socktype = SOCK_STREAM;
190f2a
+  hint.ai_protocol = IPPROTO_TCP;
190f2a
+
190f2a
+  parsed_connection_spec parsed
190f2a
+    = parse_connection_spec_without_prefix (name, &hint);
190f2a
+
190f2a
+  if (parsed.port_str.empty ())
190f2a
     {
190f2a
       cs.transport_is_reliable = 0;
190f2a
       return;
190f2a
     }
190f2a
 
190f2a
-  port = strtoul (port_str + 1, &port_end, 10);
190f2a
-  if (port_str[1] == '\0' || *port_end != '\0')
190f2a
-    error ("Bad port argument: %s", name);
190f2a
-
190f2a
 #ifdef USE_WIN32API
190f2a
   if (!winsock_initialized)
190f2a
     {
190f2a
@@ -259,8 +277,26 @@ remote_prepare (const char *name)
190f2a
     }
190f2a
 #endif
190f2a
 
190f2a
-  listen_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
190f2a
-  if (listen_desc == -1)
190f2a
+  int r = getaddrinfo (parsed.host_str.c_str (), parsed.port_str.c_str (),
190f2a
+		       &hint, &ainfo);
190f2a
+
190f2a
+  if (r != 0)
190f2a
+    error (_("%s: cannot resolve name: %s"), name, gai_strerror (r));
190f2a
+
190f2a
+  scoped_free_addrinfo freeaddrinfo (ainfo);
190f2a
+
190f2a
+  struct addrinfo *iter;
190f2a
+
190f2a
+  for (iter = ainfo; iter != NULL; iter = iter->ai_next)
190f2a
+    {
190f2a
+      listen_desc = gdb_socket_cloexec (iter->ai_family, iter->ai_socktype,
190f2a
+					iter->ai_protocol);
190f2a
+
190f2a
+      if (listen_desc >= 0)
190f2a
+	break;
190f2a
+    }
190f2a
+
190f2a
+  if (iter == NULL)
190f2a
     perror_with_name ("Can't open socket");
190f2a
 
190f2a
   /* Allow rapid reuse of this port. */
190f2a
@@ -268,14 +304,25 @@ remote_prepare (const char *name)
190f2a
   setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
190f2a
 	      sizeof (tmp));
190f2a
 
190f2a
-  sockaddr.sin_family = PF_INET;
190f2a
-  sockaddr.sin_port = htons (port);
190f2a
-  sockaddr.sin_addr.s_addr = INADDR_ANY;
190f2a
+  switch (iter->ai_family)
190f2a
+    {
190f2a
+    case AF_INET:
190f2a
+      ((struct sockaddr_in *) iter->ai_addr)->sin_addr.s_addr = INADDR_ANY;
190f2a
+      break;
190f2a
+    case AF_INET6:
190f2a
+      ((struct sockaddr_in6 *) iter->ai_addr)->sin6_addr = in6addr_any;
190f2a
+      break;
190f2a
+    default:
190f2a
+      internal_error (__FILE__, __LINE__,
190f2a
+		      _("Invalid 'ai_family' %d\n"), iter->ai_family);
190f2a
+    }
190f2a
 
190f2a
-  if (bind (listen_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
190f2a
-      || listen (listen_desc, 1))
190f2a
+  if (bind (listen_desc, iter->ai_addr, iter->ai_addrlen) != 0)
190f2a
     perror_with_name ("Can't bind address");
190f2a
 
190f2a
+  if (listen (listen_desc, 1) != 0)
190f2a
+    perror_with_name ("Can't listen on socket");
190f2a
+
190f2a
   cs.transport_is_reliable = 1;
190f2a
 }
190f2a
 
190f2a
@@ -350,18 +397,24 @@ remote_open (const char *name)
190f2a
 #endif /* USE_WIN32API */
190f2a
   else
190f2a
     {
190f2a
-      int port;
190f2a
-      socklen_t len;
190f2a
-      struct sockaddr_in sockaddr;
190f2a
-
190f2a
-      len = sizeof (sockaddr);
190f2a
-      if (getsockname (listen_desc,
190f2a
-		       (struct sockaddr *) &sockaddr, &len) < 0
190f2a
-	  || len < sizeof (sockaddr))
190f2a
+      char listen_port[GDB_NI_MAX_PORT];
190f2a
+      struct sockaddr_storage sockaddr;
190f2a
+      socklen_t len = sizeof (sockaddr);
190f2a
+
190f2a
+      if (getsockname (listen_desc, (struct sockaddr *) &sockaddr, &len) < 0)
190f2a
 	perror_with_name ("Can't determine port");
190f2a
-      port = ntohs (sockaddr.sin_port);
190f2a
 
190f2a
-      fprintf (stderr, "Listening on port %d\n", port);
190f2a
+      int r = getnameinfo ((struct sockaddr *) &sockaddr, len,
190f2a
+			   NULL, 0,
190f2a
+			   listen_port, sizeof (listen_port),
190f2a
+			   NI_NUMERICSERV);
190f2a
+
190f2a
+      if (r != 0)
190f2a
+	fprintf (stderr, _("Can't obtain port where we are listening: %s"),
190f2a
+		 gai_strerror (r));
190f2a
+      else
190f2a
+	fprintf (stderr, _("Listening on port %s\n"), listen_port);
190f2a
+
190f2a
       fflush (stderr);
190f2a
 
190f2a
       /* Register the event loop handler.  */
190f2a
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
190f2a
--- a/gdb/ser-tcp.c
190f2a
+++ b/gdb/ser-tcp.c
190f2a
@@ -25,6 +25,7 @@
190f2a
 #include "cli/cli-decode.h"
190f2a
 #include "cli/cli-setshow.h"
190f2a
 #include "filestuff.h"
190f2a
+#include "netstuff.h"
190f2a
 
190f2a
 #include <sys/types.h>
190f2a
 
190f2a
@@ -39,6 +40,7 @@
190f2a
 
190f2a
 #ifdef USE_WIN32API
190f2a
 #include <winsock2.h>
190f2a
+#include <wspiapi.h>
190f2a
 #ifndef ETIMEDOUT
190f2a
 #define ETIMEDOUT WSAETIMEDOUT
190f2a
 #endif
190f2a
@@ -81,12 +83,13 @@ static unsigned int tcp_retry_limit = 15;
190f2a
 
190f2a
 #define POLL_INTERVAL 5
190f2a
 
190f2a
-/* Helper function to wait a while.  If SCB is non-null, wait on its
190f2a
-   file descriptor.  Otherwise just wait on a timeout, updating *POLLS.
190f2a
-   Returns -1 on timeout or interrupt, otherwise the value of select.  */
190f2a
+/* Helper function to wait a while.  If SOCK is not -1, wait on its
190f2a
+   file descriptor.  Otherwise just wait on a timeout, updating
190f2a
+   *POLLS.  Returns -1 on timeout or interrupt, otherwise the value of
190f2a
+   select.  */
190f2a
 
190f2a
 static int
190f2a
-wait_for_connect (struct serial *scb, unsigned int *polls)
190f2a
+wait_for_connect (int sock, unsigned int *polls)
190f2a
 {
190f2a
   struct timeval t;
190f2a
   int n;
190f2a
@@ -120,24 +123,24 @@ wait_for_connect (struct serial *scb, unsigned int *polls)
190f2a
       t.tv_usec = 0;
190f2a
     }
190f2a
 
190f2a
-  if (scb)
190f2a
+  if (sock >= 0)
190f2a
     {
190f2a
       fd_set rset, wset, eset;
190f2a
 
190f2a
       FD_ZERO (&rset);
190f2a
-      FD_SET (scb->fd, &rset);
190f2a
+      FD_SET (sock, &rset);
190f2a
       wset = rset;
190f2a
       eset = rset;
190f2a
-	  
190f2a
+
190f2a
       /* POSIX systems return connection success or failure by signalling
190f2a
 	 wset.  Windows systems return success in wset and failure in
190f2a
 	 eset.
190f2a
-     
190f2a
+
190f2a
 	 We must call select here, rather than gdb_select, because
190f2a
 	 the serial structure has not yet been initialized - the
190f2a
 	 MinGW select wrapper will not know that this FD refers
190f2a
 	 to a socket.  */
190f2a
-      n = select (scb->fd + 1, &rset, &wset, &eset, &t);
190f2a
+      n = select (sock + 1, &rset, &wset, &eset, &t);
190f2a
     }
190f2a
   else
190f2a
     /* Use gdb_select here, since we have no file descriptors, and on
190f2a
@@ -153,80 +156,28 @@ wait_for_connect (struct serial *scb, unsigned int *polls)
190f2a
   return n;
190f2a
 }
190f2a
 
190f2a
-/* Open a tcp socket.  */
190f2a
+/* Try to connect to the host represented by AINFO.  If the connection
190f2a
+   succeeds, return its socket.  Otherwise, return -1 and set ERRNO
190f2a
+   accordingly.  POLLS is used when 'connect' returns EINPROGRESS, and
190f2a
+   we need to invoke 'wait_for_connect' to obtain the status.  */
190f2a
 
190f2a
-int
190f2a
-net_open (struct serial *scb, const char *name)
190f2a
+static int
190f2a
+try_connect (const struct addrinfo *ainfo, unsigned int *polls)
190f2a
 {
190f2a
-  char hostname[100];
190f2a
-  const char *port_str;
190f2a
-  int n, port, tmp;
190f2a
-  int use_udp;
190f2a
-  struct hostent *hostent;
190f2a
-  struct sockaddr_in sockaddr;
190f2a
-#ifdef USE_WIN32API
190f2a
-  u_long ioarg;
190f2a
-#else
190f2a
-  int ioarg;
190f2a
-#endif
190f2a
-  unsigned int polls = 0;
190f2a
-
190f2a
-  use_udp = 0;
190f2a
-  if (startswith (name, "udp:"))
190f2a
-    {
190f2a
-      use_udp = 1;
190f2a
-      name = name + 4;
190f2a
-    }
190f2a
-  else if (startswith (name, "tcp:"))
190f2a
-    name = name + 4;
190f2a
-
190f2a
-  port_str = strchr (name, ':');
190f2a
-
190f2a
-  if (!port_str)
190f2a
-    error (_("net_open: No colon in host name!"));  /* Shouldn't ever
190f2a
-						       happen.  */
190f2a
-
190f2a
-  tmp = std::min (port_str - name, (ptrdiff_t) sizeof hostname - 1);
190f2a
-  strncpy (hostname, name, tmp);	/* Don't want colon.  */
190f2a
-  hostname[tmp] = '\000';	/* Tie off host name.  */
190f2a
-  port = atoi (port_str + 1);
190f2a
-
190f2a
-  /* Default hostname is localhost.  */
190f2a
-  if (!hostname[0])
190f2a
-    strcpy (hostname, "localhost");
190f2a
-
190f2a
-  hostent = gethostbyname (hostname);
190f2a
-  if (!hostent)
190f2a
-    {
190f2a
-      fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
190f2a
-      errno = ENOENT;
190f2a
-      return -1;
190f2a
-    }
190f2a
+  int sock = gdb_socket_cloexec (ainfo->ai_family, ainfo->ai_socktype,
190f2a
+				 ainfo->ai_protocol);
190f2a
 
190f2a
-  sockaddr.sin_family = PF_INET;
190f2a
-  sockaddr.sin_port = htons (port);
190f2a
-  memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
190f2a
-	  sizeof (struct in_addr));
190f2a
-
190f2a
- retry:
190f2a
-
190f2a
-  if (use_udp)
190f2a
-    scb->fd = gdb_socket_cloexec (PF_INET, SOCK_DGRAM, 0);
190f2a
-  else
190f2a
-    scb->fd = gdb_socket_cloexec (PF_INET, SOCK_STREAM, 0);
190f2a
-
190f2a
-  if (scb->fd == -1)
190f2a
+  if (sock < 0)
190f2a
     return -1;
190f2a
-  
190f2a
+
190f2a
   /* Set socket nonblocking.  */
190f2a
-  ioarg = 1;
190f2a
-  ioctl (scb->fd, FIONBIO, &ioarg);
190f2a
+  int ioarg = 1;
190f2a
+
190f2a
+  ioctl (sock, FIONBIO, &ioarg);
190f2a
 
190f2a
   /* Use Non-blocking connect.  connect() will return 0 if connected
190f2a
      already.  */
190f2a
-  n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
190f2a
-
190f2a
-  if (n < 0)
190f2a
+  if (connect (sock, ainfo->ai_addr, ainfo->ai_addrlen) < 0)
190f2a
     {
190f2a
 #ifdef USE_WIN32API
190f2a
       int err = WSAGetLastError();
190f2a
@@ -234,21 +185,26 @@ net_open (struct serial *scb, const char *name)
190f2a
       int err = errno;
190f2a
 #endif
190f2a
 
190f2a
-      /* Maybe we're waiting for the remote target to become ready to
190f2a
-	 accept connections.  */
190f2a
-      if (tcp_auto_retry
190f2a
+      /* If we've got a "connection refused" error, just return
190f2a
+	 -1.  The caller will know what to do.  */
190f2a
+      if (
190f2a
 #ifdef USE_WIN32API
190f2a
-	  && err == WSAECONNREFUSED
190f2a
+	  err == WSAECONNREFUSED
190f2a
 #else
190f2a
-	  && err == ECONNREFUSED
190f2a
+	  err == ECONNREFUSED
190f2a
 #endif
190f2a
-	  && wait_for_connect (NULL, &polls) >= 0)
190f2a
+	  )
190f2a
 	{
190f2a
-	  close (scb->fd);
190f2a
-	  goto retry;
190f2a
+	  close (sock);
190f2a
+	  errno = err;
190f2a
+	  return -1;
190f2a
 	}
190f2a
 
190f2a
       if (
190f2a
+	  /* Any other error (except EINPROGRESS) will be "swallowed"
190f2a
+	     here.  We return without specifying a return value, and
190f2a
+	     set errno if the caller wants to inspect what
190f2a
+	     happened.  */
190f2a
 #ifdef USE_WIN32API
190f2a
 	  /* Under Windows, calling "connect" with a non-blocking socket
190f2a
 	     results in WSAEWOULDBLOCK, not WSAEINPROGRESS.  */
190f2a
@@ -258,66 +214,166 @@ net_open (struct serial *scb, const char *name)
190f2a
 #endif
190f2a
 	  )
190f2a
 	{
190f2a
+	  close (sock);
190f2a
 	  errno = err;
190f2a
-	  net_close (scb);
190f2a
 	  return -1;
190f2a
 	}
190f2a
 
190f2a
       /* Looks like we need to wait for the connect.  */
190f2a
-      do 
190f2a
-	{
190f2a
-	  n = wait_for_connect (scb, &polls);
190f2a
-	} 
190f2a
+      int n;
190f2a
+
190f2a
+      do
190f2a
+	n = wait_for_connect (sock, polls);
190f2a
       while (n == 0);
190f2a
+
190f2a
       if (n < 0)
190f2a
 	{
190f2a
-	  net_close (scb);
190f2a
+	  int saved_errno = errno;
190f2a
+
190f2a
+	  /* A negative value here means that we either timed out or
190f2a
+	     got interrupted by the user.  Just return.  */
190f2a
+	  close (sock);
190f2a
+	  errno = saved_errno;
190f2a
 	  return -1;
190f2a
 	}
190f2a
     }
190f2a
 
190f2a
   /* Got something.  Is it an error?  */
190f2a
-  {
190f2a
-    int res, err;
190f2a
-    socklen_t len;
190f2a
-
190f2a
-    len = sizeof (err);
190f2a
-    /* On Windows, the fourth parameter to getsockopt is a "char *";
190f2a
-       on UNIX systems it is generally "void *".  The cast to "char *"
190f2a
-       is OK everywhere, since in C++ any data pointer type can be
190f2a
-       implicitly converted to "void *".  */
190f2a
-    res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (char *) &err, &len;;
190f2a
-    if (res < 0 || err)
190f2a
-      {
190f2a
-	/* Maybe the target still isn't ready to accept the connection.  */
190f2a
-	if (tcp_auto_retry
190f2a
+  int err;
190f2a
+  socklen_t len = sizeof (err);
190f2a
+
190f2a
+  /* On Windows, the fourth parameter to getsockopt is a "char *";
190f2a
+     on UNIX systems it is generally "void *".  The cast to "char *"
190f2a
+     is OK everywhere, since in C++ any data pointer type can be
190f2a
+     implicitly converted to "void *".  */
190f2a
+  int ret = getsockopt (sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len;;
190f2a
+
190f2a
+  if (ret < 0)
190f2a
+    {
190f2a
+      int saved_errno = errno;
190f2a
+
190f2a
+      close (sock);
190f2a
+      errno = saved_errno;
190f2a
+      return -1;
190f2a
+    }
190f2a
+  else if (ret == 0 && err != 0)
190f2a
+    {
190f2a
+      close (sock);
190f2a
+      errno = err;
190f2a
+      return -1;
190f2a
+    }
190f2a
+
190f2a
+  /* The connection succeeded.  Return the socket.  */
190f2a
+  return sock;
190f2a
+}
190f2a
+
190f2a
+/* Open a tcp socket.  */
190f2a
+
190f2a
+int
190f2a
+net_open (struct serial *scb, const char *name)
190f2a
+{
190f2a
+  struct addrinfo hint;
190f2a
+  struct addrinfo *ainfo;
190f2a
+
190f2a
+  memset (&hint, 0, sizeof (hint));
190f2a
+  /* Assume no prefix will be passed, therefore we should use
190f2a
+     AF_UNSPEC.  */
190f2a
+  hint.ai_family = AF_UNSPEC;
190f2a
+  hint.ai_socktype = SOCK_STREAM;
190f2a
+  hint.ai_protocol = IPPROTO_TCP;
190f2a
+
190f2a
+  parsed_connection_spec parsed = parse_connection_spec (name, &hint);
190f2a
+
190f2a
+  if (parsed.port_str.empty ())
190f2a
+    error (_("Missing port on hostname '%s'"), name);
190f2a
+
190f2a
+  int r = getaddrinfo (parsed.host_str.c_str (),
190f2a
+		       parsed.port_str.c_str (),
190f2a
+		       &hint, &ainfo);
190f2a
+
190f2a
+  if (r != 0)
190f2a
+    {
190f2a
+      fprintf_unfiltered (gdb_stderr, _("%s: cannot resolve name: %s\n"),
190f2a
+			  name, gai_strerror (r));
190f2a
+      errno = ENOENT;
190f2a
+      return -1;
190f2a
+    }
190f2a
+
190f2a
+  scoped_free_addrinfo free_ainfo (ainfo);
190f2a
+
190f2a
+  /* Flag to indicate whether we've got a connection refused.  It will
190f2a
+     be true if any of the connections tried was refused.  */
190f2a
+  bool got_connrefused;
190f2a
+  /* If a connection succeeeds, SUCCESS_AINFO will point to the
190f2a
+     'struct addrinfo' that succeed.  */
190f2a
+  struct addrinfo *success_ainfo = NULL;
190f2a
+  unsigned int polls = 0;
190f2a
+
190f2a
+  /* Assume the worst.  */
190f2a
+  scb->fd = -1;
190f2a
+
190f2a
+  do
190f2a
+    {
190f2a
+      got_connrefused = false;
190f2a
+
190f2a
+      for (struct addrinfo *iter = ainfo; iter != NULL; iter = iter->ai_next)
190f2a
+	{
190f2a
+	  /* Iterate over the list of possible addresses to connect
190f2a
+	     to.  For each, we'll try to connect and see if it
190f2a
+	     succeeds.  */
190f2a
+	  int sock = try_connect (iter, &polls);
190f2a
+
190f2a
+	  if (sock >= 0)
190f2a
+	    {
190f2a
+	      /* We've gotten a successful connection.  Save its
190f2a
+		 'struct addrinfo', the socket, and break.  */
190f2a
+	      success_ainfo = iter;
190f2a
+	      scb->fd = sock;
190f2a
+	      break;
190f2a
+	    }
190f2a
+	  else if (
190f2a
 #ifdef USE_WIN32API
190f2a
-	    && err == WSAECONNREFUSED
190f2a
+	  errno == WSAECONNREFUSED
190f2a
 #else
190f2a
-	    && err == ECONNREFUSED
190f2a
+	  errno == ECONNREFUSED
190f2a
 #endif
190f2a
-	    && wait_for_connect (NULL, &polls) >= 0)
190f2a
-	  {
190f2a
-	    close (scb->fd);
190f2a
-	    goto retry;
190f2a
-	  }
190f2a
-	if (err)
190f2a
-	  errno = err;
190f2a
-	net_close (scb);
190f2a
-	return -1;
190f2a
-      }
190f2a
-  } 
190f2a
+		   )
190f2a
+	    got_connrefused = true;
190f2a
+	}
190f2a
+    }
190f2a
+  /* Just retry if:
190f2a
+
190f2a
+     - tcp_auto_retry is true, and
190f2a
+     - We haven't gotten a connection yet, and
190f2a
+     - Any of our connection attempts returned with ECONNREFUSED, and
190f2a
+     - wait_for_connect signals that we can keep going.  */
190f2a
+  while (tcp_auto_retry
190f2a
+	 && success_ainfo == NULL
190f2a
+	 && got_connrefused
190f2a
+	 && wait_for_connect (-1, &polls) >= 0);
190f2a
+
190f2a
+  if (success_ainfo == NULL)
190f2a
+    {
190f2a
+      net_close (scb);
190f2a
+      return -1;
190f2a
+    }
190f2a
 
190f2a
   /* Turn off nonblocking.  */
190f2a
-  ioarg = 0;
190f2a
+#ifdef USE_WIN32API
190f2a
+  u_long ioarg = 0;
190f2a
+#else
190f2a
+  int ioarg = 0;
190f2a
+#endif
190f2a
+
190f2a
   ioctl (scb->fd, FIONBIO, &ioarg);
190f2a
 
190f2a
-  if (use_udp == 0)
190f2a
+  if (success_ainfo->ai_socktype == IPPROTO_TCP)
190f2a
     {
190f2a
       /* Disable Nagle algorithm.  Needed in some cases.  */
190f2a
-      tmp = 1;
190f2a
+      int tmp = 1;
190f2a
+
190f2a
       setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY,
190f2a
-		  (char *)&tmp, sizeof (tmp));
190f2a
+		  (char *) &tmp, sizeof (tmp));
190f2a
     }
190f2a
 
190f2a
 #ifdef SIGPIPE
190f2a
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
190f2a
--- a/gdb/testsuite/ChangeLog
190f2a
+++ b/gdb/testsuite/ChangeLog
190f2a
@@ -1,3 +1,23 @@
190f2a
+2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
190f2a
+	    Jan Kratochvil  <jan.kratochvil@redhat.com>
190f2a
+	    Paul Fertser  <fercerpav@gmail.com>
190f2a
+	    Tsutomu Seki  <sekiriki@gmail.com>
190f2a
+
190f2a
+	* README (Testsuite Parameters): Mention new 'GDB_TEST_SOCKETHOST'
190f2a
+	parameter.
190f2a
+	* boards/native-extended-gdbserver.exp: Do not set 'sockethost'
190f2a
+	by default.
190f2a
+	* boards/native-gdbserver.exp: Likewise.
190f2a
+	* gdb.server/run-without-local-binary.exp: Improve regexp used
190f2a
+	for detecting when a remote debugging connection succeeds.
190f2a
+	* gdb.server/server-connect.exp: New file.
190f2a
+	* lib/gdbserver-support.exp (gdbserver_default_get_comm_port):
190f2a
+	Do not prefix the port number with ":".
190f2a
+	(gdbserver_start): New global GDB_TEST_SOCKETHOST.  Implement
190f2a
+	support for detecting and using it.  Add '$debughost_gdbserver'
190f2a
+	to the list of arguments used to start gdbserver.  Handle case
190f2a
+	when gdbserver cannot resolve a network name.
190f2a
+
190f2a
 2018-08-31  Tom Tromey  <tom@tromey.com>
190f2a
 
190f2a
 	* gdb.rust/simple.rs: Rename second variable "v".
190f2a
diff --git a/gdb/testsuite/README b/gdb/testsuite/README
190f2a
--- a/gdb/testsuite/README
190f2a
+++ b/gdb/testsuite/README
190f2a
@@ -259,6 +259,20 @@ This make (not runtest) variable is used to specify whether the
190f2a
 testsuite preloads the read1.so library into expect.  Any non-empty
190f2a
 value means true.  See "Race detection" below.
190f2a
 
190f2a
+GDB_TEST_SOCKETHOST
190f2a
+
190f2a
+This variable can provide the hostname/address that should be used
190f2a
+when performing GDBserver-related tests.  This is useful in some
190f2a
+situations, e.g., when you want to test the IPv6 connectivity of GDB
190f2a
+and GDBserver, or when using a different hostname/address is needed.
190f2a
+For example, to make GDB and GDBserver use IPv6-only connections, you
190f2a
+can do:
190f2a
+
190f2a
+	make check TESTS="gdb.server/*.exp" RUNTESTFLAGS='GDB_TEST_SOCKETHOST=tcp6:[::1]'
190f2a
+
190f2a
+Note that only a hostname/address can be provided, without a port
190f2a
+number.
190f2a
+
190f2a
 Race detection
190f2a
 **************
190f2a
 
190f2a
diff --git a/gdb/testsuite/boards/native-extended-gdbserver.exp b/gdb/testsuite/boards/native-extended-gdbserver.exp
190f2a
--- a/gdb/testsuite/boards/native-extended-gdbserver.exp
190f2a
+++ b/gdb/testsuite/boards/native-extended-gdbserver.exp
190f2a
@@ -24,8 +24,6 @@ load_generic_config "extended-gdbserver"
190f2a
 load_board_description "gdbserver-base"
190f2a
 load_board_description "local-board"
190f2a
 
190f2a
-set_board_info sockethost "localhost:"
190f2a
-
190f2a
 # We will be using the extended GDB remote protocol.
190f2a
 set_board_info gdb_protocol "extended-remote"
190f2a
 
190f2a
diff --git a/gdb/testsuite/boards/native-gdbserver.exp b/gdb/testsuite/boards/native-gdbserver.exp
190f2a
--- a/gdb/testsuite/boards/native-gdbserver.exp
190f2a
+++ b/gdb/testsuite/boards/native-gdbserver.exp
190f2a
@@ -30,7 +30,6 @@ set_board_info gdb,do_reload_on_run 1
190f2a
 # There's no support for argument-passing (yet).
190f2a
 set_board_info noargs 1
190f2a
 
190f2a
-set_board_info sockethost "localhost:"
190f2a
 set_board_info use_gdb_stub 1
190f2a
 set_board_info exit_is_reliable 1
190f2a
 
190f2a
diff --git a/gdb/testsuite/gdb.server/run-without-local-binary.exp b/gdb/testsuite/gdb.server/run-without-local-binary.exp
190f2a
--- a/gdb/testsuite/gdb.server/run-without-local-binary.exp
190f2a
+++ b/gdb/testsuite/gdb.server/run-without-local-binary.exp
190f2a
@@ -53,7 +53,7 @@ save_vars { GDBFLAGS } {
190f2a
     set use_gdb_stub 0
190f2a
 
190f2a
     gdb_test "target ${gdbserver_protocol} ${gdbserver_gdbport}" \
190f2a
-	"Remote debugging using $gdbserver_gdbport" \
190f2a
+	"Remote debugging using [string_to_regexp $gdbserver_gdbport]" \
190f2a
 	"connect to gdbserver"
190f2a
 
190f2a
     gdb_test "run" \
190f2a
diff --git a/gdb/testsuite/gdb.server/server-connect.exp b/gdb/testsuite/gdb.server/server-connect.exp
190f2a
new file mode 100644
190f2a
--- /dev/null
190f2a
+++ b/gdb/testsuite/gdb.server/server-connect.exp
190f2a
@@ -0,0 +1,111 @@
190f2a
+# This testcase is part of GDB, the GNU debugger.
190f2a
+#
190f2a
+# Copyright 2018 Free Software Foundation, Inc.
190f2a
+#
190f2a
+# This program is free software; you can redistribute it and/or modify
190f2a
+# it under the terms of the GNU General Public License as published by
190f2a
+# the Free Software Foundation; either version 3 of the License, or
190f2a
+# (at your option) any later version.
190f2a
+#
190f2a
+# This program is distributed in the hope that it will be useful,
190f2a
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
190f2a
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
190f2a
+# GNU General Public License for more details.
190f2a
+#
190f2a
+# You should have received a copy of the GNU General Public License
190f2a
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
190f2a
+
190f2a
+# Test multiple types of connection (IPv4, IPv6, TCP, UDP) and make
190f2a
+# sure both gdbserver and GDB work.
190f2a
+
190f2a
+load_lib gdbserver-support.exp
190f2a
+
190f2a
+standard_testfile normal.c
190f2a
+
190f2a
+if {[skip_gdbserver_tests]} {
190f2a
+    return 0
190f2a
+}
190f2a
+
190f2a
+# We want to have control over where we start gdbserver.
190f2a
+if { [is_remote target] } {
190f2a
+    return 0
190f2a
+}
190f2a
+
190f2a
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
190f2a
+    return -1
190f2a
+}
190f2a
+
190f2a
+# Make sure we're disconnected, in case we're testing with an
190f2a
+# extended-remote board, therefore already connected.
190f2a
+gdb_test "disconnect" ".*"
190f2a
+
190f2a
+set target_exec [gdbserver_download_current_prog]
190f2a
+
190f2a
+# An array containing the test instructions for each scenario.  The
190f2a
+# description of each field is as follows:
190f2a
+#
190f2a
+# - The connection specification to be used when starting
190f2a
+#   gdbserver/GDB.  This string will be used to set the
190f2a
+#   GDB_TEST_SOCKETHOST when calling gdbserver_start.
190f2a
+#
190f2a
+# - A flag indicating whether gdbserver should fail when we attempt to
190f2a
+#   start it.  Useful when testing erroneous connection specs such as
190f2a
+#   "tcp8:".
190f2a
+#
190f2a
+# - The prefix that should be prepended to the test messages.
190f2a
+set test_params \
190f2a
+    { \
190f2a
+	  { "tcp4:127.0.0.1" 0 "tcp4" } \
190f2a
+	  { "tcp6:::1"       0 "tcp6" } \
190f2a
+	  { "tcp6:[::1]"     0 "tcp6-with-brackets" } \
190f2a
+	  { "tcp:localhost"  0 "tcp" } \
190f2a
+	  { "udp4:127.0.0.1" 0 "udp4" } \
190f2a
+	  { "udp6:::1"       0 "udp6" } \
190f2a
+	  { "udp6:[::1]"     0 "udp6-with-brackets" } \
190f2a
+	  { "tcp8:123"       1 "tcp8" } \
190f2a
+	  { "udp123:::"      1 "udp123" } \
190f2a
+	  { "garbage:1234"   1 "garbage:1234" } \
190f2a
+    }
190f2a
+
190f2a
+# The best way to test different types of connections is to set the
190f2a
+# GDB_TEST_SOCKETHOST variable accordingly.
190f2a
+save_vars { GDB_TEST_SOCKETHOST } {
190f2a
+    foreach line $test_params {
190f2a
+	set sockhost [lindex $line 0]
190f2a
+	set gdbserver_should_fail [lindex $line 1]
190f2a
+	set prefix [lindex $line 2]
190f2a
+
190f2a
+	with_test_prefix $prefix {
190f2a
+	    set GDB_TEST_SOCKETHOST $sockhost
190f2a
+	    set test "start gdbserver"
190f2a
+
190f2a
+	    # Try to start gdbserver.
190f2a
+	    set catchres [catch {set res [gdbserver_start "" $target_exec]} errmsg]
190f2a
+
190f2a
+	    if { $catchres != 0 } {
190f2a
+		if { $gdbserver_should_fail } {
190f2a
+		    pass "$test: gdbserver failed as expected"
190f2a
+		} else {
190f2a
+		    fail "$test: $errmsg"
190f2a
+		}
190f2a
+		continue
190f2a
+	    } else {
190f2a
+		if { $gdbserver_should_fail } {
190f2a
+		    fail "$test: gdbserver should fail but did not"
190f2a
+		} else {
190f2a
+		    pass "$test"
190f2a
+		}
190f2a
+	    }
190f2a
+
190f2a
+	    set gdbserver_protocol [lindex $res 0]
190f2a
+	    set gdbserver_gdbport [lindex $res 1]
190f2a
+	    set test "connect to gdbserver using $sockhost"
190f2a
+
190f2a
+	    if { [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport] == 0 } {
190f2a
+		pass $test
190f2a
+	    } else {
190f2a
+		fail $test
190f2a
+	    }
190f2a
+	}
190f2a
+    }
190f2a
+}
190f2a
diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp
190f2a
--- a/gdb/testsuite/lib/gdbserver-support.exp
190f2a
+++ b/gdb/testsuite/lib/gdbserver-support.exp
190f2a
@@ -211,7 +211,7 @@ proc gdbserver_default_get_remote_address { host port } {
190f2a
 # Default routine to compute the "comm" argument for gdbserver.
190f2a
 
190f2a
 proc gdbserver_default_get_comm_port { port } {
190f2a
-    return ":$port"
190f2a
+    return "$port"
190f2a
 }
190f2a
 
190f2a
 # Start a gdbserver process with initial OPTIONS and trailing ARGUMENTS.
190f2a
@@ -221,6 +221,7 @@ proc gdbserver_default_get_comm_port { port } {
190f2a
 
190f2a
 proc gdbserver_start { options arguments } {
190f2a
     global portnum
190f2a
+    global GDB_TEST_SOCKETHOST
190f2a
 
190f2a
     # Port id -- either specified in baseboard file, or managed here.
190f2a
     if [target_info exists gdb,socketport] {
190f2a
@@ -231,10 +232,22 @@ proc gdbserver_start { options arguments } {
190f2a
     }
190f2a
 
190f2a
     # Extract the local and remote host ids from the target board struct.
190f2a
-    if [target_info exists sockethost] {
190f2a
+    if { [info exists GDB_TEST_SOCKETHOST] } {
190f2a
+	# The user is not supposed to provide a port number, just a
190f2a
+	# hostname/address, therefore we add the trailing ":" here.
190f2a
+	set debughost "${GDB_TEST_SOCKETHOST}:"
190f2a
+	# Escape open and close square brackets.
190f2a
+	set debughost_tmp [string map { [ \\[ ] \\] } $debughost]
190f2a
+	# We need a "gdbserver" version of the debughost, which will
190f2a
+	# have the possible connection prefix stripped.  This is
190f2a
+	# because gdbserver currently doesn't recognize the prefixes.
190f2a
+	regsub -all "^\(tcp:|udp:|tcp4:|udp4:|tcp6:|udp6:\)" $debughost_tmp "" debughost_gdbserver
190f2a
+    } elseif [target_info exists sockethost] {
190f2a
 	set debughost [target_info sockethost]
190f2a
+	set debughost_gdbserver $debughost
190f2a
     } else {
190f2a
 	set debughost "localhost:"
190f2a
+	set debughost_gdbserver $debughost
190f2a
     }
190f2a
 
190f2a
     # Some boards use a different value for the port that is passed to
190f2a
@@ -277,8 +290,14 @@ proc gdbserver_start { options arguments } {
190f2a
 	if { $options != "" } {
190f2a
 	    append gdbserver_command " $options"
190f2a
 	}
190f2a
+	if { $debughost_gdbserver != "" } {
190f2a
+	    append gdbserver_command " $debughost_gdbserver"
190f2a
+	}
190f2a
 	if { $portnum != "" } {
190f2a
-	    append gdbserver_command " [$get_comm_port $portnum]"
190f2a
+	    if { $debughost_gdbserver == "" } {
190f2a
+		append gdbserver_command " "
190f2a
+	    }
190f2a
+	    append gdbserver_command "[$get_comm_port $portnum]"
190f2a
 	}
190f2a
 	if { $arguments != "" } {
190f2a
 	    append gdbserver_command " $arguments"
190f2a
@@ -307,6 +326,9 @@ proc gdbserver_start { options arguments } {
190f2a
 		    continue
190f2a
 		}
190f2a
 	    }
190f2a
+	    -re ".*: cannot resolve name: Name or service not known\r\n" {
190f2a
+		error "gdbserver cannot resolve name."
190f2a
+	    }
190f2a
 	    timeout {
190f2a
 		error "Timeout waiting for gdbserver response."
190f2a
 	    }
190f2a
diff --git a/gdb/unittests/parse-connection-spec-selftests.c b/gdb/unittests/parse-connection-spec-selftests.c
190f2a
new file mode 100644
190f2a
--- /dev/null
190f2a
+++ b/gdb/unittests/parse-connection-spec-selftests.c
190f2a
@@ -0,0 +1,249 @@
190f2a
+/* Self tests for parsing connection specs for GDB, the GNU debugger.
190f2a
+
190f2a
+   Copyright (C) 2018 Free Software Foundation, Inc.
190f2a
+
190f2a
+   This file is part of GDB.
190f2a
+
190f2a
+   This program is free software; you can redistribute it and/or modify
190f2a
+   it under the terms of the GNU General Public License as published by
190f2a
+   the Free Software Foundation; either version 3 of the License, or
190f2a
+   (at your option) any later version.
190f2a
+
190f2a
+   This program is distributed in the hope that it will be useful,
190f2a
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
190f2a
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
190f2a
+   GNU General Public License for more details.
190f2a
+
190f2a
+   You should have received a copy of the GNU General Public License
190f2a
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
190f2a
+
190f2a
+#include "defs.h"
190f2a
+#include "selftest.h"
190f2a
+#include "common/netstuff.h"
190f2a
+#include "diagnostics.h"
190f2a
+#ifdef USE_WIN32API
190f2a
+#include <winsock2.h>
190f2a
+#include <wspiapi.h>
190f2a
+#else
190f2a
+#include <netinet/in.h>
190f2a
+#include <arpa/inet.h>
190f2a
+#include <netdb.h>
190f2a
+#include <sys/socket.h>
190f2a
+#include <netinet/tcp.h>
190f2a
+#endif
190f2a
+
190f2a
+namespace selftests {
190f2a
+namespace parse_connection_spec_tests {
190f2a
+
190f2a
+/* Auxiliary struct that holds info about a specific test for a
190f2a
+   connection spec.  */
190f2a
+
190f2a
+struct parse_conn_test
190f2a
+{
190f2a
+  /* The connection spec.  */
190f2a
+  const char *connspec;
190f2a
+
190f2a
+  /* Expected result from 'parse_connection_spec'.  */
190f2a
+  parsed_connection_spec expected_result;
190f2a
+
190f2a
+  /* True if this test should fail, false otherwise.  If true, only
190f2a
+     the CONNSPEC field should be considered as valid.  */
190f2a
+  bool should_fail;
190f2a
+
190f2a
+  /* The expected AI_FAMILY to be found on the 'struct addrinfo'
190f2a
+     HINT.  */
190f2a
+  int exp_ai_family;
190f2a
+
190f2a
+  /* The expected AI_SOCKTYPE to be found on the 'struct addrinfo'
190f2a
+     HINT.  */
190f2a
+  int exp_ai_socktype;
190f2a
+
190f2a
+  /* The expected AI_PROTOCOL to be found on the 'struct addrinfo'
190f2a
+     HINT.  */
190f2a
+  int exp_ai_protocol;
190f2a
+};
190f2a
+
190f2a
+/* Some defines to help us fill a 'struct parse_conn_test'.  */
190f2a
+
190f2a
+/* Initialize a full entry.  */
190f2a
+#define INIT_ENTRY(ADDR, EXP_HOST, EXP_PORT, SHOULD_FAIL, EXP_AI_FAMILY, \
190f2a
+		   EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL)			\
190f2a
+  { ADDR, { EXP_HOST, EXP_PORT }, SHOULD_FAIL, EXP_AI_FAMILY, \
190f2a
+    EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL }
190f2a
+
190f2a
+/* Initialize an unprefixed entry.  In this case, we don't expect
190f2a
+   anything on the 'struct addrinfo' HINT.  */
190f2a
+#define INIT_UNPREFIXED_ENTRY(ADDR, EXP_HOST, EXP_PORT) \
190f2a
+  INIT_ENTRY (ADDR, EXP_HOST, EXP_PORT, false, 0, 0, 0)
190f2a
+
190f2a
+/* Initialized an unprefixed IPv6 entry.  In this case, we don't
190f2a
+   expect anything on the 'struct addrinfo' HINT.  */
190f2a
+#define INIT_UNPREFIXED_IPV6_ENTRY(ADDR, EXP_HOST, EXP_PORT) \
190f2a
+  INIT_ENTRY (ADDR, EXP_HOST, EXP_PORT, false, AF_INET6, 0, 0)
190f2a
+
190f2a
+/* Initialize a prefixed entry.  */
190f2a
+#define INIT_PREFIXED_ENTRY(ADDR, EXP_HOST, EXP_PORT, EXP_AI_FAMILY, \
190f2a
+			    EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL) \
190f2a
+  INIT_ENTRY (ADDR, EXP_HOST, EXP_PORT, false, EXP_AI_FAMILY, \
190f2a
+	      EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL)
190f2a
+
190f2a
+/* Initialize an entry prefixed with "tcp4:".  */
190f2a
+#define INIT_PREFIXED_IPV4_TCP(ADDR, EXP_HOST, EXP_PORT) \
190f2a
+  INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET, SOCK_STREAM, \
190f2a
+		       IPPROTO_TCP)
190f2a
+
190f2a
+/* Initialize an entry prefixed with "tcp6:".  */
190f2a
+#define INIT_PREFIXED_IPV6_TCP(ADDR, EXP_HOST, EXP_PORT) \
190f2a
+  INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET6, SOCK_STREAM, \
190f2a
+		       IPPROTO_TCP)
190f2a
+
190f2a
+/* Initialize an entry prefixed with "udp4:".  */
190f2a
+#define INIT_PREFIXED_IPV4_UDP(ADDR, EXP_HOST, EXP_PORT) \
190f2a
+  INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET, SOCK_DGRAM, \
190f2a
+		       IPPROTO_UDP)
190f2a
+
190f2a
+/* Initialize an entry prefixed with "udp6:".  */
190f2a
+#define INIT_PREFIXED_IPV6_UDP(ADDR, EXP_HOST, EXP_PORT) \
190f2a
+  INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET6, SOCK_DGRAM, \
190f2a
+		       IPPROTO_UDP)
190f2a
+
190f2a
+/* Initialize a bogus entry, i.e., a connection spec that should
190f2a
+   fail.  */
190f2a
+#define INIT_BOGUS_ENTRY(ADDR) \
190f2a
+  INIT_ENTRY (ADDR, "", "", true, 0, 0, 0)
190f2a
+
190f2a
+/* The variable which holds all of our tests.  */
190f2a
+
190f2a
+static const parse_conn_test conn_test[] =
190f2a
+  {
190f2a
+    /* Unprefixed addresses.  */
190f2a
+
190f2a
+    /* IPv4, host and port present.  */
190f2a
+    INIT_UNPREFIXED_ENTRY ("127.0.0.1:1234", "127.0.0.1", "1234"),
190f2a
+    /* IPv4, only host.  */
190f2a
+    INIT_UNPREFIXED_ENTRY ("127.0.0.1", "127.0.0.1", ""),
190f2a
+    /* IPv4, missing port.  */
190f2a
+    INIT_UNPREFIXED_ENTRY ("127.0.0.1:", "127.0.0.1", ""),
190f2a
+
190f2a
+    /* IPv6, host and port present, no brackets.  */
190f2a
+    INIT_UNPREFIXED_ENTRY ("::1:1234", "::1", "1234"),
190f2a
+    /* IPv6, missing port, no brackets.  */
190f2a
+    INIT_UNPREFIXED_ENTRY ("::1:", "::1", ""),
190f2a
+    /* IPv6, host and port present, with brackets.  */
190f2a
+    INIT_UNPREFIXED_IPV6_ENTRY ("[::1]:1234", "::1", "1234"),
190f2a
+    /* IPv6, only host, with brackets.  */
190f2a
+    INIT_UNPREFIXED_IPV6_ENTRY ("[::1]", "::1", ""),
190f2a
+    /* IPv6, missing port, with brackets.  */
190f2a
+    INIT_UNPREFIXED_IPV6_ENTRY ("[::1]:", "::1", ""),
190f2a
+
190f2a
+    /* Unspecified, only port.  */
190f2a
+    INIT_UNPREFIXED_ENTRY (":1234", "localhost", "1234"),
190f2a
+
190f2a
+    /* Prefixed addresses.  */
190f2a
+
190f2a
+    /* Prefixed "tcp4:" IPv4, host and port presents.  */
190f2a
+    INIT_PREFIXED_IPV4_TCP ("tcp4:127.0.0.1:1234", "127.0.0.1", "1234"),
190f2a
+    /* Prefixed "tcp4:" IPv4, only port.  */
190f2a
+    INIT_PREFIXED_IPV4_TCP ("tcp4::1234", "localhost", "1234"),
190f2a
+    /* Prefixed "tcp4:" IPv4, only host.  */
190f2a
+    INIT_PREFIXED_IPV4_TCP ("tcp4:127.0.0.1", "127.0.0.1", ""),
190f2a
+    /* Prefixed "tcp4:" IPv4, missing port.  */
190f2a
+    INIT_PREFIXED_IPV4_TCP ("tcp4:127.0.0.1:", "127.0.0.1", ""),
190f2a
+
190f2a
+    /* Prefixed "udp4:" IPv4, host and port present.  */
190f2a
+    INIT_PREFIXED_IPV4_UDP ("udp4:127.0.0.1:1234", "127.0.0.1", "1234"),
190f2a
+    /* Prefixed "udp4:" IPv4, only port.  */
190f2a
+    INIT_PREFIXED_IPV4_UDP ("udp4::1234", "localhost", "1234"),
190f2a
+    /* Prefixed "udp4:" IPv4, only host.  */
190f2a
+    INIT_PREFIXED_IPV4_UDP ("udp4:127.0.0.1", "127.0.0.1", ""),
190f2a
+    /* Prefixed "udp4:" IPv4, missing port.  */
190f2a
+    INIT_PREFIXED_IPV4_UDP ("udp4:127.0.0.1:", "127.0.0.1", ""),
190f2a
+
190f2a
+
190f2a
+    /* Prefixed "tcp6:" IPv6, host and port present.  */
190f2a
+    INIT_PREFIXED_IPV6_TCP ("tcp6:::1:1234", "::1", "1234"),
190f2a
+    /* Prefixed "tcp6:" IPv6, only port.  */
190f2a
+    INIT_PREFIXED_IPV6_TCP ("tcp6::1234", "localhost", "1234"),
190f2a
+    /* Prefixed "tcp6:" IPv6, only host.  */
190f2a
+    //INIT_PREFIXED_IPV6_TCP ("tcp6:::1", "::1", ""),
190f2a
+    /* Prefixed "tcp6:" IPv6, missing port.  */
190f2a
+    INIT_PREFIXED_IPV6_TCP ("tcp6:::1:", "::1", ""),
190f2a
+
190f2a
+    /* Prefixed "udp6:" IPv6, host and port present.  */
190f2a
+    INIT_PREFIXED_IPV6_UDP ("udp6:::1:1234", "::1", "1234"),
190f2a
+    /* Prefixed "udp6:" IPv6, only port.  */
190f2a
+    INIT_PREFIXED_IPV6_UDP ("udp6::1234", "localhost", "1234"),
190f2a
+    /* Prefixed "udp6:" IPv6, only host.  */
190f2a
+    //INIT_PREFIXED_IPV6_UDP ("udp6:::1", "::1", ""),
190f2a
+    /* Prefixed "udp6:" IPv6, missing port.  */
190f2a
+    INIT_PREFIXED_IPV6_UDP ("udp6:::1:", "::1", ""),
190f2a
+
190f2a
+    /* Prefixed "tcp6:" IPv6 with brackets, host and port present.  */
190f2a
+    INIT_PREFIXED_IPV6_TCP ("tcp6:[::1]:1234", "::1", "1234"),
190f2a
+    /* Prefixed "tcp6:" IPv6 with brackets, only host.  */
190f2a
+    INIT_PREFIXED_IPV6_TCP ("tcp6:[::1]", "::1", ""),
190f2a
+    /* Prefixed "tcp6:" IPv6 with brackets, missing port.  */
190f2a
+    INIT_PREFIXED_IPV6_TCP ("tcp6:[::1]:", "::1", ""),
190f2a
+
190f2a
+    /* Prefixed "udp6:" IPv6 with brackets, host and port present.  */
190f2a
+    INIT_PREFIXED_IPV6_UDP ("udp6:[::1]:1234", "::1", "1234"),
190f2a
+    /* Prefixed "udp6:" IPv6 with brackets, only host.  */
190f2a
+    INIT_PREFIXED_IPV6_UDP ("udp6:[::1]", "::1", ""),
190f2a
+    /* Prefixed "udp6:" IPv6 with brackets, missing port.  */
190f2a
+    INIT_PREFIXED_IPV6_UDP ("udp6:[::1]:", "::1", ""),
190f2a
+
190f2a
+
190f2a
+    /* Bogus addresses.  */
190f2a
+    INIT_BOGUS_ENTRY ("tcp6:[::1]123:44"),
190f2a
+    INIT_BOGUS_ENTRY ("[::1"),
190f2a
+    INIT_BOGUS_ENTRY ("tcp6:::1]:"),
190f2a
+  };
190f2a
+
190f2a
+/* Test a connection spec C.  */
190f2a
+
190f2a
+static void
190f2a
+test_conn (const parse_conn_test &c)
190f2a
+{
190f2a
+  struct addrinfo hint;
190f2a
+  parsed_connection_spec ret;
190f2a
+
190f2a
+  memset (&hint, 0, sizeof (hint));
190f2a
+
190f2a
+  TRY
190f2a
+    {
190f2a
+      ret = parse_connection_spec (c.connspec, &hint);
190f2a
+    }
190f2a
+  CATCH (ex, RETURN_MASK_ERROR)
190f2a
+    {
190f2a
+      /* If we caught an error, we should check if this connection
190f2a
+	 spec was supposed to fail.  */
190f2a
+      SELF_CHECK (c.should_fail);
190f2a
+      return;
190f2a
+    }
190f2a
+  END_CATCH
190f2a
+
190f2a
+  SELF_CHECK (!c.should_fail);
190f2a
+  SELF_CHECK (ret.host_str == c.expected_result.host_str);
190f2a
+  SELF_CHECK (ret.port_str == c.expected_result.port_str);
190f2a
+  SELF_CHECK (hint.ai_family == c.exp_ai_family);
190f2a
+  SELF_CHECK (hint.ai_socktype == c.exp_ai_socktype);
190f2a
+  SELF_CHECK (hint.ai_protocol == c.exp_ai_protocol);
190f2a
+}
190f2a
+
190f2a
+/* Run the tests associated with parsing connection specs.  */
190f2a
+
190f2a
+static void
190f2a
+run_tests ()
190f2a
+{
190f2a
+  for (const parse_conn_test &c : conn_test)
190f2a
+    test_conn (c);
190f2a
+}
190f2a
+} /* namespace parse_connection_spec_tests */
190f2a
+} /* namespace selftests */
190f2a
+
190f2a
+void
190f2a
+_initialize_parse_connection_spec_selftests ()
190f2a
+{
190f2a
+  selftests::register_test ("parse_connection_spec",
190f2a
+			    selftests::parse_connection_spec_tests::run_tests);
190f2a
+}