netstuff.cc revision 1.1 1 1.1 christos /* Operations on network stuff.
2 1.1 christos Copyright (C) 2018-2020 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of GDB.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 1.1 christos
19 1.1 christos #include "common-defs.h"
20 1.1 christos #include "netstuff.h"
21 1.1 christos #include <algorithm>
22 1.1 christos
23 1.1 christos #ifdef USE_WIN32API
24 1.1 christos #include <ws2tcpip.h>
25 1.1 christos #else
26 1.1 christos #include <netinet/in.h>
27 1.1 christos #include <arpa/inet.h>
28 1.1 christos #include <netdb.h>
29 1.1 christos #include <sys/socket.h>
30 1.1 christos #include <netinet/tcp.h>
31 1.1 christos #endif
32 1.1 christos
33 1.1 christos /* See gdbsupport/netstuff.h. */
34 1.1 christos
35 1.1 christos scoped_free_addrinfo::~scoped_free_addrinfo ()
36 1.1 christos {
37 1.1 christos freeaddrinfo (m_res);
38 1.1 christos }
39 1.1 christos
40 1.1 christos /* See gdbsupport/netstuff.h. */
41 1.1 christos
42 1.1 christos parsed_connection_spec
43 1.1 christos parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
44 1.1 christos {
45 1.1 christos parsed_connection_spec ret;
46 1.1 christos size_t last_colon_pos = 0;
47 1.1 christos /* We're dealing with IPv6 if:
48 1.1 christos
49 1.1 christos - ai_family is AF_INET6, or
50 1.1 christos - ai_family is not AF_INET, and
51 1.1 christos - spec[0] is '[', or
52 1.1 christos - the number of ':' on spec is greater than 1. */
53 1.1 christos bool is_ipv6 = (hint->ai_family == AF_INET6
54 1.1 christos || (hint->ai_family != AF_INET
55 1.1 christos && (spec[0] == '['
56 1.1 christos || std::count (spec.begin (),
57 1.1 christos spec.end (), ':') > 1)));
58 1.1 christos
59 1.1 christos if (is_ipv6)
60 1.1 christos {
61 1.1 christos if (spec[0] == '[')
62 1.1 christos {
63 1.1 christos /* IPv6 addresses can be written as '[ADDR]:PORT', and we
64 1.1 christos support this notation. */
65 1.1 christos size_t close_bracket_pos = spec.find_first_of (']');
66 1.1 christos
67 1.1 christos if (close_bracket_pos == std::string::npos)
68 1.1 christos error (_("Missing close bracket in hostname '%s'"),
69 1.1 christos spec.c_str ());
70 1.1 christos
71 1.1 christos hint->ai_family = AF_INET6;
72 1.1 christos
73 1.1 christos const char c = spec[close_bracket_pos + 1];
74 1.1 christos
75 1.1 christos if (c == '\0')
76 1.1 christos last_colon_pos = std::string::npos;
77 1.1 christos else if (c != ':')
78 1.1 christos error (_("Invalid cruft after close bracket in '%s'"),
79 1.1 christos spec.c_str ());
80 1.1 christos
81 1.1 christos /* Erase both '[' and ']'. */
82 1.1 christos spec.erase (0, 1);
83 1.1 christos spec.erase (close_bracket_pos - 1, 1);
84 1.1 christos }
85 1.1 christos else if (spec.find_first_of (']') != std::string::npos)
86 1.1 christos error (_("Missing open bracket in hostname '%s'"),
87 1.1 christos spec.c_str ());
88 1.1 christos }
89 1.1 christos
90 1.1 christos if (last_colon_pos == 0)
91 1.1 christos last_colon_pos = spec.find_last_of (':');
92 1.1 christos
93 1.1 christos /* The length of the hostname part. */
94 1.1 christos size_t host_len;
95 1.1 christos
96 1.1 christos if (last_colon_pos != std::string::npos)
97 1.1 christos {
98 1.1 christos /* The user has provided a port. */
99 1.1 christos host_len = last_colon_pos;
100 1.1 christos ret.port_str = spec.substr (last_colon_pos + 1);
101 1.1 christos }
102 1.1 christos else
103 1.1 christos host_len = spec.size ();
104 1.1 christos
105 1.1 christos ret.host_str = spec.substr (0, host_len);
106 1.1 christos
107 1.1 christos /* Default hostname is localhost. */
108 1.1 christos if (ret.host_str.empty ())
109 1.1 christos ret.host_str = "localhost";
110 1.1 christos
111 1.1 christos return ret;
112 1.1 christos }
113 1.1 christos
114 1.1 christos /* See gdbsupport/netstuff.h. */
115 1.1 christos
116 1.1 christos parsed_connection_spec
117 1.1 christos parse_connection_spec (const char *spec, struct addrinfo *hint)
118 1.1 christos {
119 1.1 christos /* Struct to hold the association between valid prefixes, their
120 1.1 christos family and socktype. */
121 1.1 christos struct host_prefix
122 1.1 christos {
123 1.1 christos /* The prefix. */
124 1.1 christos const char *prefix;
125 1.1 christos
126 1.1 christos /* The 'ai_family'. */
127 1.1 christos int family;
128 1.1 christos
129 1.1 christos /* The 'ai_socktype'. */
130 1.1 christos int socktype;
131 1.1 christos };
132 1.1 christos static const struct host_prefix prefixes[] =
133 1.1 christos {
134 1.1 christos { "udp:", AF_UNSPEC, SOCK_DGRAM },
135 1.1 christos { "tcp:", AF_UNSPEC, SOCK_STREAM },
136 1.1 christos { "udp4:", AF_INET, SOCK_DGRAM },
137 1.1 christos { "tcp4:", AF_INET, SOCK_STREAM },
138 1.1 christos { "udp6:", AF_INET6, SOCK_DGRAM },
139 1.1 christos { "tcp6:", AF_INET6, SOCK_STREAM },
140 1.1 christos };
141 1.1 christos
142 1.1 christos for (const host_prefix prefix : prefixes)
143 1.1 christos if (startswith (spec, prefix.prefix))
144 1.1 christos {
145 1.1 christos spec += strlen (prefix.prefix);
146 1.1 christos hint->ai_family = prefix.family;
147 1.1 christos hint->ai_socktype = prefix.socktype;
148 1.1 christos hint->ai_protocol
149 1.1 christos = hint->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
150 1.1 christos break;
151 1.1 christos }
152 1.1 christos
153 1.1 christos return parse_connection_spec_without_prefix (spec, hint);
154 1.1 christos }
155