6#include <bitcoin-build-config.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);
 
  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) {
 
  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);
 
  177std::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());
 
  195std::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);
 
  213std::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;
 
  324    auto curTime{Now<SteadyMilliseconds>()};
 
  325    const auto endTime{curTime + timeout};
 
  326    while (len > 0 && curTime < endTime) {
 
  331        } 
else if (
ret == 0) { 
 
  338                const auto remaining = std::chrono::milliseconds{endTime - curTime};
 
  339                const auto timeout = std::min(remaining, std::chrono::milliseconds{
MAX_WAIT_FOR_IO});
 
  350        curTime = Now<SteadyMilliseconds>();
 
  360            return "general failure";
 
  362            return "connection not allowed";
 
  364            return "network unreachable";
 
  366            return "host unreachable";
 
  368            return "connection refused";
 
  370            return "TTL expired";
 
  372            return "protocol error";
 
  374            return "address type not supported";
 
  376            return "onion service descriptor can not be found";
 
  378            return "onion service descriptor is invalid";
 
  380            return "onion service introduction failed";
 
  382            return "onion service rendezvous failed";
 
  384            return "onion service missing client authorization";
 
  386            return "onion service wrong client authorization";
 
  388            return "onion service invalid address";
 
  390            return "onion service introduction timed out";
 
  392            return strprintf(
"unknown (0x%02x)", err);
 
  401        if (strDest.size() > 255) {
 
  406        std::vector<uint8_t> vSocks5Init;
 
  409            vSocks5Init.push_back(0x02); 
 
  413            vSocks5Init.push_back(0x01); 
 
  419            LogPrintf(
"Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
 
  423            LogError(
"Proxy failed to initialize\n");
 
  428            std::vector<uint8_t> vAuth;
 
  429            vAuth.push_back(0x01); 
 
  431                LogError(
"Proxy username or password too long\n");
 
  434            vAuth.push_back(auth->
username.size());
 
  436            vAuth.push_back(auth->
password.size());
 
  442                LogError(
"Error reading proxy authentication response\n");
 
  445            if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
 
  446                LogError(
"Proxy authentication unsuccessful\n");
 
  452            LogError(
"Proxy requested wrong authentication method %02x\n", pchRet1[1]);
 
  455        std::vector<uint8_t> vSocks5;
 
  458        vSocks5.push_back(0x00);                   
 
  460        vSocks5.push_back(strDest.size());         
 
  461        vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
 
  462        vSocks5.push_back((port >> 8) & 0xFF);
 
  463        vSocks5.push_back((port >> 0) & 0xFF);
 
  473                LogError(
"Error while reading proxy response\n");
 
  478            LogError(
"Proxy failed to accept request\n");
 
  484                          "Socks5() connect to %s:%d failed: %s\n", strDest, port, 
Socks5ErrorString(pchRet2[1]));
 
  487        if (pchRet2[2] != 0x00) { 
 
  488            LogError(
"Error: malformed proxy response\n");
 
  491        uint8_t pchRet3[256];
 
  492        switch (pchRet2[3]) {
 
  498                LogError(
"Error reading from proxy\n");
 
  501            int nRecv = pchRet3[0];
 
  506            LogError(
"Error: malformed proxy response\n");
 
  511            LogError(
"Error reading from proxy\n");
 
  515            LogError(
"Error reading from proxy\n");
 
  520    } 
catch (
const std::runtime_error& e) {
 
  521        LogError(
"Error during SOCKS5 proxy handshake: %s\n", e.what());
 
  529    if (domain == AF_UNSPEC) 
return nullptr;
 
  532    SOCKET hSocket = socket(domain, type, protocol);
 
  537    auto sock = std::make_unique<Sock>(hSocket);
 
  539    if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
 
  545    if (!sock->IsSelectable()) {
 
  546        LogPrintf(
"Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
 
  554    if (sock->SetSockOpt(SOL_SOCKET, SO_NOSIGPIPE, &set, 
sizeof(
int)) == 
SOCKET_ERROR) {
 
  555        LogPrintf(
"Error setting SO_NOSIGPIPE on socket: %s, continuing anyway\n",
 
  561    if (!sock->SetNonBlocking()) {
 
  566#ifdef HAVE_SOCKADDR_UN 
  567    if (domain == AF_UNIX) 
return sock;
 
  570    if (protocol == IPPROTO_TCP) {
 
  573        if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, 
sizeof(on)) == 
SOCKET_ERROR) {
 
  574            LogDebug(
BCLog::NET, 
"Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n");
 
  583template<
typename... Args>
 
  587    if (manual_connection) {
 
  594static bool ConnectToSocket(
const Sock& sock, 
struct sockaddr* sockaddr, socklen_t len, 
const std::string& dest_str, 
bool manual_connection)
 
  607            if (!sock.
Wait(std::chrono::milliseconds{nConnectTimeout}, requested, &occurred)) {
 
  608                LogPrintf(
"wait for connect to %s failed: %s\n",
 
  612            } 
else if (occurred == 0) {
 
  622            socklen_t sockerr_len = 
sizeof(sockerr);
 
  623            if (sock.
GetSockOpt(SOL_SOCKET, SO_ERROR, &sockerr, &sockerr_len) ==
 
  630                                  "connect() to %s failed after wait: %s",
 
  658    struct sockaddr_storage sockaddr;
 
  659    socklen_t len = 
sizeof(sockaddr);
 
  660    if (!dest.
GetSockAddr((
struct sockaddr*)&sockaddr, &len)) {
 
  678#ifdef HAVE_SOCKADDR_UN 
  679    auto sock = 
CreateSock(AF_UNIX, SOCK_STREAM, 0);
 
  687    struct sockaddr_un addrun;
 
  688    memset(&addrun, 0, 
sizeof(addrun));
 
  689    addrun.sun_family = AF_UNIX;
 
  691    memcpy(addrun.sun_path, path.c_str(), std::min(
sizeof(addrun.sun_path) - 1, path.length()));
 
  692    socklen_t len = 
sizeof(addrun);
 
  694    if(!
ConnectToSocket(*sock, (
struct sockaddr*)&addrun, len, path, 
true)) {
 
  709    proxyInfo[net] = addrProxy;
 
  716    if (!proxyInfo[net].IsValid())
 
  718    proxyInfoOut = proxyInfo[net];
 
  726    nameProxy = addrProxy;
 
  732    if(!nameProxy.IsValid())
 
  734    nameProxyOut = nameProxy;
 
  740    return nameProxy.IsValid();
 
  745    for (
int i = 0; i < 
NET_MAX; i++) {
 
  746        if (addr == 
static_cast<CNetAddr>(proxyInfo[i].proxy))
 
  783        std::array<uint8_t, PREFIX_BYTE_LENGTH> prefix_bytes;
 
  785        return HexStr(prefix_bytes) + 
"-";
 
  790                                          const std::string& dest,
 
  792                                          bool& proxy_connection_failed)
 
  797        proxy_connection_failed = 
true;
 
  805        if (!
Socks5(dest, port, &random_auth, *sock)) {
 
  809        if (!
Socks5(dest, port, 
nullptr, *sock)) {
 
  824    const size_t slash_pos{subnet_str.find_last_of(
'/')};
 
  825    const std::string str_addr{subnet_str.substr(0, slash_pos)};
 
  826    std::optional<CNetAddr> addr{
LookupHost(str_addr, 
false)};
 
  828    if (addr.has_value()) {
 
  830        if (slash_pos != subnet_str.npos) {
 
  831            const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
 
  832            if (
const auto netmask{ToIntegral<uint8_t>(netmask_str)}) {
 
  834                subnet = 
CSubNet{addr.value(), *netmask};
 
  837                const std::optional<CNetAddr> full_netmask{
LookupHost(netmask_str, 
false)};
 
  838                if (full_netmask.has_value()) {
 
  839                    subnet = 
CSubNet{addr.value(), full_netmask.value()};
 
  844            subnet = 
CSubNet{addr.value()};
 
bool SetSpecial(std::string_view 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
A helper class for interruptible sleeps.
Different type to mark Mutex at global scope.
std::unique_ptr< Sock > Connect() const
bool m_tor_stream_isolation
std::string m_unix_socket_path
List of reachable networks.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
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).
virtual void SendComplete(std::span< const unsigned char > data, std::chrono::milliseconds timeout, CThreadInterrupt &interrupt) const
Send the given data, retrying on transient errors.
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.
Generate unique credentials for Tor stream isolation.
std::atomic< uint64_t > m_counter
TorStreamIsolationCredentialsGenerator()
ProxyCredentials Generate()
Return the next unique proxy credentials.
const std::string m_prefix
static std::string GenerateUniquePrefix()
Generate a random prefix for each of the credentials returned by this generator.
static constexpr size_t PREFIX_BYTE_LENGTH
Size of session prefix in bytes.
#define WSAGetLastError()
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
#define LogPrintLevel(category, level,...)
#define LogDebug(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.
CSubNet LookupSubNet(const std::string &subnet_str)
Parse and resolve a specified subnet string into the appropriate internal representation.
SOCKS5Command
Values defined for CMD in RFC1928.
static void LogConnectFailure(bool manual_connection, util::ConstevalFormatString< sizeof...(Args)> fmt, const Args &... args)
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 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.
CThreadInterrupt g_socks5_interrupt
Interrupt SOCKS5 reads or writes.
SOCKSVersion
SOCKS version.
bool SetNameProxy(const Proxy &addrProxy)
Set the name proxy to use for all connections to nodes specified by a hostname.
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.
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 and https://spec.torproject.org/socks-extensions....
@ TTLEXPIRED
RFC1928: TTL expired.
@ CMDUNSUPPORTED
RFC1928: Command not supported.
@ TOR_HS_WRONG_CLIENT_AUTH
Tor: Onion service wrong client authorization.
@ TOR_HS_DESC_INVALID
Tor: Onion service descriptor is invalid.
@ NETUNREACHABLE
RFC1928: Network unreachable.
@ GENFAILURE
RFC1928: General failure.
@ TOR_HS_MISSING_CLIENT_AUTH
Tor: Onion service missing client authorization.
@ CONNREFUSED
RFC1928: Connection refused.
@ TOR_HS_BAD_ADDRESS
Tor: Onion service invalid address.
@ SUCCEEDED
RFC1928: Succeeded.
@ ATYPEUNSUPPORTED
RFC1928: Address type not supported.
@ NOTALLOWED
RFC1928: Connection not allowed by ruleset.
@ TOR_HS_INTRO_FAILED
Tor: Onion service introduction failed.
@ TOR_HS_DESC_NOT_FOUND
Tor: Onion service descriptor can not be found.
@ HOSTUNREACHABLE
RFC1928: Network unreachable.
@ TOR_HS_INTRO_TIMEOUT
Tor: Onion service introduction timed out.
@ TOR_HS_REND_FAILED
Tor: Onion service rendezvous failed.
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...
static GlobalMutex g_proxyinfo_mutex
ReachableNets g_reachable_nets
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 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
void GetRandBytes(std::span< unsigned char > bytes) noexcept
Generate random data via the internal PRNG.
@ 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 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.