6 #include <bitcoin-build-config.h> 17 #include <util/time.h> 26 #ifdef HAVE_SOCKADDR_UN 49 ai_hint.ai_socktype = SOCK_STREAM;
50 ai_hint.ai_protocol = IPPROTO_TCP;
52 ai_hint.ai_family = AF_UNSPEC;
60 ai_hint.ai_flags = allow_lookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
62 addrinfo* ai_res{
nullptr};
63 const int n_err{getaddrinfo(
name.c_str(),
nullptr, &ai_hint, &ai_res)};
65 if ((ai_hint.ai_flags & AI_ADDRCONFIG) == AI_ADDRCONFIG) {
68 ai_hint.ai_flags = (ai_hint.ai_flags & ~AI_ADDRCONFIG);
69 const int n_err_retry{getaddrinfo(
name.c_str(),
nullptr, &ai_hint, &ai_res)};
70 if (n_err_retry != 0) {
79 addrinfo* ai_trav{ai_res};
80 std::vector<CNetAddr> resolved_addresses;
81 while (ai_trav !=
nullptr) {
82 if (ai_trav->ai_family == AF_INET) {
83 assert(ai_trav->ai_addrlen >=
sizeof(sockaddr_in));
84 resolved_addresses.emplace_back(reinterpret_cast<sockaddr_in*>(ai_trav->ai_addr)->sin_addr);
86 if (ai_trav->ai_family == AF_INET6) {
87 assert(ai_trav->ai_addrlen >=
sizeof(sockaddr_in6));
88 const sockaddr_in6* s6{
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 ==
"cjdns") {
132 std::vector<std::string> names;
133 for (
int n = 0; n <
NET_MAX; ++n) {
138 if (append_unroutable) {
144 static std::vector<CNetAddr>
LookupIntern(
const std::string&
name,
unsigned int nMaxSolutions,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
158 std::vector<CNetAddr> addresses;
160 for (
const CNetAddr& resolved : dns_lookup_function(
name, fAllowLookup)) {
161 if (nMaxSolutions > 0 && addresses.size() >= nMaxSolutions) {
165 if (!resolved.IsInternal()) {
166 addresses.push_back(resolved);
173 std::vector<CNetAddr>
LookupHost(
const std::string&
name,
unsigned int nMaxSolutions,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
176 std::string strHost =
name;
177 if (strHost.empty())
return {};
178 if (strHost.front() ==
'[' && strHost.back() ==
']') {
179 strHost = strHost.substr(1, strHost.size() - 2);
182 return LookupIntern(strHost, nMaxSolutions, fAllowLookup, dns_lookup_function);
187 const std::vector<CNetAddr> addresses{
LookupHost(
name, 1, fAllowLookup, dns_lookup_function)};
188 return addresses.empty() ? std::nullopt : std::make_optional(addresses.front());
191 std::vector<CService>
Lookup(
const std::string&
name, uint16_t portDefault,
bool fAllowLookup,
unsigned int nMaxSolutions,
DNSLookupFn dns_lookup_function)
196 uint16_t port{portDefault};
197 std::string hostname;
200 const std::vector<CNetAddr> addresses{
LookupIntern(hostname, nMaxSolutions, fAllowLookup, dns_lookup_function)};
201 if (addresses.empty())
return {};
202 std::vector<CService> services;
203 services.reserve(addresses.size());
204 for (
const auto& addr : addresses)
205 services.emplace_back(addr, port);
209 std::optional<CService>
Lookup(
const std::string&
name, uint16_t portDefault,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
211 const std::vector<CService> services{
Lookup(
name, portDefault, fAllowLookup, 1, dns_lookup_function)};
213 return services.empty() ? std::nullopt : std::make_optional(services.front());
228 #ifdef HAVE_SOCKADDR_UN 236 if (str.size() + 1 >
sizeof(((sockaddr_un*)
nullptr)->sun_path))
return false;
320 auto curTime{Now<SteadyMilliseconds>()};
321 const auto endTime{curTime + timeout};
322 while (len > 0 && curTime < endTime) {
327 }
else if (
ret == 0) {
334 const auto remaining = std::chrono::milliseconds{endTime - curTime};
335 const auto timeout = std::min(remaining, std::chrono::milliseconds{
MAX_WAIT_FOR_IO});
346 curTime = Now<SteadyMilliseconds>();
356 return "general failure";
358 return "connection not allowed";
360 return "network unreachable";
362 return "host unreachable";
364 return "connection refused";
366 return "TTL expired";
368 return "protocol error";
370 return "address type not supported";
372 return "onion service descriptor can not be found";
374 return "onion service descriptor is invalid";
376 return "onion service introduction failed";
378 return "onion service rendezvous failed";
380 return "onion service missing client authorization";
382 return "onion service wrong client authorization";
384 return "onion service invalid address";
386 return "onion service introduction timed out";
388 return strprintf(
"unknown (0x%02x)", err);
397 if (strDest.size() > 255) {
402 std::vector<uint8_t> vSocks5Init;
405 vSocks5Init.push_back(0x02);
409 vSocks5Init.push_back(0x01);
415 LogInfo(
"Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
419 LogError(
"Proxy failed to initialize\n");
424 std::vector<uint8_t> vAuth;
425 vAuth.push_back(0x01);
427 LogError(
"Proxy username or password too long\n");
430 vAuth.push_back(auth->
username.size());
432 vAuth.push_back(auth->
password.size());
438 LogError(
"Error reading proxy authentication response\n");
441 if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
442 LogError(
"Proxy authentication unsuccessful\n");
448 LogError(
"Proxy requested wrong authentication method %02x\n", pchRet1[1]);
451 std::vector<uint8_t> vSocks5;
454 vSocks5.push_back(0x00);
456 vSocks5.push_back(strDest.size());
457 vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
458 vSocks5.push_back((port >> 8) & 0xFF);
459 vSocks5.push_back((port >> 0) & 0xFF);
469 LogError(
"Error while reading proxy response\n");
474 LogError(
"Proxy failed to accept request\n");
480 "Socks5() connect to %s:%d failed: %s\n", strDest, port,
Socks5ErrorString(pchRet2[1]));
483 if (pchRet2[2] != 0x00) {
484 LogError(
"Error: malformed proxy response\n");
487 uint8_t pchRet3[256];
488 switch (pchRet2[3]) {
494 LogError(
"Error reading from proxy\n");
497 int nRecv = pchRet3[0];
502 LogError(
"Error: malformed proxy response\n");
507 LogError(
"Error reading from proxy\n");
511 LogError(
"Error reading from proxy\n");
516 }
catch (
const std::runtime_error& e) {
517 LogError(
"Error during SOCKS5 proxy handshake: %s\n", e.what());
525 if (domain == AF_UNSPEC)
return nullptr;
528 SOCKET hSocket = socket(domain, type, protocol);
533 auto sock = std::make_unique<Sock>(hSocket);
535 if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
541 if (!sock->IsSelectable()) {
542 LogInfo(
"Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
550 if (sock->SetSockOpt(SOL_SOCKET, SO_NOSIGPIPE, &
set,
sizeof(
int)) ==
SOCKET_ERROR) {
551 LogInfo(
"Error setting SO_NOSIGPIPE on socket: %s, continuing anyway\n",
557 if (!sock->SetNonBlocking()) {
562 #ifdef HAVE_SOCKADDR_UN 563 if (domain == AF_UNIX)
return sock;
566 if (protocol == IPPROTO_TCP) {
569 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
570 LogDebug(
BCLog::NET,
"Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n");
579 template<
typename... Args>
583 if (manual_connection) {
584 LogInfo(
"%s\n", error_message);
590 static bool ConnectToSocket(
const Sock& sock,
struct sockaddr* sockaddr, socklen_t len,
const std::string& dest_str,
bool manual_connection)
603 if (!sock.
Wait(std::chrono::milliseconds{nConnectTimeout}, requested, &occurred)) {
604 LogInfo(
"wait for connect to %s failed: %s\n",
608 }
else if (occurred == 0) {
618 socklen_t sockerr_len =
sizeof(sockerr);
619 if (sock.
GetSockOpt(SOL_SOCKET, SO_ERROR, &sockerr, &sockerr_len) ==
626 "connect() to %s failed after wait: %s",
654 struct sockaddr_storage sockaddr;
655 socklen_t len =
sizeof(sockaddr);
656 if (!dest.
GetSockAddr((
struct sockaddr*)&sockaddr, &len)) {
674 #ifdef HAVE_SOCKADDR_UN 675 auto sock =
CreateSock(AF_UNIX, SOCK_STREAM, 0);
683 struct sockaddr_un addrun;
684 memset(&addrun, 0,
sizeof(addrun));
685 addrun.sun_family = AF_UNIX;
687 memcpy(addrun.sun_path, path.c_str(), std::min(
sizeof(addrun.sun_path) - 1, path.length()));
688 socklen_t len =
sizeof(addrun);
690 if(!
ConnectToSocket(*sock, (
struct sockaddr*)&addrun, len, path,
true)) {
705 proxyInfo[net] = addrProxy;
712 if (!proxyInfo[net].IsValid())
714 proxyInfoOut = proxyInfo[net];
722 nameProxy = addrProxy;
728 if(!nameProxy.IsValid())
730 nameProxyOut = nameProxy;
736 return nameProxy.IsValid();
741 for (
int i = 0; i <
NET_MAX; i++) {
742 if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
779 std::array<uint8_t, PREFIX_BYTE_LENGTH> prefix_bytes;
781 return HexStr(prefix_bytes) +
"-";
786 const std::string& dest,
788 bool& proxy_connection_failed)
793 proxy_connection_failed =
true;
801 if (!
Socks5(dest, port, &random_auth, *sock)) {
805 if (!
Socks5(dest, port,
nullptr, *sock)) {
820 const size_t slash_pos{subnet_str.find_last_of(
'/')};
821 const std::string str_addr{subnet_str.substr(0, slash_pos)};
822 std::optional<CNetAddr> addr{
LookupHost(str_addr,
false)};
824 if (addr.has_value()) {
826 if (slash_pos != subnet_str.npos) {
827 const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
828 if (
const auto netmask{ToIntegral<uint8_t>(netmask_str)}) {
830 subnet =
CSubNet{addr.value(), *netmask};
833 const std::optional<CNetAddr> full_netmask{
LookupHost(netmask_str,
false)};
834 if (full_netmask.has_value()) {
835 subnet =
CSubNet{addr.value(), full_netmask.value()};
840 subnet =
CSubNet{addr.value()};
954 sockaddr_storage storage;
955 socklen_t len =
sizeof(storage);
957 auto sa =
reinterpret_cast<sockaddr*
>(&storage);
static constexpr size_t PREFIX_BYTE_LENGTH
Size of session prefix in bytes.
Tor: Onion service rendezvous failed.
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.
RFC1928: Connection refused.
const std::string m_prefix
SOCKS5Reply
Values defined for REP in RFC1928 and https://spec.torproject.org/socks-extensions.html.
const std::string ADDR_PREFIX_UNIX
Prefix for unix domain socket addresses (which are local filesystem paths)
std::unique_ptr< Sock > Connect() const
bool IsUnixSocketPath(const std::string &name)
Check if a string is a valid UNIX domain socket path.
bool SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
Set CService from a network sockaddr.
A set of addresses that represent the hash of a string or FQDN.
Dummy value to indicate the number of NET_* constants.
bool SplitHostPort(std::string_view in, uint16_t &portOut, std::string &hostOut)
Splits socket address string into host string and port value.
static bool ConnectToSocket(const Sock &sock, struct sockaddr *sockaddr, socklen_t len, const std::string &dest_str, bool manual_connection)
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.
Tor: Onion service descriptor can not be found.
RFC1928: Network unreachable.
bool GetProxy(enum Network net, Proxy &proxyInfoOut)
Tor: Onion service missing client authorization.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
CService MaybeFlipIPv6toCJDNS(const CService &service)
If an IPv6 address belongs to the address range used by the CJDNS network and the CJDNS network is re...
memcpy(result.begin(), stream.data(), stream.size())
bool SetProxy(enum Network net, const Proxy &addrProxy)
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 ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
std::atomic< uint64_t > m_counter
virtual ssize_t Recv(void *buf, size_t len, int flags) const
recv(2) wrapper.
#define WSAGetLastError()
bool m_tor_stream_isolation
List of reachable networks.
virtual bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const
Wait for readiness for input (recv) or output (send).
std::string ToStringAddrPort() const
No authentication required.
SOCKS5Command
Values defined for CMD in RFC1928.
static constexpr Event SEND
If passed to Wait(), then it will wait for readiness to send to the socket.
static Proxy proxyInfo [NET_MAX] GUARDED_BY(g_proxyinfo_mutex)
virtual int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const
getsockopt(2) wrapper.
static std::string GenerateUniquePrefix()
Generate a random prefix for each of the credentials returned by this generator.
bool IsBadPort(uint16_t port)
Determine if a port is "bad" from the perspective of attempting to connect to a node on that port...
void GetRandBytes(std::span< unsigned char > bytes) noexcept
Generate random data via the internal PRNG.
std::string m_unix_socket_path
Tor: Onion service introduction failed.
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 > WrappedGetAddrInfo(const std::string &name, bool allow_lookup)
Wrapper for getaddrinfo(3).
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.
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
A combination of a network address (CNetAddr) and a (TCP) port.
bool SetSpecial(std::string_view addr)
Parse a Tor or I2P address and set this object to it.
static void LogConnectFailure(bool manual_connection, util::ConstevalFormatString< sizeof...(Args)> fmt, const Args &... args)
static std::vector< CNetAddr > LookupIntern(const std::string &name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
bool SetNameProxy(const Proxy &addrProxy)
Set the name proxy to use for all connections to nodes specified by a hostname.
Generate unique credentials for Tor stream isolation.
Credentials for proxy authentication.
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
bool IsProxy(const CNetAddr &addr)
std::chrono::milliseconds g_socks5_recv_timeout
SOCKSVersion
SOCKS version.
RFC1928: General failure.
CThreadInterrupt g_socks5_interrupt
Interrupt SOCKS5 reads or writes.
Tor: Onion service introduction timed out.
static const int DEFAULT_NAME_LOOKUP
-dns default
A helper class for interruptible sleeps.
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
static std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to an error message.
std::vector< std::string > GetNetworkNames(bool append_unroutable)
Return a vector of publicly routable Network names; optionally append NET_UNROUTABLE.
SOCKS5Method
Values defined for METHOD in RFC1928.
enum Network ParseNetwork(const std::string &net_in)
std::string ToLower(std::string_view str)
Returns the lowercase equivalent of the given string.
bool GetNameProxy(Proxy &nameProxyOut)
CService GetBindAddress(const Sock &sock)
Get the bind address for a socket as CService.
#define LogDebug(category,...)
RFC1928: Network unreachable.
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 constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
std::function< std::vector< CNetAddr >(const std::string &, bool)> DNSLookupFn
TorStreamIsolationCredentialsGenerator()
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
Tor: Onion service wrong client authorization.
Tor: Onion service invalid address.
virtual void SendComplete(std::span< const unsigned char > data, std::chrono::milliseconds timeout, CThreadInterrupt &interrupt) const
Send the given data, retrying on transient errors.
Tor: Onion service descriptor is invalid.
RAII helper class that manages a socket and closes it automatically when it goes out of scope...
ProxyCredentials Generate()
Return the next unique proxy credentials.
RFC1928: Address type not supported.
RFC1928: Command not supported.
std::function< std::unique_ptr< Sock >int, int, int)> CreateSock
Socket factory.
RFC1928: Connection not allowed by ruleset.
Different type to mark Mutex at global scope.
std::string GetNetworkName(enum Network net)
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...
static GlobalMutex g_proxyinfo_mutex
sa_family_t GetSAFamily() const
Get the address family.
std::unique_ptr< Sock > CreateSockOS(int domain, int type, int protocol)
Create a real socket from the operating system.
virtual int GetSockName(sockaddr *name, socklen_t *name_len) const
getsockname(2) wrapper.
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
virtual int Connect(const sockaddr *addr, socklen_t addr_len) const
connect(2) wrapper.
static constexpr auto MAX_WAIT_FOR_IO
Maximum time to wait for I/O readiness.
CSubNet LookupSubNet(const std::string &subnet_str)
Parse and resolve a specified subnet string into the appropriate internal representation.
ReachableNets g_reachable_nets
Addresses from these networks are not publicly routable on the global Internet.