6#if defined(HAVE_CONFIG_H)
7#include <config/bitcoin-config.h>
58 ai_hint.ai_socktype = SOCK_STREAM;
59 ai_hint.ai_protocol = IPPROTO_TCP;
61 ai_hint.ai_family = AF_UNSPEC;
68 ai_hint.ai_flags = allow_lookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
70 addrinfo *ai_res{
nullptr};
71 const int n_err{getaddrinfo(
name.c_str(),
nullptr, &ai_hint, &ai_res)};
77 addrinfo *ai_trav{ai_res};
78 std::vector<CNetAddr> resolved_addresses;
79 while (ai_trav !=
nullptr) {
80 if (ai_trav->ai_family == AF_INET) {
81 assert(ai_trav->ai_addrlen >=
sizeof(sockaddr_in));
82 resolved_addresses.emplace_back(
83 reinterpret_cast<sockaddr_in *
>(ai_trav->ai_addr)->sin_addr);
85 if (ai_trav->ai_family == AF_INET6) {
86 assert(ai_trav->ai_addrlen >=
sizeof(sockaddr_in6));
87 const sockaddr_in6 *s6{
88 reinterpret_cast<sockaddr_in6 *
>(ai_trav->ai_addr)};
89 resolved_addresses.emplace_back(s6->sin6_addr, s6->sin6_scope_id);
91 ai_trav = ai_trav->ai_next;
95 return resolved_addresses;
101 std::string net =
ToLower(net_in);
108 if (net ==
"onion") {
112 LogPrintf(
"Warning: net name 'tor' is deprecated and will be removed "
113 "in the future. You should use 'onion' instead.\n");
125 return "not_publicly_routable";
146 std::vector<std::string> names;
147 for (
int n = 0; n <
NET_MAX; ++n) {
155 if (append_unroutable) {
162 unsigned int nMaxSolutions,
181 std::vector<CNetAddr> addresses;
183 for (
const CNetAddr &resolved : dns_lookup_function(
name, fAllowLookup)) {
184 if (nMaxSolutions > 0 && addresses.size() >= nMaxSolutions) {
190 if (!resolved.IsInternal()) {
191 addresses.push_back(resolved);
199 unsigned int nMaxSolutions,
bool fAllowLookup,
204 std::string strHost =
name;
205 if (strHost.empty()) {
208 if (strHost.front() ==
'[' && strHost.back() ==
']') {
209 strHost = strHost.substr(1, strHost.size() - 2);
212 return LookupIntern(strHost, nMaxSolutions, fAllowLookup,
213 dns_lookup_function);
218 const std::vector<CNetAddr> addresses{
220 return addresses.empty() ? std::nullopt
221 : std::make_optional(addresses.front());
224std::vector<CService>
Lookup(
const std::string &
name, uint16_t portDefault,
225 bool fAllowLookup,
unsigned int nMaxSolutions,
230 uint16_t port{portDefault};
231 std::string hostname;
235 hostname, nMaxSolutions, fAllowLookup, dns_lookup_function)};
236 if (addresses.empty()) {
239 std::vector<CService> services;
240 services.reserve(addresses.size());
241 for (
const auto &addr : addresses) {
242 services.emplace_back(addr, port);
247std::optional<CService>
Lookup(
const std::string &
name, uint16_t portDefault,
250 const std::vector<CService> services{
251 Lookup(
name, portDefault, fAllowLookup, 1, dns_lookup_function)};
253 return services.empty() ? std::nullopt
254 : std::make_optional(services.front());
280 return str.size() + 1 <=
sizeof(((sockaddr_un *)
nullptr)->sun_path);
351 std::chrono::milliseconds timeout,
353 auto curTime{Now<SteadyMilliseconds>()};
354 const auto endTime{curTime + timeout};
355 while (len > 0 && curTime < endTime) {
357 ssize_t ret = sock.
Recv(data, len, 0);
361 }
else if (ret == 0) {
371 const auto remaining =
372 std::chrono::milliseconds{endTime - curTime};
373 const auto timeout_ = std::min(
385 curTime = Now<SteadyMilliseconds>();
394 return "general failure";
396 return "connection not allowed";
398 return "network unreachable";
400 return "host unreachable";
402 return "connection refused";
404 return "TTL expired";
406 return "protocol error";
408 return "address type not supported";
432bool Socks5(
const std::string &strDest, uint16_t port,
436 if (strDest.size() > 255) {
441 std::vector<uint8_t> vSocks5Init;
446 vSocks5Init.push_back(0x02);
451 vSocks5Init.push_back(0x01);
456 if (ret != (ssize_t)vSocks5Init.size()) {
457 LogError(
"Error sending to proxy\n");
463 LogPrintf(
"Socks5() connect to %s:%d failed: InterruptibleRecv() "
464 "timeout or other failure\n",
469 LogError(
"Proxy failed to initialize\n");
474 std::vector<uint8_t> vAuth;
476 vAuth.push_back(0x01);
478 LogError(
"Proxy username or password too long\n");
481 vAuth.push_back(auth->
username.size());
483 vAuth.push_back(auth->
password.size());
486 if (ret != (ssize_t)vAuth.size()) {
487 LogError(
"Error sending authentication to proxy\n");
495 LogError(
"Error reading proxy authentication response\n");
498 if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
499 LogError(
"Proxy authentication unsuccessful\n");
505 LogError(
"Proxy requested wrong authentication method %02x\n",
509 std::vector<uint8_t> vSocks5;
515 vSocks5.push_back(0x00);
519 vSocks5.push_back(strDest.size());
520 vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
521 vSocks5.push_back((port >> 8) & 0xFF);
522 vSocks5.push_back((port >> 0) & 0xFF);
524 if (ret != (ssize_t)vSocks5.size()) {
525 LogError(
"Error sending to proxy\n");
539 LogError(
"Error while reading proxy response\n");
544 LogError(
"Proxy failed to accept request\n");
549 LogPrintf(
"Socks5() connect to %s:%d failed: %s\n", strDest, port,
554 if (pchRet2[2] != 0x00) {
555 LogError(
"Error: malformed proxy response\n");
558 uint8_t pchRet3[256];
559 switch (pchRet2[3]) {
569 LogError(
"Error reading from proxy\n");
572 int nRecv = pchRet3[0];
578 LogError(
"Error: malformed proxy response\n");
582 LogError(
"Error reading from proxy\n");
587 LogError(
"Error reading from proxy\n");
594std::unique_ptr<Sock>
CreateSockOS(
int domain,
int type,
int protocol) {
596 if (domain == AF_UNSPEC) {
601 SOCKET hSocket = socket(domain, type, protocol);
606 auto sock = std::make_unique<Sock>(hSocket);
608 if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
614 if (!sock->IsSelectable()) {
615 LogPrintf(
"Cannot create connection: non-selectable socket created (fd "
616 ">= FD_SETSIZE ?)\n");
627 "Error setting SO_NOSIGPIPE on socket: %s, continuing anyway\n",
633 if (!sock->SetNonBlocking()) {
634 LogPrintf(
"CreateSocket: Setting socket to non-blocking "
635 "failed, error %s\n",
641 if (domain == AF_UNIX) {
646 if (protocol == IPPROTO_TCP) {
650 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
653 "socket, continuing anyway\n");
662template <
typename... Args>
664 const Args &...args) {
665 std::string error_message =
tfm::format(fmt, args...);
666 if (manual_connection) {
674 socklen_t len,
const std::string &dest_str,
675 bool manual_connection) {
687 if (!sock.
Wait(std::chrono::milliseconds{nConnectTimeout},
688 requested, &occurred)) {
689 LogPrintf(
"wait for connect to %s failed: %s\n", dest_str,
692 }
else if (occurred == 0) {
703 socklen_t sockerr_len =
sizeof(sockerr);
707 LogPrintf(
"getsockopt() for %s failed: %s\n", dest_str,
713 "connect() to %s failed after wait: %s",
733 bool manual_connection) {
737 "Cannot create a socket for connecting to %s\n",
743 struct sockaddr_storage sockaddr;
744 socklen_t len =
sizeof(sockaddr);
745 if (!dest.
GetSockAddr((
struct sockaddr *)&sockaddr, &len)) {
746 LogPrintf(
"Cannot get sockaddr for %s: unsupported network\n",
762 LogPrintf(
"Cannot connect to invalid Proxy\n");
771 auto sock =
CreateSock(AF_UNIX, SOCK_STREAM, 0);
774 "Cannot create a socket for connecting to %s\n",
779 const std::string path{
782 struct sockaddr_un addrun;
783 memset(&addrun, 0,
sizeof(addrun));
784 addrun.sun_family = AF_UNIX;
786 memcpy(addrun.sun_path, path.c_str(),
787 std::min(
sizeof(addrun.sun_path) - 1, path.length()));
788 socklen_t len =
sizeof(addrun);
792 LogPrintf(
"Cannot connect to socket for %s\n", path);
808 proxyInfo[net] = addrProxy;
815 if (!proxyInfo[net].IsValid()) {
818 proxyInfoOut = proxyInfo[net];
827 nameProxy = addrProxy;
833 if (!nameProxy.IsValid()) {
836 nameProxyOut = nameProxy;
842 return nameProxy.IsValid();
847 for (
int i = 0; i <
NET_MAX; i++) {
848 if (addr ==
static_cast<CNetAddr>(proxyInfo[i].proxy)) {
856 const std::string &dest,
858 bool &proxy_connection_failed) {
862 proxy_connection_failed =
true;
869 static std::atomic_int counter(0);
872 if (!
Socks5(dest, port, &random_auth, *sock)) {
875 }
else if (!
Socks5(dest, port, 0, *sock)) {
886 size_t slash = strSubnet.find_last_of(
'/');
887 std::string strAddress = strSubnet.substr(0, slash);
888 const std::optional<CNetAddr> network{
891 if (network.has_value()) {
892 if (slash != strSubnet.npos) {
893 std::string strNetmask = strSubnet.substr(slash + 1);
897 ret =
CSubNet(network.value(), n);
901 const std::optional<CNetAddr> netmask{
LookupHost(
902 strNetmask,
false, dns_lookup_function)};
904 if (netmask.has_value()) {
905 ret =
CSubNet(network.value(), netmask.value());
911 ret =
CSubNet(network.value());
bool SetSpecial(const std::string &addr)
Parse a Tor or I2P address and set this object to it.
A combination of a network address (CNetAddr) and a (TCP) port.
sa_family_t GetSAFamily() const
Get the address family.
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
std::string ToStringAddrPort() const
Different type to mark Mutex at global scope.
bool m_randomize_credentials
std::unique_ptr< Sock > Connect() const
std::string m_unix_socket_path
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
virtual ssize_t Send(const void *data, size_t len, int flags) const
send(2) wrapper.
static constexpr Event SEND
If passed to Wait(), then it will wait for readiness to send to the socket.
virtual bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const
Wait for readiness for input (recv) or output (send).
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
virtual int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const
getsockopt(2) wrapper.
virtual int Connect(const sockaddr *addr, socklen_t addr_len) const
connect(2) wrapper.
virtual ssize_t Recv(void *buf, size_t len, int flags) const
recv(2) wrapper.
#define WSAGetLastError()
#define LogPrintLevel(category, level,...)
#define LogPrint(category,...)
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
@ NET_MAX
Dummy value to indicate the number of NET_* constants.
@ NET_ONION
TOR (v2 or v3)
@ NET_UNROUTABLE
Addresses from these networks are not publicly routable on the global Internet.
@ NET_INTERNAL
A set of addresses that represent the hash of a string or FQDN.
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
SOCKS5Command
Values defined for CMD in RFC1928.
std::unique_ptr< Sock > ConnectDirectly(const CService &dest, bool manual_connection)
Create a socket and try to connect to the specified service.
std::vector< CNetAddr > LookupHost(const std::string &name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
Resolve a host string to its corresponding network addresses.
static Proxy proxyInfo[NET_MAX] GUARDED_BY(g_proxyinfo_mutex)
std::chrono::milliseconds g_socks5_recv_timeout
std::string GetNetworkName(enum Network net)
static void LogConnectFailure(bool manual_connection, const char *fmt, const Args &...args)
static IntrRecvError InterruptibleRecv(uint8_t *data, size_t len, std::chrono::milliseconds timeout, const Sock &sock)
Try to read a specified number of bytes from a socket.
SOCKSVersion
SOCKS version.
bool SetNameProxy(const Proxy &addrProxy)
Set the name proxy to use for all connections to nodes specified by a hostname.
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret, DNSLookupFn dns_lookup_function)
Parse and resolve a specified subnet string into the appropriate internal representation.
enum Network ParseNetwork(const std::string &net_in)
SOCKS5Method
Values defined for METHOD in RFC1928.
@ NOAUTH
No authentication required.
@ USER_PASS
Username/password.
@ NO_ACCEPTABLE
No acceptable methods.
bool Socks5(const std::string &strDest, uint16_t port, const ProxyCredentials *auth, const Sock &sock)
Connect to a specified destination service through an already connected SOCKS5 proxy.
static std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to an error message.
void InterruptSocks5(bool interrupt)
bool SetProxy(enum Network net, const Proxy &addrProxy)
std::vector< CService > Lookup(const std::string &name, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
Resolve a service string to its corresponding service.
static std::vector< CNetAddr > LookupIntern(const std::string &name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
SOCKS5Reply
Values defined for REP in RFC1928.
@ CMDUNSUPPORTED
Command not supported.
@ NETUNREACHABLE
Network unreachable.
@ GENFAILURE
General failure.
@ CONNREFUSED
Connection refused.
@ ATYPEUNSUPPORTED
Address type not supported.
@ NOTALLOWED
Connection not allowed by ruleset.
@ HOSTUNREACHABLE
Network unreachable.
static GlobalMutex g_proxyinfo_mutex
std::unique_ptr< Sock > CreateSockOS(int domain, int type, int protocol)
Create a real socket from the operating system.
bool GetProxy(enum Network net, Proxy &proxyInfoOut)
static std::atomic< bool > interruptSocks5Recv(false)
static bool ConnectToSocket(const Sock &sock, struct sockaddr *sockaddr, socklen_t len, const std::string &dest_str, bool manual_connection)
std::unique_ptr< Sock > ConnectThroughProxy(const Proxy &proxy, const std::string &dest, uint16_t port, bool &proxy_connection_failed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
std::function< std::unique_ptr< Sock >(int, int, int)> CreateSock
Socket factory.
bool IsUnixSocketPath(const std::string &name)
Check if a string is a valid UNIX domain socket path.
bool GetNameProxy(Proxy &nameProxyOut)
CService LookupNumeric(const std::string &name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
Resolve a service string with a numeric IP to its first corresponding service.
bool IsProxy(const CNetAddr &addr)
bool IsBadPort(uint16_t port)
Determine if a port is "bad" from the perspective of attempting to connect to a node on that port.
std::vector< CNetAddr > WrappedGetAddrInfo(const std::string &name, bool allow_lookup)
Wrapper for getaddrinfo(3).
std::vector< std::string > GetNetworkNames(bool append_unroutable)
Return a vector of publicly routable Network names; optionally append NET_UNROUTABLE.
static const int DEFAULT_NAME_LOOKUP
-dns default
const std::string ADDR_PREFIX_UNIX
Prefix for unix domain socket addresses (which are local filesystem paths)
std::function< std::vector< CNetAddr >(const std::string &, bool)> DNSLookupFn
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
@ OK
The message verification was successful.
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
static constexpr auto MAX_WAIT_FOR_IO
Maximum time to wait for I/O readiness.
Credentials for proxy authentication.
bool ParseUInt8(std::string_view str, uint8_t *out)
Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
bool SplitHostPort(std::string_view in, uint16_t &portOut, std::string &hostOut)
Splits socket address string into host string and port value.
std::string ToLower(std::string_view str)
Returns the lowercase equivalent of the given string.