This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] supports IPv6 only remote target
- From: Tsutomu Seki <sekiriki at gmail dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 9 Feb 2016 22:49:57 +0900
- Subject: [PATCH] supports IPv6 only remote target
- Authentication-results: sourceware.org; auth=none
Hi,
While I'm trying to connect remote target that has only IPv6
(Link-Local) address,
> $ getent hosts hogehoge.local
> fe80::XXXX:XXff:feXX:XXXX hogehoge.local
> $ arm-none-eabi-gdb
> (gdb) target remote hogehoge.local:2159
I found gdb is sending packets for invalid address,
> $ tcpdump -n "tcp port 2159"
> 14:06:39.611372 IP 10.XX.XX.10.51012 > 254.128.0.0.2159: Flags [S], seq 4014569856, win 29200, options [mss 1460,sackOK,TS val 429376439 ecr 0,nop,wscale 7], length 0
> 14:06:40.608993 IP 10.XX.XX.10.51012 > 254.128.0.0.2159: Flags [S], seq 4014569856, win 29200, options [mss 1460,sackOK,TS val 429376689 ecr 0,nop,wscale 7], length 0
> ...
and then, it fails to connect after few seconds.
In addition to that, it seems port number is invalidly parsed when only colon,
without decimal number was passed. I mean;
> (gdb) target remote tcp::
will result to try to connect tcp port 0 on localhost.
Forthcoming patch fixes these problem and add IPv6 support.
Tested to build for --target=arm-none-eabi, with --host=x86_64-linux-gnu
and i686-w64-mingw32, by applying the patch to a version 5-2015-q4-major
of https://launchpad.net/gcc-arm-embedded, and to run on Ubuntu 14.04.3
and Windows 7 Enterprise SP1, respectively.
Thanks in advance and sorry for my poor English.
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 | 27 +++++++++++++---
gdb/ser-tcp.c | 91 ++++++++++++++++++++++++++++++++++-------------------
2 files changed, 82 insertions(+), 36 deletions(-)
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. */
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