aboutsummaryrefslogtreecommitdiff
path: root/gdb/common
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/common')
-rw-r--r--gdb/common/netstuff.c155
-rw-r--r--gdb/common/netstuff.h76
2 files changed, 231 insertions, 0 deletions
diff --git a/gdb/common/netstuff.c b/gdb/common/netstuff.c
new file mode 100644
index 0000000..c1c401c
--- /dev/null
+++ b/gdb/common/netstuff.c
@@ -0,0 +1,155 @@
+/* Operations on network stuff.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "common-defs.h"
+#include "netstuff.h"
+#include <algorithm>
+
+#ifdef USE_WIN32API
+#include <winsock2.h>
+#include <wspiapi.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#endif
+
+/* See common/netstuff.h. */
+
+scoped_free_addrinfo::~scoped_free_addrinfo ()
+{
+ freeaddrinfo (m_res);
+}
+
+/* See common/netstuff.h. */
+
+parsed_connection_spec
+parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
+{
+ parsed_connection_spec ret;
+ size_t last_colon_pos = 0;
+ /* We're dealing with IPv6 if:
+
+ - ai_family is AF_INET6, or
+ - ai_family is not AF_INET, and
+ - spec[0] is '[', or
+ - the number of ':' on spec is greater than 1. */
+ bool is_ipv6 = (hint->ai_family == AF_INET6
+ || (hint->ai_family != AF_INET
+ && (spec[0] == '['
+ || std::count (spec.begin (),
+ spec.end (), ':') > 1)));
+
+ if (is_ipv6)
+ {
+ if (spec[0] == '[')
+ {
+ /* IPv6 addresses can be written as '[ADDR]:PORT', and we
+ support this notation. */
+ size_t close_bracket_pos = spec.find_first_of (']');
+
+ if (close_bracket_pos == std::string::npos)
+ error (_("Missing close bracket in hostname '%s'"),
+ spec.c_str ());
+
+ hint->ai_family = AF_INET6;
+
+ const char c = spec[close_bracket_pos + 1];
+
+ if (c == '\0')
+ last_colon_pos = std::string::npos;
+ else if (c != ':')
+ error (_("Invalid cruft after close bracket in '%s'"),
+ spec.c_str ());
+
+ /* Erase both '[' and ']'. */
+ spec.erase (0, 1);
+ spec.erase (close_bracket_pos - 1, 1);
+ }
+ else if (spec.find_first_of (']') != std::string::npos)
+ error (_("Missing open bracket in hostname '%s'"),
+ spec.c_str ());
+ }
+
+ if (last_colon_pos == 0)
+ last_colon_pos = spec.find_last_of (':');
+
+ /* The length of the hostname part. */
+ size_t host_len;
+
+ if (last_colon_pos != std::string::npos)
+ {
+ /* The user has provided a port. */
+ host_len = last_colon_pos;
+ ret.port_str = spec.substr (last_colon_pos + 1);
+ }
+ else
+ host_len = spec.size ();
+
+ ret.host_str = spec.substr (0, host_len);
+
+ /* Default hostname is localhost. */
+ if (ret.host_str.empty ())
+ ret.host_str = "localhost";
+
+ return ret;
+}
+
+/* See common/netstuff.h. */
+
+parsed_connection_spec
+parse_connection_spec (const char *spec, struct addrinfo *hint)
+{
+ /* Struct to hold the association between valid prefixes, their
+ family and socktype. */
+ struct host_prefix
+ {
+ /* The prefix. */
+ const char *prefix;
+
+ /* The 'ai_family'. */
+ int family;
+
+ /* The 'ai_socktype'. */
+ int socktype;
+ };
+ static const struct host_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 },
+ };
+
+ for (const host_prefix prefix : prefixes)
+ if (startswith (spec, prefix.prefix))
+ {
+ spec += strlen (prefix.prefix);
+ hint->ai_family = prefix.family;
+ hint->ai_socktype = prefix.socktype;
+ hint->ai_protocol
+ = hint->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
+ break;
+ }
+
+ return parse_connection_spec_without_prefix (spec, hint);
+}
diff --git a/gdb/common/netstuff.h b/gdb/common/netstuff.h
new file mode 100644
index 0000000..2b65807
--- /dev/null
+++ b/gdb/common/netstuff.h
@@ -0,0 +1,76 @@
+/* Operations on network stuff.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef NETSTUFF_H
+#define NETSTUFF_H
+
+#include <string>
+
+/* Like NI_MAXHOST/NI_MAXSERV, but enough for numeric forms. */
+#define GDB_NI_MAX_ADDR 64
+#define GDB_NI_MAX_PORT 16
+
+/* Helper class to guarantee that we always call 'freeaddrinfo'. */
+
+class scoped_free_addrinfo
+{
+public:
+ /* Default constructor. */
+ explicit scoped_free_addrinfo (struct addrinfo *ainfo)
+ : m_res (ainfo)
+ {
+ }
+
+ /* Destructor responsible for free'ing M_RES by calling
+ 'freeaddrinfo'. */
+ ~scoped_free_addrinfo ();
+
+ DISABLE_COPY_AND_ASSIGN (scoped_free_addrinfo);
+
+private:
+ /* The addrinfo resource. */
+ struct addrinfo *m_res;
+};
+
+/* The struct we return after parsing the connection spec. */
+
+struct parsed_connection_spec
+{
+ /* The hostname. */
+ std::string host_str;
+
+ /* The port, if any. */
+ std::string port_str;
+};
+
+
+/* Parse SPEC (which is a string in the form of "ADDR:PORT") and
+ return a 'parsed_connection_spec' structure with the proper fields
+ filled in. Also adjust HINT accordingly. */
+extern parsed_connection_spec
+ parse_connection_spec_without_prefix (std::string spec,
+ struct addrinfo *hint);
+
+/* Parse SPEC (which is a string in the form of
+ "[tcp[6]:|udp[6]:]ADDR:PORT") and return a 'parsed_connection_spec'
+ structure with the proper fields filled in. Also adjust HINT
+ accordingly. */
+extern parsed_connection_spec parse_connection_spec (const char *spec,
+ struct addrinfo *hint);
+
+#endif /* ! NETSTUFF_H */