diff options
-rw-r--r-- | src/net.cpp | 2 | ||||
-rw-r--r-- | src/netbase.cpp | 18 | ||||
-rw-r--r-- | src/netbase.h | 39 | ||||
-rw-r--r-- | src/rpc/net.cpp | 2 |
4 files changed, 55 insertions, 6 deletions
diff --git a/src/net.cpp b/src/net.cpp index 345c1c8b4b..2cc85aa488 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -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) diff --git a/src/netbase.cpp b/src/netbase.cpp index 93a84a73b0..d3c3c36b37 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -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, diff --git a/src/netbase.h b/src/netbase.h index c54056d25c..e3b7da470c 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -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 */ diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 5e6f42b596..be07e6c2d5 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -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); } |