MySQL 9.1.0
Source Code Documentation
resolver.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2020, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25#ifndef MYSQL_HARNESS_NET_TS_IMPL_RESOLVER_H_
26#define MYSQL_HARNESS_NET_TS_IMPL_RESOLVER_H_
27
28#include <algorithm>
29#include <memory> // unique_ptr
30#include <string>
31#include <system_error>
32
33#ifdef _WIN32
34#include <WinSock2.h>
35#include <windows.h>
36#include <ws2tcpip.h> // addrinfo
37#else
38#include <arpa/inet.h> // inet_ntop
39#include <netdb.h> // getaddrinfo
40#include <unistd.h> // gethostname
41#endif
42
43#include "mysql/harness/net_ts/impl/socket_error.h" // socket::last_error_code
45
46namespace net {
47namespace ip {
48enum class resolver_errc {
49 try_again = EAI_AGAIN, //!< name could not be resolved at this time
50 bad_flags = EAI_BADFLAGS, //!< flags parameter had an invalid value
51#ifdef EAI_BADHINTS
52 // freebsd, macosx
53 bad_hints = EAI_BADHINTS, //!< invalid value for hints
54#endif
55#ifdef EAI_ADDRFAMILY
56 // glibc, (removed in freebsd), solaris, macosx
57 bad_address_family =
58 EAI_ADDRFAMILY, //!< address family for NAME not supported
59#endif
60 fail = EAI_FAIL, //!< non recoverable failed on name resolution
61 bad_family = EAI_FAMILY, //!< ai_family not supported
62 out_of_memory = EAI_MEMORY, //!< memory allocation failed
63#ifdef EAI_NODATA
64 // glibc, (removed in freebsd), solaris, macosx
65 no_data = EAI_NODATA, //!< no address associated with NAME
66#endif
67 host_not_found = EAI_NONAME, //!< NAME or SERVICE is unknown
68#ifdef EAI_OVERFLOW
69 // glibc, freebsd, solaris, macosx, musl
70 overflow = EAI_OVERFLOW, //!< argument buffer overflow
71#endif
72#ifdef EAI_PROTOCOL
73 // glibc, freebsd, solaris, macosx
74 bad_protocol = EAI_PROTOCOL, //!< resolved protocol unknown
75#endif
76#ifdef EAI_CANCELED
77 // glibc
78 cancelled = EAI_CANCELED, //!< request cancelled
79#endif
80#ifdef EAI_NOTCANCELED
81 // glibc
82 not_cancelled = EAI_NOTCANCELED, //!< request not cancelled
83#endif
84#ifdef EAI_INPROGRESS
85 // glibc
86 in_progress = EAI_INPROGRESS, //!< request in progress
87#endif
88#ifdef EAI_ALLDONE
89 // glibc
90 all_done = EAI_ALLDONE, //!< all done
91#endif
92#ifdef EAI_INTR
93 // glibc
94 interrupted = EAI_INTR, //!< interrupted
95#endif
96#ifdef EAI_IDN_ENCODE
97 // glibc
98 idn_encode_failed = EAI_IDN_ENCODE, //!< IDN encode failed
99#endif
100 service_not_found = EAI_SERVICE, //!< SERVICE not supported for ai_socktype
101 bad_socktype = EAI_SOCKTYPE, //!< ai_socktype not supported
102};
103} // namespace ip
104} // namespace net
105
106namespace std {
107template <>
108struct is_error_code_enum<net::ip::resolver_errc> : true_type {};
109} // namespace std
110
111namespace net {
112namespace ip {
113inline const std::error_category &resolver_category() noexcept {
114 class category_impl : public std::error_category {
115 public:
116 const char *name() const noexcept override { return "resolver"; }
117 std::string message(int ev) const override { return gai_strerror(ev); }
118
119 // MSDN says:
120 //
121 // EAI_AGAIN == WSATRY_AGAIN
122 // EAI_BADFLAGS == WSAEINVAL
123 // EAI_FAIL == WSANO_RECOVERY
124 // EAI_FAMILY == WSAEAFNOSUPPORT
125 // EAI_MEMORY == WSA_NOT_ENOUGH_MEMORY
126 // EAI_NONAME == WSAHOST_NOT_FOUND
127 // EAI_SERVICE == WSATYPE_NOT_FOUND
128 // EAI_SOCKTYPE == WSAESOCKTNOTSUPPORT
129 };
130
131 static category_impl instance;
132 return instance;
133}
134
135inline std::error_code make_error_code(resolver_errc ec) {
136 return {static_cast<int>(ec), resolver_category()};
137}
138} // namespace ip
139
140namespace impl {
141namespace resolver {
142
143/**
144 * get hostname.
145 *
146 * @returns void on success, the native function's error-code on error
147 * @retval std::errc::filename_too_long if the buffer is too small to contain
148 * the hostname + nul-char
149 *
150 */
152 size_t buf_len) {
153 if (0 != ::gethostname(buf, buf_len)) {
155 }
156
157 // POSIX says that it is unspecified if the returned string contains
158 // a \0 char if truncation occurred.
159 //
160 // Looks like only Solaris doesn't add \0 and doesn't return an error.
161 //
162 const auto begin = buf;
163 const auto end = buf + buf_len;
164
165 if (end == std::find(begin, end, '\0')) {
166 return stdx::unexpected(
167 std::error_code(make_error_code(std::errc::filename_too_long)));
168 }
169
170 return {};
171}
172
174 const struct sockaddr *saddr, socklen_t addrlen, char *host,
175 socklen_t hostlen, char *serv, socklen_t servlen, int flags) {
176#if defined(__APPLE__)
177 // macosx doesn't check the 'addrlen' parameter and reads garbage.
178
179 if (addrlen < sizeof(*saddr)) {
180 return stdx::unexpected(
182 }
183
184 if ((saddr->sa_family == AF_INET && addrlen < sizeof(sockaddr_in)) ||
185 (saddr->sa_family == AF_INET6 && addrlen < sizeof(sockaddr_in6))) {
186 return stdx::unexpected(
188 }
189#endif
190
191 int ret = ::getnameinfo(saddr, addrlen, host, hostlen, serv, servlen, flags);
192 if (ret != 0) {
193#ifdef EAI_SYSTEM
194 // linux, freebsd, solaris, macosx
195 if (ret == EAI_SYSTEM) {
197 } else {
198 return stdx::unexpected(
199 std::error_code{ret, net::ip::resolver_category()});
200 }
201#else
202#if defined(_WIN32)
203 switch (ret) {
204 case EAI_AGAIN:
205 case EAI_BADFLAGS:
206 case EAI_FAIL:
207 case EAI_FAMILY:
208 case EAI_MEMORY:
209 case EAI_NONAME:
210 case EAI_SERVICE:
211 case EAI_SOCKTYPE:
212 break;
213 default:
214 return stdx::unexpected(std::error_code{ret, std::system_category()});
215 }
216#endif
217 return stdx::unexpected(std::error_code{ret, net::ip::resolver_category()});
218#endif
219 }
220
221 return {};
222}
223
224inline stdx::expected<
225 std::unique_ptr<struct addrinfo, void (*)(struct addrinfo *)>,
226 std::error_code>
227getaddrinfo(const char *node, const char *service,
228 const struct addrinfo *hints) {
229 struct addrinfo *ainfo{nullptr};
230
231 int ret = ::getaddrinfo(node, service, hints, &ainfo);
232 if (ret != 0) {
233#ifdef EAI_SYSTEM
234 // linux, freebsd, solaris, macosx
235 if (ret == EAI_SYSTEM) {
237 } else {
238 return stdx::unexpected(
239 std::error_code{ret, net::ip::resolver_category()});
240 }
241#else
242#if defined(_WIN32)
243 switch (ret) {
244 case EAI_AGAIN:
245 case EAI_BADFLAGS:
246 case EAI_FAIL:
247 case EAI_FAMILY:
248 case EAI_MEMORY:
249 case EAI_NONAME:
250 case EAI_SERVICE:
251 case EAI_SOCKTYPE:
252 break;
253 default:
254 return stdx::unexpected(std::error_code{ret, std::system_category()});
255 }
256#endif
257 return stdx::unexpected(std::error_code{ret, net::ip::resolver_category()});
258#endif
259 }
260 using ret_type = stdx::expected<
261 std::unique_ptr<struct addrinfo, void (*)(struct addrinfo *)>,
262 std::error_code>;
263
264 return ret_type{std::in_place, ainfo, &::freeaddrinfo};
265}
266
268 const void *src,
269 char *out,
270 size_t out_len) {
271 if (nullptr == ::inet_ntop(af, src, out, out_len)) {
273 }
274 return out;
275}
276
277// # async getaddrinfo
278//
279// windows has GetAddrInfoEx
280// linux has getaddrinfo_a
281// freebsd has getaddrinfo_async
282
283} // namespace resolver
284} // namespace impl
285
286} // namespace net
287
288#endif
Definition: expected.h:286
static char buf[MAX_BUF]
Definition: conf_to_src.cc:73
static int flags[50]
Definition: hp_test1.cc:40
const char * host
Definition: mysqladmin.cc:65
static bool interrupted
Definition: mysqladmin.cc:72
Definition: buf0block_hint.cc:30
Container::const_iterator find(const Container &c, Value &&value)
Definition: generic.h:39
Definition: http_server_component.cc:34
const char * begin(const char *const c)
Definition: base64.h:44
stdx::expected< std::unique_ptr< struct addrinfo, void(*)(struct addrinfo *)>, std::error_code > getaddrinfo(const char *node, const char *service, const struct addrinfo *hints)
Definition: resolver.h:227
stdx::expected< const char *, std::error_code > inetntop(int af, const void *src, char *out, size_t out_len)
Definition: resolver.h:267
stdx::expected< void, std::error_code > gethostname(char *buf, size_t buf_len)
get hostname.
Definition: resolver.h:151
stdx::expected< void, std::error_code > getnameinfo(const struct sockaddr *saddr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
Definition: resolver.h:173
std::error_code last_error_code()
get last std::error_code for socket-errors.
Definition: socket_error.h:107
resolver_errc
Definition: resolver.h:48
@ bad_socktype
ai_socktype not supported
@ host_not_found
NAME or SERVICE is unknown.
@ bad_flags
flags parameter had an invalid value
@ service_not_found
SERVICE not supported for ai_socktype.
@ out_of_memory
memory allocation failed
@ try_again
name could not be resolved at this time
@ fail
non recoverable failed on name resolution
@ bad_family
ai_family not supported
const std::error_category & resolver_category() noexcept
Definition: resolver.h:113
std::error_code make_error_code(resolver_errc ec)
Definition: resolver.h:135
Definition: buffer.h:45
std::error_code make_error_code(net::stream_errc e) noexcept
Definition: buffer.h:103
Definition: gcs_xcom_synode.h:64
unexpected(E) -> unexpected< E >
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr
The following is a common type that is returned by all the ut::make_unique (non-aligned) specializati...
Definition: ut0new.h:2440
struct sockaddr sockaddr
Definition: sock_probe_win32.h:63
case opt name
Definition: sslopt-case.h:29