From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25928 invoked by alias); 8 Feb 2014 16:54:12 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 25918 invoked by uid 89); 8 Feb 2014 16:54:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-lb0-f173.google.com Received: from mail-lb0-f173.google.com (HELO mail-lb0-f173.google.com) (209.85.217.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 08 Feb 2014 16:54:11 +0000 Received: by mail-lb0-f173.google.com with SMTP id s7so2117245lbd.32 for ; Sat, 08 Feb 2014 08:54:07 -0800 (PST) X-Received: by 10.112.211.233 with SMTP id nf9mr1621173lbc.50.1391878447189; Sat, 08 Feb 2014 08:54:07 -0800 (PST) Received: from localhost ([2001:470:1f15:397:656e:bd4e:cdf3:153d]) by mx.google.com with ESMTPSA id dm8sm12740356lad.7.2014.02.08.08.54.05 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 08 Feb 2014 08:54:06 -0800 (PST) From: Paul Fertser To: gdb-patches@sourceware.org Cc: Paul Fertser Subject: [PATCH] Add IPv6 support for remote TCP connections Date: Sat, 08 Feb 2014 16:54:00 -0000 Message-Id: <1391878435-19340-1-git-send-email-fercerpav@gmail.com> X-SW-Source: 2014-02/txt/msg00248.txt.bz2 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 * 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