[patch] IPv6 support for gdbserver
Jan Kratochvil
jan.kratochvil@redhat.com
Wed Sep 27 16:33:00 GMT 2006
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
-------------- next part --------------
2006-09-27 Jan Kratochvil <jan.kratochvil@redhat.com>
* ser-tcp.c (net_open): Support IPv6, "tcp6:"&co. notation.
2006-09-27 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdbreplay.c (remote_open): Support IPv6, "tcp6:"&co. notation.
* remote-utils.c (remote_open): Likewise.
2006-09-27 Jan Kratochvil <jan.kratochvil@redhat.com>
* 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:
More information about the Gdb-patches
mailing list