aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/net.cpp15
-rw-r--r--src/rpc/blockchain.cpp4
-rw-r--r--src/test/fuzz/util.cpp53
-rw-r--r--src/test/fuzz/util.h6
-rw-r--r--src/test/util/net.h10
-rw-r--r--src/util/sock.cpp15
-rw-r--r--src/util/sock.h19
7 files changed, 112 insertions, 10 deletions
diff --git a/src/net.cpp b/src/net.cpp
index c05fa771ef..7f4e571c8d 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -422,13 +422,13 @@ bool CConnman::CheckIncomingNonce(uint64_t nonce)
}
/** Get the bind address for a socket as CAddress */
-static CAddress GetBindAddress(SOCKET sock)
+static CAddress GetBindAddress(const Sock& sock)
{
CAddress addr_bind;
struct sockaddr_storage sockaddr_bind;
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
- if (sock != INVALID_SOCKET) {
- if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
+ if (sock.Get() != INVALID_SOCKET) {
+ if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
} else {
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
@@ -540,7 +540,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
if (!addr_bind.IsValid()) {
- addr_bind = GetBindAddress(sock->Get());
+ addr_bind = GetBindAddress(*sock);
}
CNode* pnode = new CNode(id,
nLocalServices,
@@ -1154,7 +1154,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
}
- const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(sock->Get())), NODE_NONE};
+ const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock)), NODE_NONE};
NetPermissionFlags permissionFlags = NetPermissionFlags::None;
hListenSocket.AddSocketPermissionFlags(permissionFlags);
@@ -2323,8 +2323,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
#endif
}
- if (::bind(sock->Get(), (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
- {
+ if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE)
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
@@ -2336,7 +2335,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
LogPrintf("Bound to %s\n", addrBind.ToString());
// Listen for incoming connections
- if (listen(sock->Get(), SOMAXCONN) == SOCKET_ERROR)
+ if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)
{
strError = strprintf(_("Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 9766a237c7..af9458206e 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2177,7 +2177,7 @@ static RPCHelpMan getblockfilter()
"\nRetrieve a BIP 157 content filter for a particular block.\n",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"},
- {"filtertype", RPCArg::Type::STR, RPCArg::Default{"basic"}, "The type name of the filter"},
+ {"filtertype", RPCArg::Type::STR, RPCArg::Default{BlockFilterTypeName(BlockFilterType::BASIC)}, "The type name of the filter"},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -2192,7 +2192,7 @@ static RPCHelpMan getblockfilter()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
uint256 block_hash = ParseHashV(request.params[0], "blockhash");
- std::string filtertype_name = "basic";
+ std::string filtertype_name = BlockFilterTypeName(BlockFilterType::BASIC);
if (!request.params[1].isNull()) {
filtertype_name = request.params[1].get_str();
}
diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp
index 8f5e771e37..4b893c648e 100644
--- a/src/test/fuzz/util.cpp
+++ b/src/test/fuzz/util.cpp
@@ -155,6 +155,45 @@ int FuzzedSock::Connect(const sockaddr*, socklen_t) const
return 0;
}
+int FuzzedSock::Bind(const sockaddr*, socklen_t) const
+{
+ // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
+ // SetFuzzedErrNo() will always set the global errno to bind_errnos[0]. We want to
+ // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
+ // repeatedly because proper code should retry on temporary errors, leading to an
+ // infinite loop.
+ constexpr std::array bind_errnos{
+ EACCES,
+ EADDRINUSE,
+ EADDRNOTAVAIL,
+ EAGAIN,
+ };
+ if (m_fuzzed_data_provider.ConsumeBool()) {
+ SetFuzzedErrNo(m_fuzzed_data_provider, bind_errnos);
+ return -1;
+ }
+ return 0;
+}
+
+int FuzzedSock::Listen(int) const
+{
+ // Have a permanent error at listen_errnos[0] because when the fuzzed data is exhausted
+ // SetFuzzedErrNo() will always set the global errno to listen_errnos[0]. We want to
+ // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
+ // repeatedly because proper code should retry on temporary errors, leading to an
+ // infinite loop.
+ constexpr std::array listen_errnos{
+ EADDRINUSE,
+ EINVAL,
+ EOPNOTSUPP,
+ };
+ if (m_fuzzed_data_provider.ConsumeBool()) {
+ SetFuzzedErrNo(m_fuzzed_data_provider, listen_errnos);
+ return -1;
+ }
+ return 0;
+}
+
std::unique_ptr<Sock> FuzzedSock::Accept(sockaddr* addr, socklen_t* addr_len) const
{
constexpr std::array accept_errnos{
@@ -201,6 +240,20 @@ int FuzzedSock::SetSockOpt(int, int, const void*, socklen_t) const
return 0;
}
+int FuzzedSock::GetSockName(sockaddr* name, socklen_t* name_len) const
+{
+ constexpr std::array getsockname_errnos{
+ ECONNRESET,
+ ENOBUFS,
+ };
+ if (m_fuzzed_data_provider.ConsumeBool()) {
+ SetFuzzedErrNo(m_fuzzed_data_provider, getsockname_errnos);
+ return -1;
+ }
+ *name_len = m_fuzzed_data_provider.ConsumeData(name, *name_len);
+ return 0;
+}
+
bool FuzzedSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
{
constexpr std::array wait_errnos{
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index 0819d326fd..4b89ad9bdc 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -61,12 +61,18 @@ public:
int Connect(const sockaddr*, socklen_t) const override;
+ int Bind(const sockaddr*, socklen_t) const override;
+
+ int Listen(int backlog) const override;
+
std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
int SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt_len) const override;
+ int GetSockName(sockaddr* name, socklen_t* name_len) const override;
+
bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
diff --git a/src/test/util/net.h b/src/test/util/net.h
index edb45d7c8e..c5dbaeca3e 100644
--- a/src/test/util/net.h
+++ b/src/test/util/net.h
@@ -122,6 +122,10 @@ public:
int Connect(const sockaddr*, socklen_t) const override { return 0; }
+ int Bind(const sockaddr*, socklen_t) const override { return 0; }
+
+ int Listen(int) const override { return 0; }
+
std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override
{
if (addr != nullptr) {
@@ -147,6 +151,12 @@ public:
int SetSockOpt(int, int, const void*, socklen_t) const override { return 0; }
+ int GetSockName(sockaddr* name, socklen_t* name_len) const override
+ {
+ std::memset(name, 0x0, *name_len);
+ return 0;
+ }
+
bool Wait(std::chrono::milliseconds timeout,
Event requested,
Event* occurred = nullptr) const override
diff --git a/src/util/sock.cpp b/src/util/sock.cpp
index 1d44fbfdae..2588575d81 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -66,6 +66,16 @@ int Sock::Connect(const sockaddr* addr, socklen_t addr_len) const
return connect(m_socket, addr, addr_len);
}
+int Sock::Bind(const sockaddr* addr, socklen_t addr_len) const
+{
+ return bind(m_socket, addr, addr_len);
+}
+
+int Sock::Listen(int backlog) const
+{
+ return listen(m_socket, backlog);
+}
+
std::unique_ptr<Sock> Sock::Accept(sockaddr* addr, socklen_t* addr_len) const
{
#ifdef WIN32
@@ -102,6 +112,11 @@ int Sock::SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt
return setsockopt(m_socket, level, opt_name, static_cast<const char*>(opt_val), opt_len);
}
+int Sock::GetSockName(sockaddr* name, socklen_t* name_len) const
+{
+ return getsockname(m_socket, name, name_len);
+}
+
bool Sock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
{
// We need a `shared_ptr` owning `this` for `WaitMany()`, but don't want
diff --git a/src/util/sock.h b/src/util/sock.h
index 5ca5f1b91b..b854609c22 100644
--- a/src/util/sock.h
+++ b/src/util/sock.h
@@ -87,6 +87,18 @@ public:
[[nodiscard]] virtual int Connect(const sockaddr* addr, socklen_t addr_len) const;
/**
+ * bind(2) wrapper. Equivalent to `bind(this->Get(), addr, addr_len)`. Code that uses this
+ * wrapper can be unit tested if this method is overridden by a mock Sock implementation.
+ */
+ [[nodiscard]] virtual int Bind(const sockaddr* addr, socklen_t addr_len) const;
+
+ /**
+ * listen(2) wrapper. Equivalent to `listen(this->Get(), backlog)`. Code that uses this
+ * wrapper can be unit tested if this method is overridden by a mock Sock implementation.
+ */
+ [[nodiscard]] virtual int Listen(int backlog) const;
+
+ /**
* accept(2) wrapper. Equivalent to `std::make_unique<Sock>(accept(this->Get(), addr, addr_len))`.
* Code that uses this wrapper can be unit tested if this method is overridden by a mock Sock
* implementation.
@@ -114,6 +126,13 @@ public:
const void* opt_val,
socklen_t opt_len) const;
+ /**
+ * getsockname(2) wrapper. Equivalent to
+ * `getsockname(this->Get(), name, name_len)`. Code that uses this
+ * wrapper can be unit tested if this method is overridden by a mock Sock implementation.
+ */
+ [[nodiscard]] virtual int GetSockName(sockaddr* name, socklen_t* name_len) const;
+
using Event = uint8_t;
/**