From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14281 invoked by alias); 27 Sep 2006 16:33:49 -0000 Received: (qmail 14188 invoked by uid 22791); 27 Sep 2006 16:33:46 -0000 X-Spam-Check-By: sourceware.org Received: from 195.22.55.53.adsl.nextra.cz (HELO host0.dyn.jankratochvil.net) (195.22.55.53) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 27 Sep 2006 16:33:40 +0000 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.13.8/8.13.8) with ESMTP id k8RGXb1j027163 for ; Wed, 27 Sep 2006 18:33:37 +0200 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.13.8/8.13.8/Submit) id k8RGXb8l027162 for gdb-patches@sourceware.org; Wed, 27 Sep 2006 18:33:37 +0200 Date: Wed, 27 Sep 2006 16:33:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [patch] IPv6 support for gdbserver Message-ID: <20060927163337.GA27149@host0.dyn.jankratochvil.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="ibTvN161/egqYuK8" Content-Disposition: inline User-Agent: Mutt/1.4.2.2i X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-09/txt/msg00192.txt.bz2 --ibTvN161/egqYuK8 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 178 Hi, while it may not make too much sense here is IPv6 support ("tcp6:"/"udp6:" address prefixes, autodetected if possible) for target-remote/gdbserver/gdbreplay. Regards, Jan --ibTvN161/egqYuK8 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="gdb-6.5-IPv6.patch" Content-length: 27559 2006-09-27 Jan Kratochvil * ser-tcp.c (net_open): Support IPv6, "tcp6:"&co. notation. 2006-09-27 Jan Kratochvil * gdbreplay.c (remote_open): Support IPv6, "tcp6:"&co. notation. * remote-utils.c (remote_open): Likewise. 2006-09-27 Jan Kratochvil * gdb.texinfo (Connecting to a remote target): Support IPv6, "tcp6:"&co. notation. (Using the gdbserver program): Likewise. Index: gdb/ser-tcp.c =================================================================== RCS file: /cvs/src/src/gdb/ser-tcp.c,v retrieving revision 1.26 diff -u -p -r1.26 ser-tcp.c --- gdb/ser-tcp.c 10 Feb 2006 22:01:43 -0000 1.26 +++ gdb/ser-tcp.c 27 Sep 2006 13:11:01 -0000 @@ -68,67 +68,129 @@ void _initialize_ser_tcp (void); int net_open (struct serial *scb, const char *name) { - char *port_str, hostname[100]; - int n, port, tmp; - int use_udp; - struct hostent *hostent; - struct sockaddr_in sockaddr; + char *name_base; + char *port_str; + int n, tmp; #ifdef USE_WIN32API u_long ioarg; #else int ioarg; #endif - - use_udp = 0; - if (strncmp (name, "udp:", 4) == 0) + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = + { + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, + }; + const struct prefix *prefix; + struct addrinfo hints, *hints_p = NULL; + struct addrinfo *addrinfo_base, *addrinfo = NULL; + struct address + { + const char *string; + int family; + }; + const struct address addresses[] = + { + { "::1", AF_INET6 }, + { "127.0.0.1", AF_INET }, + { "localhost", AF_UNSPEC }, + }; + const struct address *address; + int fake_localhost = 0; + + name_base = xstrdup (name); + name = name_base; + for (prefix = prefixes; prefix < prefixes + ARRAY_SIZE (prefixes); prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); + memset (&hints, 0, sizeof (hints)); + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; + hints_p = &hints; + break; + } + if (!(hints_p != NULL && hints_p->ai_family == AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) { - use_udp = 1; - name = name + 4; + name++; + *port_str++ = 0; } - else if (strncmp (name, "tcp:", 4) == 0) - name = name + 4; - - port_str = strchr (name, ':'); - - if (!port_str) - error (_("net_open: No colon in host name!")); /* Shouldn't ever happen */ - - 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); + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + error (_("net_open: No colon in host name!")); + *port_str++ = 0; /* default hostname is localhost */ - if (!hostname[0]) - strcpy (hostname, "localhost"); + if (name[0] == 0) + fake_localhost = 1; - hostent = gethostbyname (hostname); - if (!hostent) + for (address = addresses; + address < addresses + sizeof (addresses) / sizeof (*addresses); + address++) { - fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname); - errno = ENOENT; - return -1; - } + int fatal; - if (use_udp) - scb->fd = socket (PF_INET, SOCK_DGRAM, 0); - else - scb->fd = socket (PF_INET, SOCK_STREAM, 0); + if (fake_localhost) + { + if (address->family != AF_UNSPEC + && hints_p != NULL && hints_p->ai_family != address->family) + continue; + name = (char *) address->string; + fatal = (address + 1 + >= addresses + sizeof (addresses) / sizeof (*addresses)); + } + else + fatal = 1; - if (scb->fd < 0) - 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)); + n = getaddrinfo (name, port_str, hints_p, &addrinfo_base); + if (n != 0) + { + if (!fatal) + continue; + fprintf_unfiltered (gdb_stderr, "%s:%s: cannot resolve name: %s\n", + name, port_str, gai_strerror (n)); + errno = ENOENT; + free (name_base); + return -1; + } + free (name_base); + + for (addrinfo = addrinfo_base; addrinfo != NULL; addrinfo = addrinfo->ai_next) + { + scb->fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (scb->fd >= 0) + break; + } + if (addrinfo == NULL) + { + if (!fatal) + continue; + freeaddrinfo (addrinfo_base); + return -1; + } + break; + } /* 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)); + n = connect (scb->fd, addrinfo->ai_addr, addrinfo->ai_addrlen); if (n < 0 #ifdef USE_WIN32API @@ -144,6 +206,7 @@ net_open (struct serial *scb, const char errno = WSAGetLastError(); #endif net_close (scb); + freeaddrinfo (addrinfo_base); return -1; } @@ -166,6 +229,7 @@ net_open (struct serial *scb, const char { errno = EINTR; net_close (scb); + freeaddrinfo (addrinfo_base); return -1; } } @@ -193,6 +257,7 @@ net_open (struct serial *scb, const char if (polls > TIMEOUT * POLL_INTERVAL) errno = ETIMEDOUT; net_close (scb); + freeaddrinfo (addrinfo_base); return -1; } } @@ -212,6 +277,7 @@ net_open (struct serial *scb, const char if (err) errno = err; net_close (scb); + freeaddrinfo (addrinfo_base); return -1; } } @@ -220,7 +286,7 @@ net_open (struct serial *scb, const char ioarg = 0; ioctl (scb->fd, FIONBIO, &ioarg); - if (use_udp == 0) + if (addrinfo->ai_protocol == SOCK_STREAM) { /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; @@ -234,6 +300,7 @@ net_open (struct serial *scb, const char signal (SIGPIPE, SIG_IGN); #endif + freeaddrinfo (addrinfo_base); return 0; } Index: gdb/gdbserver/gdbreplay.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/gdbreplay.c,v retrieving revision 1.12 diff -u -p -r1.12 gdbreplay.c --- gdb/gdbserver/gdbreplay.c 23 Jul 2006 03:52:15 -0000 1.12 +++ gdb/gdbserver/gdbreplay.c 27 Sep 2006 13:11:10 -0000 @@ -115,6 +115,8 @@ remote_close (void) static void remote_open (char *name) { + char *name_orig = name; + if (!strchr (name, ':')) { fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); @@ -127,14 +129,145 @@ remote_open (char *name) static int winsock_initialized; #endif char *port_str; - int port; - struct sockaddr_in sockaddr; socklen_t tmp; - int tmp_desc; + int tmp_desc = -1; + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = + { + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, + }; + const struct prefix *prefix; + struct addrinfo hints, *hints_p = NULL; + struct addrinfo *addrinfo_base, *addrinfo = NULL; + char back_host[64], back_port[16]; + int fake_any = 0, err; + char *name_base; + struct address + { + const char *string; + int family; + }; + const struct address addresses[] = + { + { "::", AF_INET6 }, + { "127.0.0.1", AF_INET }, + { "localhost", AF_UNSPEC }, + }; + const struct address *address; + + name_base = strdup (name); + name = name_base; + for (prefix = prefixes; + prefix < prefixes + sizeof (prefixes) / sizeof (*prefixes); + prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); + memset (&hints, 0, sizeof (hints)); + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; + hints_p = &hints; + break; + } + if (!(hints_p != NULL && hints_p->ai_family == AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + { + fprintf (stderr, "net_open: No colon in host name!\n"); + fflush (stderr); + exit (1); + } + *port_str++ = 0; - port_str = strchr (name, ':'); + /* We need to provide some fake name for resolving. + but I am not aware of any universal host string for both + `INADDR_ANY' and `in6addr_any'. + So we try those from `addresses' in the specified order. */ + if (name[0] == 0) + fake_any = 1; + + for (address = addresses; + address < addresses + sizeof (addresses) / sizeof (*addresses); + address++) + { + int fatal; + + if (fake_any) + { + if (address->family != AF_UNSPEC + && hints_p != NULL && hints_p->ai_family != address->family) + continue; + name = (char *) address->string; + fatal = (address + 1 + >= addresses + sizeof (addresses) / sizeof (*addresses)); + } + else + fatal = 1; + + err = getaddrinfo (name, port_str, hints_p, &addrinfo_base); + if (err != 0) + { + if (!fatal) + continue; + /* `name_base' is used here for `port_str'. */ + fprintf (stderr, "%s:%s: cannot resolve name: %s\n", + name, port_str, gai_strerror (err)); + fflush (stderr); + exit (1); + } + free (name_base); + + for (addrinfo = addrinfo_base; + addrinfo != NULL; + addrinfo = addrinfo->ai_next) + { + tmp_desc = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (tmp_desc >= 0) + break; + } + if (addrinfo == NULL) + { + if (!fatal) + continue; + freeaddrinfo (addrinfo_base); + perror_with_name ("Can't open socket"); + } + break; + } - port = atoi (port_str + 1); + if (fake_any) + switch (addrinfo->ai_family) + { + case AF_INET: + ((struct sockaddr_in *)addrinfo->ai_addr)->sin_addr.s_addr + = INADDR_ANY; + break; + case AF_INET6: + memcpy (&((struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_addr, + &in6addr_any, sizeof (in6addr_any)); + break; + default: + fprintf (stderr, "Error setting 'any' listening for ai_family %d", + addrinfo->ai_family); + } #ifdef USE_WIN32API if (!winsock_initialized) @@ -146,55 +279,83 @@ remote_open (char *name) } #endif - tmp_desc = socket (PF_INET, SOCK_STREAM, 0); - if (tmp_desc < 0) - perror_with_name ("Can't open socket"); - /* Allow rapid reuse of this port. */ tmp = 1; setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp)); - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - sockaddr.sin_addr.s_addr = INADDR_ANY; - - if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) - perror_with_name ("Can't bind address"); - - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); - - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); - - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); + if (bind (tmp_desc, addrinfo->ai_addr, addrinfo->ai_addrlen) + || (addrinfo->ai_socktype != SOCK_DGRAM && listen (tmp_desc, 1))) + { + freeaddrinfo (addrinfo_base); + perror_with_name ("Can't bind address"); + } + + if (0 != getnameinfo (addrinfo->ai_addr, addrinfo->ai_addrlen, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Error detecting listening address, trying anyway\n"); + else + fprintf (stderr, "Listening on port %s (on host %s)\n", + back_port, back_host); + fflush (stderr); - close (tmp_desc); /* No longer need this */ + if (addrinfo->ai_socktype == SOCK_DGRAM) + remote_desc = tmp_desc; + else + { + struct sockaddr_in6 sockaddr6; + socklen_t sockaddr6_len; + sockaddr6_len = sizeof (sockaddr6); + remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr6, &sockaddr6_len); + if (remote_desc == -1) + { + freeaddrinfo (addrinfo_base); + perror_with_name ("Accept failed"); + } + + /* Enable TCP keep alive process. */ + tmp = 1; + setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + if (addrinfo->ai_socktype == SOCK_STREAM) + { + tmp = 1; + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (tmp)); + } + freeaddrinfo (addrinfo_base); #ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ + close (tmp_desc); /* No longer need this */ - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply - exits when the remote side dies. */ + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply + exits when the remote side dies. */ #else - closesocket (tmp_desc); /* No longer need this */ + closesocket (tmp_desc); /* No longer need this */ #endif + + /* Convert IP address to string. */ + if (0 != getnameinfo ((struct sockaddr *) &sockaddr6, sockaddr6_len, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Error detecting originating address, trying anyway\n"); + else + fprintf (stderr, "Remote debugging from host %s port %s\n", + back_host, back_port); + } + fflush (stderr); } #if defined(F_SETFL) && defined (FASYNC) fcntl (remote_desc, F_SETFL, FASYNC); #endif - fprintf (stderr, "Replay logfile using %s\n", name); + fprintf (stderr, "Replay logfile using %s\n", name_orig); fflush (stderr); } Index: gdb/gdbserver/remote-utils.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/remote-utils.c,v retrieving revision 1.32 diff -u -p -r1.32 remote-utils.c --- gdb/gdbserver/remote-utils.c 21 Sep 2006 16:09:54 -0000 1.32 +++ gdb/gdbserver/remote-utils.c 27 Sep 2006 13:11:10 -0000 @@ -157,14 +157,139 @@ remote_open (char *name) static int winsock_initialized; #endif char *port_str; - int port; - struct sockaddr_in sockaddr; socklen_t tmp; - int tmp_desc; + int tmp_desc = -1; + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = + { + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, + }; + const struct prefix *prefix; + struct addrinfo hints, *hints_p = NULL; + struct addrinfo *addrinfo_base, *addrinfo = NULL; + char back_host[64], back_port[16]; + int fake_any = 0, err; + char *name_base; + struct address + { + const char *string; + int family; + }; + const struct address addresses[] = + { + { "::", AF_INET6 }, + { "127.0.0.1", AF_INET }, + { "localhost", AF_UNSPEC }, + }; + const struct address *address; + + name_base = strdup (name); + name = name_base; + for (prefix = prefixes; + prefix < prefixes + sizeof (prefixes) / sizeof (*prefixes); + prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); + memset (&hints, 0, sizeof (hints)); + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; + hints_p = &hints; + break; + } + if (!(hints_p != NULL && hints_p->ai_family == AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + error ("net_open: No colon in host name!"); + *port_str++ = 0; + + /* We need to provide some fake name for resolving. + but I am not aware of any universal host string for both + `INADDR_ANY' and `in6addr_any'. + So we try those from `addresses' in the specified order. */ + if (name[0] == 0) + fake_any = 1; + + for (address = addresses; + address < addresses + sizeof (addresses) / sizeof (*addresses); + address++) + { + int fatal; + + if (fake_any) + { + if (address->family != AF_UNSPEC + && hints_p != NULL && hints_p->ai_family != address->family) + continue; + name = (char *) address->string; + fatal = (address + 1 + >= addresses + sizeof (addresses) / sizeof (*addresses)); + } + else + fatal = 1; + + err = getaddrinfo (name, port_str, hints_p, &addrinfo_base); + if (err != 0) + { + if (!fatal) + continue; + /* `name_base' is used here for `port_str'. */ + error ("%s:%s: cannot resolve name: %s\n", + name, port_str, gai_strerror (err)); + } + free (name_base); - port_str = strchr (name, ':'); + for (addrinfo = addrinfo_base; + addrinfo != NULL; + addrinfo = addrinfo->ai_next) + { + tmp_desc = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (tmp_desc >= 0) + break; + } + if (addrinfo == NULL) + { + if (!fatal) + continue; + freeaddrinfo (addrinfo_base); + perror_with_name ("Can't open socket"); + } + break; + } - port = atoi (port_str + 1); + if (fake_any) + switch (addrinfo->ai_family) + { + case AF_INET: + ((struct sockaddr_in *)addrinfo->ai_addr)->sin_addr.s_addr + = INADDR_ANY; + break; + case AF_INET6: + memcpy (&((struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_addr, + &in6addr_any, sizeof (in6addr_any)); + break; + default: + fprintf (stderr, "Error setting 'any' listening for ai_family %d", + addrinfo->ai_family); + } #ifdef USE_WIN32API if (!winsock_initialized) @@ -176,54 +301,76 @@ remote_open (char *name) } #endif - tmp_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (tmp_desc < 0) - perror_with_name ("Can't open socket"); - /* Allow rapid reuse of this port. */ tmp = 1; setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp)); - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - sockaddr.sin_addr.s_addr = INADDR_ANY; - - if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) - perror_with_name ("Can't bind address"); + if (bind (tmp_desc, addrinfo->ai_addr, addrinfo->ai_addrlen) + || (addrinfo->ai_socktype != SOCK_DGRAM && listen (tmp_desc, 1))) + { + freeaddrinfo (addrinfo_base); + perror_with_name ("Can't bind address"); + } - fprintf (stderr, "Listening on port %d\n", port); + if (0 != getnameinfo (addrinfo->ai_addr, addrinfo->ai_addrlen, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Error detecting listening address, trying anyway\n"); + else + fprintf (stderr, "Listening on port %s (on host %s)\n", + back_port, back_host); fflush (stderr); - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); - - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); - - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); + if (addrinfo->ai_socktype == SOCK_DGRAM) + remote_desc = tmp_desc; + else + { + struct sockaddr_in6 sockaddr6; + socklen_t sockaddr6_len; + sockaddr6_len = sizeof (sockaddr6); + remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr6, &sockaddr6_len); + if (remote_desc == -1) + { + freeaddrinfo (addrinfo_base); + perror_with_name ("Accept failed"); + } + /* Enable TCP keep alive process. */ + tmp = 1; + setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + if (addrinfo->ai_socktype == SOCK_STREAM) + { + tmp = 1; + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (tmp)); + } + freeaddrinfo (addrinfo_base); #ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ + close (tmp_desc); /* No longer need this */ - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply - exits when the remote side dies. */ + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply + exits when the remote side dies. */ #else - closesocket (tmp_desc); /* No longer need this */ + closesocket (tmp_desc); /* No longer need this */ #endif - /* Convert IP address to string. */ - fprintf (stderr, "Remote debugging from host %s\n", - inet_ntoa (sockaddr.sin_addr)); + /* Convert IP address to string. */ + if (0 != getnameinfo ((struct sockaddr *) &sockaddr6, sockaddr6_len, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Error detecting originating address, trying anyway\n"); + else + fprintf (stderr, "Remote debugging from host %s port %s\n", + back_host, back_port); + } + fflush (stderr); } #if defined(F_SETFL) && defined (FASYNC) Index: gdb/doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.355 diff -u -p -r1.355 gdb.texinfo --- gdb/doc/gdb.texinfo 21 Sep 2006 14:01:12 -0000 1.355 +++ gdb/doc/gdb.texinfo 27 Sep 2006 13:11:10 -0000 @@ -12404,8 +12404,10 @@ If you're using a serial line, you may w (@pxref{Remote configuration, set remotebaud}) before the @code{target} command. -@item target remote @code{@var{host}:@var{port}} +@item target remote @code{@var{host}:@var{port}} @itemx target remote @code{tcp:@var{host}:@var{port}} +@itemx target remote @code{tcp4:@var{host}:@var{port}} +@itemx target remote @code{tcp6:@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} @@ -12414,6 +12416,9 @@ the target machine itself, if it is dire it might be a terminal server which in turn has a serial line to the target. +@code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} forces +IPv4, both on the reliable stream TCP connection. + For example, to connect to port 2828 on a terminal server named @code{manyfarms}: @@ -12434,10 +12439,15 @@ target remote :1234 Note that the colon is still required here. @item target remote @code{udp:@var{host}:@var{port}} +@itemx target remote @code{udp6:@var{host}:@var{port}} +@itemx target remote @code{udp4:@var{host}:@var{port}} @cindex @acronym{UDP} port, @code{target remote} Debug using @acronym{UDP} packets to @var{port} on @var{host}. For example, to connect to @acronym{UDP} port 2828 on a terminal server named @code{manyfarms}: +@code{udp6:} prefix forces IPv6 network connection while @code{udp4:} forces +IPv4, both on the unreliable datagram UDP connection. + @smallexample target remote udp:manyfarms:2828 @end smallexample @@ -12578,14 +12588,30 @@ The only difference from the previous ex specifying that you are communicating with the host @value{GDBN} via TCP. The @samp{host:2345} argument means that @code{gdbserver} is to expect a TCP connection from machine @samp{host} to local TCP port 2345. -(Currently, the @samp{host} part is ignored.) You can choose any number -you want for the port number as long as it does not conflict with any -TCP ports already in use on the target system (for example, @code{23} is -reserved for @code{telnet}).@footnote{If you choose a port number that -conflicts with another service, @code{gdbserver} prints an error message +(The @samp{host} part is usually omitted as it defaults to listen from any +host. You may use a local address as expected by the @code{bind} syscall.) +You can choose any number you want for the port number as long as it does not +conflict with any TCP ports already in use on the target system (for example, +@code{23} is reserved for @code{telnet}).@footnote{If you choose a port number +that conflicts with another service, @code{gdbserver} prints an error message and exits.} You must use the same port number with the host @value{GDBN} @code{target remote} command. +@item gdbserver @code{tcp:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{tcp6:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{tcp4:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{udp:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{udp6:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{udp4:@var{host}:@var{port}} emacs foo.txt + +The @code{::} part can be also replaced by the optional @var{host} part as +in the sample case of @code{tcp:@var{host}:@var{port}}. +These all alternative syntaxes force either the reliable stream TCP protocol or +the unreliable datagram UDP protocol appropriately. You may also force the use +of IPv6 or IPv4 network connections; @code{tcp:} and @code{udp:} select the +network version type according to the provided @var{host}. +The connection type defaults to the @code{tcp:} prefix behavior. + On some targets, @code{gdbserver} can also attach to running programs. This is accomplished via the @code{--attach} argument. The syntax is: --ibTvN161/egqYuK8--