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);
106 LogPrintf(
"Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
112 if (net ==
"cjdns") {
136 std::vector<std::string> names;
137 for (
int n = 0; n <
NET_MAX; ++n) {
142 if (append_unroutable) {
148 static std::vector<CNetAddr>
LookupIntern(
const std::string&
name,
unsigned int nMaxSolutions,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
162 std::vector<CNetAddr> addresses;
164 for (
const CNetAddr& resolved : dns_lookup_function(
name, fAllowLookup)) {
165 if (nMaxSolutions > 0 && addresses.size() >= nMaxSolutions) {
169 if (!resolved.IsInternal()) {
170 addresses.push_back(resolved);
177 std::vector<CNetAddr>
LookupHost(
const std::string&
name,
unsigned int nMaxSolutions,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
180 std::string strHost =
name;
181 if (strHost.empty())
return {};
182 if (strHost.front() ==
'[' && strHost.back() ==
']') {
183 strHost = strHost.substr(1, strHost.size() - 2);
186 return LookupIntern(strHost, nMaxSolutions, fAllowLookup, dns_lookup_function);
191 const std::vector<CNetAddr> addresses{
LookupHost(
name, 1, fAllowLookup, dns_lookup_function)};
192 return addresses.empty() ? std::nullopt : std::make_optional(addresses.front());
195 std::vector<CService>
Lookup(
const std::string&
name, uint16_t portDefault,
bool fAllowLookup,
unsigned int nMaxSolutions,
DNSLookupFn dns_lookup_function)
200 uint16_t port{portDefault};
201 std::string hostname;
204 const std::vector<CNetAddr> addresses{
LookupIntern(hostname, nMaxSolutions, fAllowLookup, dns_lookup_function)};
205 if (addresses.empty())
return {};
206 std::vector<CService> services;
207 services.reserve(addresses.size());
208 for (
const auto& addr : addresses)
209 services.emplace_back(addr, port);
213 std::optional<CService>
Lookup(
const std::string&
name, uint16_t portDefault,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
215 const std::vector<CService> services{
Lookup(
name, portDefault, fAllowLookup, 1, dns_lookup_function)};
217 return services.empty() ? std::nullopt : std::make_optional(services.front());
232 #ifdef HAVE_SOCKADDR_UN 240 if (str.size() + 1 >
sizeof(((sockaddr_un*)
nullptr)->sun_path))
return false;
316 auto curTime{Now<SteadyMilliseconds>()};
317 const auto endTime{curTime + timeout};
318 while (len > 0 && curTime < endTime) {
319 ssize_t
ret = sock.
Recv(data, len, 0);
323 }
else if (
ret == 0) {
330 const auto remaining = std::chrono::milliseconds{endTime - curTime};
331 const auto timeout = std::min(remaining, std::chrono::milliseconds{
MAX_WAIT_FOR_IO});
342 curTime = Now<SteadyMilliseconds>();
352 return "general failure";
354 return "connection not allowed";
356 return "network unreachable";
358 return "host unreachable";
360 return "connection refused";
362 return "TTL expired";
364 return "protocol error";
366 return "address type not supported";
377 if (strDest.size() > 255) {
382 std::vector<uint8_t> vSocks5Init;
385 vSocks5Init.push_back(0x02);
389 vSocks5Init.push_back(0x01);
395 LogPrintf(
"Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
399 LogError(
"Proxy failed to initialize\n");
404 std::vector<uint8_t> vAuth;
405 vAuth.push_back(0x01);
407 LogError(
"Proxy username or password too long\n");
410 vAuth.push_back(auth->
username.size());
412 vAuth.push_back(auth->
password.size());
418 LogError(
"Error reading proxy authentication response\n");
421 if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
422 LogError(
"Proxy authentication unsuccessful\n");
428 LogError(
"Proxy requested wrong authentication method %02x\n", pchRet1[1]);
431 std::vector<uint8_t> vSocks5;
434 vSocks5.push_back(0x00);
436 vSocks5.push_back(strDest.size());
437 vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
438 vSocks5.push_back((port >> 8) & 0xFF);
439 vSocks5.push_back((port >> 0) & 0xFF);
449 LogError(
"Error while reading proxy response\n");
454 LogError(
"Proxy failed to accept request\n");
460 "Socks5() connect to %s:%d failed: %s\n", strDest, port,
Socks5ErrorString(pchRet2[1]));
463 if (pchRet2[2] != 0x00) {
464 LogError(
"Error: malformed proxy response\n");
467 uint8_t pchRet3[256];
468 switch (pchRet2[3]) {
474 LogError(
"Error reading from proxy\n");
477 int nRecv = pchRet3[0];
482 LogError(
"Error: malformed proxy response\n");
487 LogError(
"Error reading from proxy\n");
491 LogError(
"Error reading from proxy\n");
496 }
catch (
const std::runtime_error& e) {
497 LogError(
"Error during SOCKS5 proxy handshake: %s\n", e.what());
505 if (domain == AF_UNSPEC)
return nullptr;
508 SOCKET hSocket = socket(domain, type, protocol);
513 auto sock = std::make_unique<Sock>(hSocket);
515 if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
521 if (!sock->IsSelectable()) {
522 LogPrintf(
"Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
530 if (sock->SetSockOpt(SOL_SOCKET, SO_NOSIGPIPE, (
void*)&
set,
sizeof(
int)) ==
SOCKET_ERROR) {
531 LogPrintf(
"Error setting SO_NOSIGPIPE on socket: %s, continuing anyway\n",
537 if (!sock->SetNonBlocking()) {
542 #ifdef HAVE_SOCKADDR_UN 543 if (domain == AF_UNIX)
return sock;
546 if (protocol == IPPROTO_TCP) {
549 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
550 LogPrint(
BCLog::NET,
"Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n");
559 template<
typename... Args>
562 if (manual_connection) {
569 static bool ConnectToSocket(
const Sock& sock,
struct sockaddr* sockaddr, socklen_t len,
const std::string& dest_str,
bool manual_connection)
582 if (!sock.
Wait(std::chrono::milliseconds{nConnectTimeout}, requested, &occurred)) {
583 LogPrintf(
"wait for connect to %s failed: %s\n",
587 }
else if (occurred == 0) {
597 socklen_t sockerr_len =
sizeof(sockerr);
605 "connect() to %s failed after wait: %s",
633 struct sockaddr_storage sockaddr;
634 socklen_t len =
sizeof(sockaddr);
635 if (!dest.
GetSockAddr((
struct sockaddr*)&sockaddr, &len)) {
653 #ifdef HAVE_SOCKADDR_UN 654 auto sock =
CreateSock(AF_UNIX, SOCK_STREAM, 0);
662 struct sockaddr_un addrun;
663 memset(&addrun, 0,
sizeof(addrun));
664 addrun.sun_family = AF_UNIX;
666 memcpy(addrun.sun_path, path.c_str(), std::min(
sizeof(addrun.sun_path) - 1, path.length()));
667 socklen_t len =
sizeof(addrun);
669 if(!
ConnectToSocket(*sock, (
struct sockaddr*)&addrun, len, path,
true)) {
684 proxyInfo[net] = addrProxy;
691 if (!proxyInfo[net].IsValid())
693 proxyInfoOut = proxyInfo[net];
701 nameProxy = addrProxy;
707 if(!nameProxy.IsValid())
709 nameProxyOut = nameProxy;
715 return nameProxy.IsValid();
720 for (
int i = 0; i <
NET_MAX; i++) {
721 if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
728 const std::string& dest,
730 bool& proxy_connection_failed)
735 proxy_connection_failed =
true;
742 static std::atomic_int counter(0);
744 if (!
Socks5(dest, port, &random_auth, *sock)) {
748 if (!
Socks5(dest, port,
nullptr, *sock)) {
763 const size_t slash_pos{subnet_str.find_last_of(
'/')};
764 const std::string str_addr{subnet_str.substr(0, slash_pos)};
765 std::optional<CNetAddr> addr{
LookupHost(str_addr,
false)};
767 if (addr.has_value()) {
769 if (slash_pos != subnet_str.npos) {
770 const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
774 subnet =
CSubNet{addr.value(), netmask};
777 const std::optional<CNetAddr> full_netmask{
LookupHost(netmask_str,
false)};
778 if (full_netmask.has_value()) {
779 subnet =
CSubNet{addr.value(), full_netmask.value()};
784 subnet =
CSubNet{addr.value()};
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.
SOCKS5Reply
Values defined for REP in RFC1928.
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.
#define LogPrint(category,...)
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.
virtual void SendComplete(Span< const unsigned char > data, std::chrono::milliseconds timeout, CThreadInterrupt &interrupt) const
Send the given data, retrying on transient errors.
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.
static void LogConnectFailure(bool manual_connection, const char *fmt, const Args &... args)
bool GetProxy(enum Network net, Proxy &proxyInfoOut)
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...
bool SetProxy(enum Network net, const Proxy &addrProxy)
bool SetSpecial(const std::string &addr)
Parse a Tor or I2P address and set this object to it.
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.
virtual ssize_t Recv(void *buf, size_t len, int flags) const
recv(2) wrapper.
#define WSAGetLastError()
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.
bool m_randomize_credentials
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::string m_unix_socket_path
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.
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.
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.
bool ParseUInt8(std::string_view str, uint8_t *out)
Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
#define LogPrintLevel(category, level,...)
CThreadInterrupt g_socks5_interrupt
Interrupt SOCKS5 reads or writes.
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)
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
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
RAII helper class that manages a socket and closes it automatically when it goes out of scope...
Address type not supported.
std::function< std::unique_ptr< Sock >int, int, int)> CreateSock
Socket factory.
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.
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
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.