This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] supports IPv6 only remote target


Hi Eli,
Thank you to review.

> Please use @code with the address string fe80::1.

Changed address to be "@code{fe80::1%eth1}", to include scope id
as written later.

> This example seems to imply that more than just taking brackets
> is required.

Your are right. This implies address/port separation rule and
address/scope separation rule. The former should be documented,
because address/port separation is done by the application before
passing them to getaddrinfo.

> Should we tell more about that?

On the other hand, the latter is difficult to document (for me) in
generic manner, because %-style scope-id notation depends on
implementation of getaddrinfo.

As far as I googled;

- Ubuntu: noted;
  http://manpages.ubuntu.com/manpages/precise/en/man3/getaddrinfo.3.html
> getaddrinfo() supports the address%scope-id notation for specifying the
> IPv6 scope-ID.

- FreeBSD: documented;
  https://www.freebsd.org/cgi/man.cgi?query=getaddrinfo&sektion=3
> This implementation of getaddrinfo() allows numeric IPv6 address
> notation with scope identifier, as documented in chapter 11 of
> RFC 4007.

- Windows: it seems to be supported, but not documented;
  https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
  https://msdn.microsoft.com/en-us/library/windows/desktop/aa385325(v=vs.85).aspx

To avoid this ambiguity whether OS supports this manner of separation,
I want to suggest to use whole "fe80::1%eth1" including scope id as
an example of "numeric IPv6 address".

> The service name defaults to @code{"gdbremote"}

I think quotation is not needed if @code is used. Please review
another example I added to show how to use service name explicitly.

> I guess you mean "on the port assigned to that service", yes?

Yes.

> I think this will break the build with mingw.org's MinGW.  It doesn't
> have wspiapi.h, AFAIK.  What exactly is needed from that header?

It is needed to support getaddrinfo() on Windows 2000 and older versions.

What can I do for it?  The easiest solution is to replace with <ws2tcpip.h>,
but Windows 2000 support (as a host) would be dropped.

Regards,
Seki, Tsutomu

---
gdb/ChangeLog:

        * ser-tcp.c (net_open): Use getaddrinfo instead of gethostbyname
        (net_open): Add IPv6 numerical address support
        (net_open): Use "gdbremote" as default service name

gdb/doc/ChangeLog:

        * gdb.texinfo (Remote Connection Commands): Update to mention
        IPv6 numerical address and default service name.

---
 gdb/doc/gdb.texinfo | 37 +++++++++++++++++++---
 gdb/ser-tcp.c       | 91 ++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 92 insertions(+), 36 deletions(-)

---
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2d09d13..ebc0263 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19571,10 +19571,11 @@ If you're using a serial line, you may want
to give @value{GDBN} the
 @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 or a numeric @acronym{IPv6} address enclosed in square
+brackets; @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

+Numeric @acronym{IPv6} address must be enclosed in square brackets.
+For example, to connect to port 2159 of a target which has
+@acronym{IPv6} address @code{fe80::1%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,26 @@ port 1234 on your local machine:
 @smallexample
 target remote :1234
 @end smallexample
+
+If the service name is present in service list (e.g.@: @file{/etc/services}
+on @sc{gnu}/Linux systems) on your local machine, and target is
+listening on the port assigned to that service, you can use
+human-friendly name instead of the port number.  For example,
+to connect to service named @code{icepick} on a target machine
+named @code{stormstown}:
+
+@smallexample
+target remote stormstown:icepick
+@end smallexample
+
+The service name defaults to @code{gdbremote}.  If your target is
+listening on the port assigned to @code{gdbremote}, you can omit the
+service name.  For example, to connect to service @code{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..0123480 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -39,6 +39,7 @@

 #ifdef USE_WIN32API
 #include <winsock2.h>
+#include <ws2tcpip.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.  */
   ioarg = 1;
@@ -221,7 +243,7 @@ net_open (struct serial *scb, const char *name)

   /* Use Non-blocking connect.  connect() will return 0 if connected
      already.  */
-  n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
+  n = connect (scb->fd, ai->ai_addr, ai->ai_addrlen);

   if (n < 0)
     {
@@ -257,7 +279,7 @@ net_open (struct serial *scb, const char *name)
  {
   errno = err;
   net_close (scb);
-  return -1;
+  goto bailout;
  }

       /* Looks like we need to wait for the connect.  */
@@ -269,7 +291,7 @@ net_open (struct serial *scb, const char *name)
       if (n < 0)
  {
   net_close (scb);
-  return -1;
+  goto bailout;
  }
     }

@@ -301,7 +323,7 @@ net_open (struct serial *scb, const char *name)
  if (err)
   errno = err;
  net_close (scb);
- return -1;
+ goto bailout;
       }
   }

@@ -323,7 +345,12 @@ net_open (struct serial *scb, const char *name)
   signal (SIGPIPE, SIG_IGN);
 #endif

+  freeaddrinfo (ai);
   return 0;
+
+ bailout:
+  freeaddrinfo (ai);
+  return -1;
 }

 void


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]