netbase: extend Proxy class to wrap UNIX socket as well as TCP

This commit is contained in:
Matthew Zipkin 2023-05-26 14:21:43 -04:00
parent 3a7d6548ef
commit a89c3f59dc
No known key found for this signature in database
GPG Key ID: E7E2984B6289C93A
4 changed files with 55 additions and 6 deletions

View File

@ -483,7 +483,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
addr_bind = CAddress{conn.me, NODE_NONE};
}
} else if (use_proxy) {
LogPrintLevel(BCLog::PROXY, BCLog::Level::Debug, "Using proxy: %s to connect to %s:%s\n", proxy.proxy.ToStringAddrPort(), addrConnect.ToStringAddr(), addrConnect.GetPort());
LogPrintLevel(BCLog::PROXY, BCLog::Level::Debug, "Using proxy: %s to connect to %s:%s\n", proxy.ToString(), addrConnect.ToStringAddr(), addrConnect.GetPort());
sock = ConnectThroughProxy(proxy, addrConnect.ToStringAddr(), addrConnect.GetPort(), proxyConnectionFailed);
} else {
// no proxy needed (none set for target network)

View File

@ -216,6 +216,24 @@ CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupF
return Lookup(name, portDefault, /*fAllowLookup=*/false, dns_lookup_function).value_or(CService{});
}
bool IsUnixSocketPath(const std::string& name)
{
#if HAVE_SOCKADDR_UN
if (name.find(ADDR_PREFIX_UNIX) != 0) return false;
// Split off "unix:" prefix
std::string str{name.substr(ADDR_PREFIX_UNIX.length())};
// Path size limit is platform-dependent
// see https://manpages.ubuntu.com/manpages/xenial/en/man7/unix.7.html
if (str.size() + 1 > sizeof(((sockaddr_un*)nullptr)->sun_path)) return false;
return true;
#else
return false;
#endif
}
/** SOCKS version */
enum SOCKSVersion: uint8_t {
SOCKS4 = 0x04,

View File

@ -27,6 +27,9 @@ static const int DEFAULT_CONNECT_TIMEOUT = 5000;
//! -dns default
static const int DEFAULT_NAME_LOOKUP = true;
/** Prefix for unix domain socket addresses (which are local filesystem paths) */
const std::string ADDR_PREFIX_UNIX = "unix:";
enum class ConnectionDirection {
None = 0,
In = (1U << 0),
@ -43,16 +46,44 @@ static inline bool operator&(ConnectionDirection a, ConnectionDirection b) {
return (underlying(a) & underlying(b));
}
/**
* Check if a string is a valid UNIX domain socket path
*
* @param name The string provided by the user representing a local path
*
* @returns Whether the string has proper format, length, and points to an existing file path
*/
bool IsUnixSocketPath(const std::string& name);
class Proxy
{
public:
Proxy(): randomize_credentials(false) {}
explicit Proxy(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), randomize_credentials(_randomize_credentials) {}
bool IsValid() const { return proxy.IsValid(); }
Proxy(): m_is_unix_socket(false), randomize_credentials(false) {}
explicit Proxy(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), m_is_unix_socket(false), randomize_credentials(_randomize_credentials) {}
explicit Proxy(const std::string path, bool _randomize_credentials=false): m_unix_socket_path(path), m_is_unix_socket(true), randomize_credentials(_randomize_credentials) {}
CService proxy;
std::string m_unix_socket_path;
bool m_is_unix_socket;
bool randomize_credentials;
bool IsValid() const
{
if (m_is_unix_socket) return IsUnixSocketPath(m_unix_socket_path);
return proxy.IsValid();
}
sa_family_t GetFamily() const
{
if (m_is_unix_socket) return AF_UNIX;
return proxy.GetSAFamily();
}
std::string ToString() const
{
if (m_is_unix_socket) return m_unix_socket_path;
return proxy.ToStringAddrPort();
}
};
/** Credentials for proxy authentication */

View File

@ -607,7 +607,7 @@ static UniValue GetNetworksInfo()
obj.pushKV("name", GetNetworkName(network));
obj.pushKV("limited", !g_reachable_nets.Contains(network));
obj.pushKV("reachable", g_reachable_nets.Contains(network));
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringAddrPort() : std::string());
obj.pushKV("proxy", proxy.IsValid() ? proxy.ToString() : std::string());
obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
networks.push_back(obj);
}