This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] Add IPv6 support for remote TCP connections
- From: Paul Fertser <fercerpav at gmail dot com>
- To: gdb-patches at sourceware dot org
- Cc: Paul Fertser <fercerpav at gmail dot com>
- Date: Sat, 8 Feb 2014 20:53:55 +0400
- Subject: [PATCH] Add IPv6 support for remote TCP connections
- Authentication-results: sourceware.org; auth=none
This patch implements target host lookup the modern way,
see ``man 3 getaddrinfo'' for details; as a result, both IPv4 and IPv6
are transparently supported.
gdb:
2014-02-08 Paul Fertser <fercerpav@gmail.com>
* ser-tcp.c (net-open): Use last semicolon as port separator.
* ser-tcp.c (net-open): Use getaddrinfo for host lookup.
---
gdb/ser-tcp.c | 190 ++++++++++++++++++++++++++++++----------------------------
1 file changed, 100 insertions(+), 90 deletions(-)
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
index c288ab4..f29c3bf 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -157,9 +157,10 @@ int
net_open (struct serial *scb, const char *name)
{
char *port_str, hostname[100];
- int n, port, tmp;
+ int n, tmp;
int use_udp;
- struct hostent *hostent;
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
struct sockaddr_in sockaddr;
#ifdef USE_WIN32API
u_long ioarg;
@@ -177,7 +178,7 @@ net_open (struct serial *scb, const char *name)
else if (strncmp (name, "tcp:", 4) == 0)
name = name + 4;
- port_str = strchr (name, ':');
+ port_str = strrchr (name, ':');
if (!port_str)
error (_("net_open: No colon in host name!")); /* Shouldn't ever
@@ -186,124 +187,133 @@ net_open (struct serial *scb, const char *name)
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);
+ port_str++;
/* Default hostname is localhost. */
if (!hostname[0])
strcpy (hostname, "localhost");
- hostent = gethostbyname (hostname);
- if (!hostent)
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ if (use_udp)
+ hints.ai_socktype = SOCK_DGRAM;
+ else
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = 0;
+
+ tmp = getaddrinfo (hostname, port_str, &hints, &result);
+ if (tmp)
{
fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
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);
+ for (rp = result; ; rp = rp->ai_next ? rp->ai_next : result)
+ {
+ scb->fd = gdb_socket_cloexec (rp->ai_family, rp->ai_socktype,
+ rp->ai_protocol);
- if (scb->fd == -1)
- return -1;
+ if (scb->fd == -1)
+ continue;
- /* Set socket nonblocking. */
- ioarg = 1;
- ioctl (scb->fd, FIONBIO, &ioarg);
+ /* Set socket nonblocking. */
+ ioarg = 1;
+ ioctl (scb->fd, FIONBIO, &ioarg);
- /* Use Non-blocking connect. connect() will return 0 if connected
- already. */
- n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
+ /* Use Non-blocking connect. connect() will return 0 if connected
+ already. */
+ n = connect (scb->fd, rp->ai_addr, rp->ai_addrlen);
- if (n < 0)
- {
+ if (n < 0)
+ {
#ifdef USE_WIN32API
- int err = WSAGetLastError();
+ int err = WSAGetLastError();
#else
- int err = errno;
+ int err = errno;
#endif
- /* Maybe we're waiting for the remote target to become ready to
- accept connections. */
- if (tcp_auto_retry
+ /* Maybe we're waiting for the remote target to become ready to
+ accept connections. */
+ if (tcp_auto_retry
#ifdef USE_WIN32API
- && err == WSAECONNREFUSED
+ && err == WSAECONNREFUSED
#else
- && err == ECONNREFUSED
+ && err == ECONNREFUSED
#endif
- && wait_for_connect (NULL, &polls) >= 0)
- {
- close (scb->fd);
- goto retry;
- }
+ && wait_for_connect (NULL, &polls) >= 0)
+ {
+ close (scb->fd);
+ continue;
+ }
- if (
+ if (
#ifdef USE_WIN32API
- /* Under Windows, calling "connect" with a non-blocking socket
- results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */
- err != WSAEWOULDBLOCK
+ /* Under Windows, calling "connect" with a non-blocking socket
+ results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */
+ err != WSAEWOULDBLOCK
#else
- err != EINPROGRESS
+ err != EINPROGRESS
#endif
- )
- {
- errno = err;
- net_close (scb);
- return -1;
- }
-
- /* Looks like we need to wait for the connect. */
- do
- {
- n = wait_for_connect (scb, &polls);
- }
- while (n == 0);
- if (n < 0)
- {
- net_close (scb);
- return -1;
- }
- }
-
- /* Got something. Is it an error? */
- {
- int res, err;
- socklen_t len;
-
- len = sizeof (err);
- /* On Windows, the fourth parameter to getsockopt is a "char *";
- on UNIX systems it is generally "void *". The cast to "void *"
- is OK everywhere, since in C "void *" can be implicitly
- converted to any pointer type. */
- res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
- if (res < 0 || err)
+ )
+ {
+ errno = err;
+ net_close (scb);
+ freeaddrinfo (result);
+ return -1;
+ }
+
+ /* Looks like we need to wait for the connect. */
+ do
+ {
+ n = wait_for_connect (scb, &polls);
+ }
+ while (n == 0);
+ if (n < 0)
+ {
+ net_close (scb);
+ freeaddrinfo (result);
+ return -1;
+ }
+ }
+
+ /* Got something. Is it an error? */
{
- /* Maybe the target still isn't ready to accept the connection. */
- if (tcp_auto_retry
+ int res, err;
+ socklen_t len;
+
+ len = sizeof (err);
+ /* On Windows, the fourth parameter to getsockopt is a "char *";
+ on UNIX systems it is generally "void *". The cast to "void *"
+ is OK everywhere, since in C "void *" can be implicitly
+ converted to any pointer type. */
+ res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
+ if (res < 0 || err)
+ {
+ /* Maybe the target still isn't ready to accept the connection. */
+ if (tcp_auto_retry
#ifdef USE_WIN32API
- && err == WSAECONNREFUSED
+ && err == WSAECONNREFUSED
#else
- && err == ECONNREFUSED
+ && err == ECONNREFUSED
#endif
- && wait_for_connect (NULL, &polls) >= 0)
- {
- close (scb->fd);
- goto retry;
- }
- if (err)
- errno = err;
- net_close (scb);
- return -1;
+ && wait_for_connect (NULL, &polls) >= 0)
+ {
+ close (scb->fd);
+ continue;
+ }
+ if (err)
+ errno = err;
+ net_close (scb);
+ freeaddrinfo (result);
+ return -1;
+ }
+ break;
}
- }
+ }
+
+ freeaddrinfo (result);
/* Turn off nonblocking. */
ioarg = 0;
--
1.8.3.2