diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2d09d13..d696ce4 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19565,16 +19565,17 @@ If you're using a serial line, you may want
to give @value{GDBN} the
 @code{target} command.

 @item target remote @code{@var{host}:@var{port}}
+@itemx target remote @code{[@var{host}]:@var{port}}
 @itemx target remote @code{tcp:@var{host}:@var{port}}
 @itemx target extended-remote @code{@var{host}:@var{port}}
 @itemx target extended-remote @code{tcp:@var{host}:@var{port}}
 @cindex @acronym{TCP} port, @code{target remote}
 Debug using a @acronym{TCP} connection to @var{port} on @var{host}.
 The @var{host} may be either a host name or a numeric @acronym{IP}
-address; @var{port} must be a decimal number.  The @var{host} could be
-the target machine itself, if it is directly connected to the net, or
-it might be a terminal server which in turn has a serial line to the
-target.
+address; @var{port} may be either a service name or a decimal number.
+The @var{host} could be the target machine itself, if it is directly
+connected to the net, or it might be a terminal server which in turn
+has a serial line to the target.

 For example, to connect to port 2828 on a terminal server named
 @code{manyfarms}:
@@ -19583,6 +19584,14 @@ For example, to connect to port 2828 on a
terminal server named
 target remote manyfarms:2828
 @end smallexample

+Numerical @acronym{IPv6} address must be enclosed in square brackets.
+For example, to connect to port 2159 of a target which has IPv6
+link-local address fe80::1 on eth1:
+
+@smallexample
+target remote [fe80::1%eth1]:2159
+@end smallexample
+
 If your remote target is actually running on the same machine as your
 debugger session (e.g.@: a simulator for your target running on the
 same host), you can omit the hostname.  For example, to connect to
@@ -19591,6 +19600,16 @@ port 1234 on your local machine:
 @smallexample
 target remote :1234
 @end smallexample
+
+The service name is default to ``gdbremote''. If the service name is
+present in service list (e.g.@: @file{/etc/services} on @sc{gnu}/Linux
+systems), and target is listening on assigned port, you can omit the
+service name. For example, to connect to service ``gdbremote'' on your
+local machine:
+
+@smallexample
+target remote :
+@end smallexample
 @noindent

 Note that the colon is still required here.
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
index df3af4c..4ed5f2a 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -39,6 +39,7 @@

 #ifdef USE_WIN32API
 #include <winsock2.h>
+#include <wspiapi.h>
 #ifndef ETIMEDOUT
 #define ETIMEDOUT WSAETIMEDOUT
 #endif
@@ -156,11 +157,10 @@ int
 net_open (struct serial *scb, const char *name)
 {
   char hostname[100];
-  const char *port_str;
-  int n, port, tmp;
+  const char *port_str, *host_str;
+  int n, tmp, err;
   int use_udp;
-  struct hostent *hostent;
-  struct sockaddr_in sockaddr;
+  struct addrinfo *ai, hint;
 #ifdef USE_WIN32API
   u_long ioarg;
 #else
@@ -177,43 +177,65 @@ net_open (struct serial *scb, const char *name)
   else if (startswith (name, "tcp:"))
     name = name + 4;

-  port_str = strchr (name, ':');
+  if (name[0] == '[')
+    {
+      const char *end = strchr(name + 1, ']');
+      if (!end)
+ error (_("net_open: No close bracket in host name!"));
+
+      tmp = min (end - name - 1, (int) sizeof hostname - 1);
+      strncpy (hostname, name + 1, tmp); /* Don't want brackets. */
+      hostname[tmp] = '\0'; /* Tie off host name.  */
+      host_str = hostname;
+      port_str = end + 1;
+    }
+  else if ((port_str = strrchr(name, ':')) != NULL)
+    {
+      tmp = min (port_str - name, (int) sizeof hostname - 1);
+      strncpy (hostname, name, tmp); /* Don't want colon.  */
+      hostname[tmp] = '\0'; /* Tie off host name.  */
+      host_str = hostname;
+    }
+  else
+    {
+      host_str = name;
+      port_str = NULL;
+    }

-  if (!port_str)
-    error (_("net_open: No colon in host name!"));  /* Shouldn't ever
-       happen.  */
+  if (port_str != NULL && port_str[0] == ':')
+    port_str++;

-  tmp = min (port_str - name, (int) sizeof hostname - 1);
-  strncpy (hostname, name, tmp); /* Don't want colon.  */
-  hostname[tmp] = '\000'; /* Tie off host name.  */
-  port = atoi (port_str + 1);
+  /* Default service name is gdbremote.  */
+  if (port_str == NULL || port_str[0] == '\0')
+    port_str = "gdbremote";

   /* Default hostname is localhost.  */
-  if (!hostname[0])
-    strcpy (hostname, "localhost");
-
-  hostent = gethostbyname (hostname);
-  if (!hostent)
+  if (host_str[0] == '\0')
+    host_str = "localhost";
+
+  memset(&hint, 0, sizeof hint);
+  hint.ai_family = AF_UNSPEC;
+  hint.ai_socktype = use_udp ? SOCK_DGRAM : SOCK_STREAM;
+  hint.ai_flags = 0;
+  hint.ai_protocol = use_udp ? IPPROTO_UDP : IPPROTO_TCP;
+  hint.ai_canonname = NULL;
+  hint.ai_addr = NULL;
+  hint.ai_next = NULL;
+  ai = NULL;
+
+  if ((err = getaddrinfo (host_str, port_str, &hint, &ai)) != 0)
     {
-      fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
+      fprintf_unfiltered (gdb_stderr, "%s: %s\n", name, gai_strerror(err));
       errno = ENOENT;
       return -1;
     }

-  sockaddr.sin_family = PF_INET;
-  sockaddr.sin_port = htons (port);
-  memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
-  sizeof (struct in_addr));
-
  retry:

-  if (use_udp)
-    scb->fd = gdb_socket_cloexec (PF_INET, SOCK_DGRAM, 0);
-  else
-    scb->fd = gdb_socket_cloexec (PF_INET, SOCK_STREAM, 0);
+  scb->fd = gdb_socket_cloexec (ai->ai_family, ai->ai_socktype,
ai->ai_protocol);

   if (scb->fd == -1)
-    return -1;
+    goto bailout;

   /* Set socket nonblocking.  */
