41 ai_hint.ai_socktype = SOCK_STREAM;
42 ai_hint.ai_protocol = IPPROTO_TCP;
44 ai_hint.ai_family = AF_UNSPEC;
51 ai_hint.ai_flags = allow_lookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
53 addrinfo* ai_res{
nullptr};
54 const int n_err{getaddrinfo(
name.c_str(),
nullptr, &ai_hint, &ai_res)};
60 addrinfo* ai_trav{ai_res};
61 std::vector<CNetAddr> resolved_addresses;
62 while (ai_trav !=
nullptr) {
63 if (ai_trav->ai_family == AF_INET) {
64 assert(ai_trav->ai_addrlen >=
sizeof(sockaddr_in));
65 resolved_addresses.emplace_back(reinterpret_cast<sockaddr_in*>(ai_trav->ai_addr)->sin_addr);
67 if (ai_trav->ai_family == AF_INET6) {
68 assert(ai_trav->ai_addrlen >=
sizeof(sockaddr_in6));
69 const sockaddr_in6* s6{
reinterpret_cast<sockaddr_in6*
>(ai_trav->ai_addr)};
70 resolved_addresses.emplace_back(s6->sin6_addr, s6->sin6_scope_id);
72 ai_trav = ai_trav->ai_next;
76 return resolved_addresses;
82 std::string net =
ToLower(net_in);
87 LogPrintf(
"Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
117 std::vector<std::string> names;
118 for (
int n = 0; n <
NET_MAX; ++n) {
123 if (append_unroutable) {
129 static std::vector<CNetAddr>
LookupIntern(
const std::string&
name,
unsigned int nMaxSolutions,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
143 std::vector<CNetAddr> addresses;
145 for (
const CNetAddr& resolved : dns_lookup_function(
name, fAllowLookup)) {
146 if (nMaxSolutions > 0 && addresses.size() >= nMaxSolutions) {
150 if (!resolved.IsInternal()) {
151 addresses.push_back(resolved);
158 std::vector<CNetAddr>
LookupHost(
const std::string&
name,
unsigned int nMaxSolutions,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
161 std::string strHost =
name;
162 if (strHost.empty())
return {};
163 if (strHost.front() ==
'[' && strHost.back() ==
']') {
164 strHost = strHost.substr(1, strHost.size() - 2);
167 return LookupIntern(strHost, nMaxSolutions, fAllowLookup, dns_lookup_function);
172 const std::vector<CNetAddr> addresses{
LookupHost(
name, 1, fAllowLookup, dns_lookup_function)};
173 return addresses.empty() ? std::nullopt : std::make_optional(addresses.front());
176 std::vector<CService>
Lookup(
const std::string&
name, uint16_t portDefault,
bool fAllowLookup,
unsigned int nMaxSolutions,
DNSLookupFn dns_lookup_function)
181 uint16_t port{portDefault};
182 std::string hostname;
185 const std::vector<CNetAddr> addresses{
LookupIntern(hostname, nMaxSolutions, fAllowLookup, dns_lookup_function)};
186 if (addresses.empty())
return {};
187 std::vector<CService> services;
188 services.reserve(addresses.size());
189 for (
const auto& addr : addresses)
190 services.emplace_back(addr, port);
194 std::optional<CService>
Lookup(
const std::string&
name, uint16_t portDefault,
bool fAllowLookup,
DNSLookupFn dns_lookup_function)
196 const std::vector<CService> services{
Lookup(
name, portDefault, fAllowLookup, 1, dns_lookup_function)};
198 return services.empty() ? std::nullopt : std::make_optional(services.front());
279 auto curTime{Now<SteadyMilliseconds>()};
280 const auto endTime{curTime + timeout};
281 while (len > 0 && curTime < endTime) {
282 ssize_t
ret = sock.
Recv(data, len, 0);
286 }
else if (
ret == 0) {
293 const auto remaining = std::chrono::milliseconds{endTime - curTime};
294 const auto timeout = std::min(remaining, std::chrono::milliseconds{
MAX_WAIT_FOR_IO});
304 curTime = Now<SteadyMilliseconds>();
314 return "general failure";
316 return "connection not allowed";
318 return "network unreachable";
320 return "host unreachable";
322 return "connection refused";
324 return "TTL expired";
326 return "protocol error";
328 return "address type not supported";
338 if (strDest.size() > 255) {
339 return error(
"Hostname too long");
342 std::vector<uint8_t> vSocks5Init;
345 vSocks5Init.push_back(0x02);
349 vSocks5Init.push_back(0x01);
353 if (
ret != (ssize_t)vSocks5Init.size()) {
354 return error(
"Error sending to proxy");
358 LogPrintf(
"Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
362 return error(
"Proxy failed to initialize");
366 std::vector<uint8_t> vAuth;
367 vAuth.push_back(0x01);
369 return error(
"Proxy username or password too long");
370 vAuth.push_back(auth->
username.size());
372 vAuth.push_back(auth->
password.size());
375 if (
ret != (ssize_t)vAuth.size()) {
376 return error(
"Error sending authentication to proxy");
381 return error(
"Error reading proxy authentication response");
383 if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
384 return error(
"Proxy authentication unsuccessful");
389 return error(
"Proxy requested wrong authentication method %02x", pchRet1[1]);
391 std::vector<uint8_t> vSocks5;
394 vSocks5.push_back(0x00);
396 vSocks5.push_back(strDest.size());
397 vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
398 vSocks5.push_back((port >> 8) & 0xFF);
399 vSocks5.push_back((port >> 0) & 0xFF);
401 if (
ret != (ssize_t)vSocks5.size()) {
402 return error(
"Error sending to proxy");
412 return error(
"Error while reading proxy response");
416 return error(
"Proxy failed to accept request");
423 if (pchRet2[2] != 0x00) {
424 return error(
"Error: malformed proxy response");
426 uint8_t pchRet3[256];
435 return error(
"Error reading from proxy");
437 int nRecv = pchRet3[0];
441 default:
return error(
"Error: malformed proxy response");
444 return error(
"Error reading from proxy");
447 return error(
"Error reading from proxy");
456 struct sockaddr_storage sockaddr;
457 socklen_t len =
sizeof(sockaddr);
458 if (!address_family.
GetSockAddr((
struct sockaddr*)&sockaddr, &len)) {
464 SOCKET hSocket = socket(((
struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
469 auto sock = std::make_unique<Sock>(hSocket);
473 if (!sock->IsSelectable()) {
474 LogPrintf(
"Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
482 if (sock->SetSockOpt(SOL_SOCKET, SO_NOSIGPIPE, (
void*)&
set,
sizeof(
int)) ==
SOCKET_ERROR) {
483 LogPrintf(
"Error setting SO_NOSIGPIPE on socket: %s, continuing anyway\n",
490 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
491 LogPrint(
BCLog::NET,
"Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n");
495 if (!sock->SetNonBlocking()) {
504 template<
typename... Args>
507 if (manual_connection) {
517 struct sockaddr_storage sockaddr;
518 socklen_t len =
sizeof(sockaddr);
519 if (!addrConnect.
GetSockAddr((
struct sockaddr*)&sockaddr, &len)) {
535 if (!sock.
Wait(std::chrono::milliseconds{nTimeout}, requested, &occurred)) {
536 LogPrintf(
"wait for connect to %s failed: %s\n",
540 }
else if (occurred == 0) {
550 socklen_t sockerr_len =
sizeof(sockerr);
558 "connect() to %s failed after wait: %s",
582 proxyInfo[net] = addrProxy;
589 if (!proxyInfo[net].IsValid())
591 proxyInfoOut = proxyInfo[net];
599 nameProxy = addrProxy;
605 if(!nameProxy.IsValid())
607 nameProxyOut = nameProxy;
613 return nameProxy.IsValid();
618 for (
int i = 0; i <
NET_MAX; i++) {
619 if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
625 bool ConnectThroughProxy(
const Proxy& proxy,
const std::string& strDest, uint16_t port,
const Sock& sock,
int nTimeout,
bool& outProxyConnectionFailed)
629 outProxyConnectionFailed =
true;
635 static std::atomic_int counter(0);
637 if (!
Socks5(strDest, port, &random_auth, sock)) {
641 if (!
Socks5(strDest, port,
nullptr, sock)) {
654 const size_t slash_pos{subnet_str.find_last_of(
'/')};
655 const std::string str_addr{subnet_str.substr(0, slash_pos)};
656 std::optional<CNetAddr> addr{
LookupHost(str_addr,
false)};
658 if (addr.has_value()) {
660 if (slash_pos != subnet_str.npos) {
661 const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
665 subnet_out =
CSubNet{addr.value(), netmask};
669 const std::optional<CNetAddr> full_netmask{
LookupHost(netmask_str,
false)};
670 if (full_netmask.has_value()) {
671 subnet_out =
CSubNet{addr.value(), full_netmask.value()};
677 subnet_out =
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.
#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 randomize_credentials
bool SplitHostPort(std::string_view in, uint16_t &portOut, std::string &hostOut)
Splits socket address string into host string and port value.
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 ConnectThroughProxy(const Proxy &proxy, const std::string &strDest, uint16_t port, const Sock &sock, int nTimeout, bool &outProxyConnectionFailed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
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.
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::unique_ptr< Sock > CreateSockTCP(const CService &address_family)
Create a TCP socket in the given address family.
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 IsBadPort(uint16_t port)
Determine if a port is "bad" from the perspective of attempting to connect to a node on that port...
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
bool ConnectSocketDirectly(const CService &addrConnect, const Sock &sock, int nTimeout, bool manual_connection)
Try to connect to the specified service on the specified socket.
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.
virtual ssize_t Send(const void *data, size_t len, int flags) const
send(2) wrapper.
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.
static std::atomic< bool > interruptSocks5Recv(false)
static const int DEFAULT_NAME_LOOKUP
-dns default
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
bool error(const char *fmt, const Args &... args)
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
bool LookupSubNet(const std::string &subnet_str, CSubNet &subnet_out)
Parse and resolve a specified subnet string into the appropriate internal representation.
void InterruptSocks5(bool interrupt)
RAII helper class that manages a socket and closes it automatically when it goes out of scope...
std::function< std::unique_ptr< Sock >const CService &)> CreateSock
Socket factory.
Address type not supported.
Connection not allowed by ruleset.
Different type to mark Mutex at global scope.
std::string GetNetworkName(enum Network net)
static GlobalMutex g_proxyinfo_mutex
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.
ReachableNets g_reachable_nets
Addresses from these networks are not publicly routable on the global Internet.