netstuff.cc revision 1.1.1.4 1 1.1 christos /* Operations on network stuff.
2 1.1.1.4 christos Copyright (C) 2018-2025 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 "netstuff.h"
20 1.1 christos #include <algorithm>
21 1.1 christos
22 1.1 christos #ifdef USE_WIN32API
23 1.1 christos #include <ws2tcpip.h>
24 1.1 christos #else
25 1.1 christos #include <netinet/in.h>
26 1.1 christos #include <arpa/inet.h>
27 1.1 christos #include <netdb.h>
28 1.1 christos #include <sys/socket.h>
29 1.1 christos #include <netinet/tcp.h>
30 1.1 christos #endif
31 1.1 christos
32 1.1 christos /* See gdbsupport/netstuff.h. */
33 1.1 christos
34 1.1 christos scoped_free_addrinfo::~scoped_free_addrinfo ()
35 1.1 christos {
36 1.1 christos freeaddrinfo (m_res);
37 1.1 christos }
38 1.1 christos
39 1.1 christos /* See gdbsupport/netstuff.h. */
40 1.1 christos
41 1.1 christos parsed_connection_spec
42 1.1 christos parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
43 1.1 christos {
44 1.1 christos parsed_connection_spec ret;
45 1.1 christos size_t last_colon_pos = 0;
46 1.1 christos /* We're dealing with IPv6 if:
47 1.1 christos
48 1.1 christos - ai_family is AF_INET6, or
49 1.1 christos - ai_family is not AF_INET, and
50 1.1 christos - spec[0] is '[', or
51 1.1 christos - the number of ':' on spec is greater than 1. */
52 1.1 christos bool is_ipv6 = (hint->ai_family == AF_INET6
53 1.1 christos || (hint->ai_family != AF_INET
54 1.1 christos && (spec[0] == '['
55 1.1 christos || std::count (spec.begin (),
56 1.1 christos spec.end (), ':') > 1)));
57 1.1 christos
58 1.1 christos if (is_ipv6)
59 1.1 christos {
60 1.1 christos if (spec[0] == '[')
61 1.1 christos {
62 1.1 christos /* IPv6 addresses can be written as '[ADDR]:PORT', and we
63 1.1 christos support this notation. */
64 1.1 christos size_t close_bracket_pos = spec.find_first_of (']');
65 1.1 christos
66 1.1 christos if (close_bracket_pos == std::string::npos)
67 1.1 christos error (_("Missing close bracket in hostname '%s'"),
68 1.1 christos spec.c_str ());
69 1.1 christos
70 1.1 christos hint->ai_family = AF_INET6;
71 1.1 christos
72 1.1 christos const char c = spec[close_bracket_pos + 1];
73 1.1 christos
74 1.1 christos if (c == '\0')
75 1.1 christos last_colon_pos = std::string::npos;
76 1.1 christos else if (c != ':')
77 1.1 christos error (_("Invalid cruft after close bracket in '%s'"),
78 1.1 christos spec.c_str ());
79 1.1 christos
80 1.1 christos /* Erase both '[' and ']'. */
81 1.1 christos spec.erase (0, 1);
82 1.1 christos spec.erase (close_bracket_pos - 1, 1);
83 1.1 christos }
84 1.1 christos else if (spec.find_first_of (']') != std::string::npos)
85 1.1 christos error (_("Missing open bracket in hostname '%s'"),
86 1.1 christos spec.c_str ());
87 1.1 christos }
88 1.1 christos
89 1.1 christos if (last_colon_pos == 0)
90 1.1 christos last_colon_pos = spec.find_last_of (':');
91 1.1 christos
92 1.1 christos /* The length of the hostname part. */
93 1.1 christos size_t host_len;
94 1.1 christos
95 1.1 christos if (last_colon_pos != std::string::npos)
96 1.1 christos {
97 1.1 christos /* The user has provided a port. */
98 1.1 christos host_len = last_colon_pos;
99 1.1 christos ret.port_str = spec.substr (last_colon_pos + 1);
100 1.1 christos }
101 1.1 christos else
102 1.1 christos host_len = spec.size ();
103 1.1 christos
104 1.1 christos ret.host_str = spec.substr (0, host_len);
105 1.1 christos
106 1.1 christos /* Default hostname is localhost. */
107 1.1 christos if (ret.host_str.empty ())
108 1.1 christos ret.host_str = "localhost";
109 1.1 christos
110 1.1 christos return ret;
111 1.1 christos }
112 1.1 christos
113 1.1 christos /* See gdbsupport/netstuff.h. */
114 1.1 christos
115 1.1 christos parsed_connection_spec
116 1.1 christos parse_connection_spec (const char *spec, struct addrinfo *hint)
117 1.1 christos {
118 1.1 christos /* Struct to hold the association between valid prefixes, their
119 1.1 christos family and socktype. */
120 1.1 christos struct host_prefix
121 1.1 christos {
122 1.1 christos /* The prefix. */
123 1.1 christos const char *prefix;
124 1.1 christos
125 1.1 christos /* The 'ai_family'. */
126 1.1 christos int family;
127 1.1 christos
128 1.1 christos /* The 'ai_socktype'. */
129 1.1 christos int socktype;
130 1.1 christos };
131 1.1 christos static const struct host_prefix prefixes[] =
132 1.1 christos {
133 1.1 christos { "udp:", AF_UNSPEC, SOCK_DGRAM },
134 1.1 christos { "tcp:", AF_UNSPEC, SOCK_STREAM },
135 1.1 christos { "udp4:", AF_INET, SOCK_DGRAM },
136 1.1 christos { "tcp4:", AF_INET, SOCK_STREAM },
137 1.1 christos { "udp6:", AF_INET6, SOCK_DGRAM },
138 1.1 christos { "tcp6:", AF_INET6, SOCK_STREAM },
139 1.1 christos };
140 1.1 christos
141 1.1 christos for (const host_prefix prefix : prefixes)
142 1.1 christos if (startswith (spec, prefix.prefix))
143 1.1 christos {
144 1.1 christos spec += strlen (prefix.prefix);
145 1.1 christos hint->ai_family = prefix.family;
146 1.1 christos hint->ai_socktype = prefix.socktype;
147 1.1 christos hint->ai_protocol
148 1.1 christos = hint->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
149 1.1 christos break;
150 1.1 christos }
151 1.1 christos
152 1.1 christos return parse_connection_spec_without_prefix (spec, hint);
153 1.1 christos }
154