Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
gruve-p committed Jun 23, 2024
2 parents 98d6083 + 5383637 commit afc66ff
Show file tree
Hide file tree
Showing 26 changed files with 217 additions and 249 deletions.
2 changes: 1 addition & 1 deletion src/banman.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CSubNet;
// disk on shutdown and reloaded on startup. Banning can be used to
// prevent connections with spy nodes or other griefers.
//
// 2. Discouragement. If a peer misbehaves enough (see Misbehaving() in
// 2. Discouragement. If a peer misbehaves (see Misbehaving() in
// net_processing.cpp), we'll mark that address as discouraged. We still allow
// incoming connections from them, but they're preferred for eviction when
// we receive new incoming connections. We never make outgoing connections to
Expand Down
5 changes: 4 additions & 1 deletion src/mapport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,11 @@ static bool ProcessUpnp()
struct UPNPUrls urls;
struct IGDdatas data;
int r;

#if MINIUPNPC_API_VERSION <= 17
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
#else
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), nullptr, 0);
#endif
if (r == 1)
{
if (fDiscover) {
Expand Down
2 changes: 1 addition & 1 deletion src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3032,7 +3032,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
return false;
}

std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily());
std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP);
if (!sock) {
strError = strprintf(Untranslated("Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
Expand Down
176 changes: 62 additions & 114 deletions src/net_processing.cpp

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions src/net_processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ static const uint32_t DEFAULT_MAX_ORPHAN_TRANSACTIONS{100};
static const uint32_t DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN{100};
static const bool DEFAULT_PEERBLOOMFILTERS = true;
static const bool DEFAULT_PEERBLOCKFILTERS = false;
/** Threshold for marking a node to be discouraged, e.g. disconnected and added to the discouragement filter. */
static const int DISCOURAGEMENT_THRESHOLD{100};
/** Maximum number of outstanding CMPCTBLOCK requests for the same block. */
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK = 3;

Expand Down Expand Up @@ -108,7 +106,7 @@ class PeerManager : public CValidationInterface, public NetEventsInterface
virtual void SetBestBlock(int height, std::chrono::seconds time) = 0;

/* Public for unit testing. */
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch) = 0;
virtual void UnitTestMisbehaving(NodeId peer_id) = 0;

/**
* Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound.
Expand Down
34 changes: 18 additions & 16 deletions src/netbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,24 +487,23 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
}
}

std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family)
std::unique_ptr<Sock> CreateSockOS(int domain, int type, int protocol)
{
// Not IPv4, IPv6 or UNIX
if (address_family == AF_UNSPEC) return nullptr;

int protocol{IPPROTO_TCP};
#if HAVE_SOCKADDR_UN
if (address_family == AF_UNIX) protocol = 0;
#endif
if (domain == AF_UNSPEC) return nullptr;

// Create a socket in the specified address family.
SOCKET hSocket = socket(address_family, SOCK_STREAM, protocol);
SOCKET hSocket = socket(domain, type, protocol);
if (hSocket == INVALID_SOCKET) {
return nullptr;
}

auto sock = std::make_unique<Sock>(hSocket);

if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
return sock;
}

// Ensure that waiting for I/O on this socket won't result in undefined
// behavior.
if (!sock->IsSelectable()) {
Expand All @@ -529,18 +528,21 @@ std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family)
}

#if HAVE_SOCKADDR_UN
if (address_family == AF_UNIX) return sock;
if (domain == AF_UNIX) return sock;
#endif

// Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
const int on{1};
if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
LogPrint(BCLog::NET, "Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n");
if (protocol == IPPROTO_TCP) {
// Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
const int on{1};
if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
LogPrint(BCLog::NET, "Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n");
}
}

return sock;
}

std::function<std::unique_ptr<Sock>(const sa_family_t&)> CreateSock = CreateSockOS;
std::function<std::unique_ptr<Sock>(int, int, int)> CreateSock = CreateSockOS;

template<typename... Args>
static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
Expand Down Expand Up @@ -609,7 +611,7 @@ static bool ConnectToSocket(const Sock& sock, struct sockaddr* sockaddr, socklen

std::unique_ptr<Sock> ConnectDirectly(const CService& dest, bool manual_connection)
{
auto sock = CreateSock(dest.GetSAFamily());
auto sock = CreateSock(dest.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP);
if (!sock) {
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "Cannot create a socket for connecting to %s\n", dest.ToStringAddrPort());
return {};
Expand Down Expand Up @@ -637,7 +639,7 @@ std::unique_ptr<Sock> Proxy::Connect() const
if (!m_is_unix_socket) return ConnectDirectly(proxy, /*manual_connection=*/true);

#if HAVE_SOCKADDR_UN
auto sock = CreateSock(AF_UNIX);
auto sock = CreateSock(AF_UNIX, SOCK_STREAM, 0);
if (!sock) {
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "Cannot create a socket for connecting to %s\n", m_unix_socket_path);
return {};
Expand Down
10 changes: 6 additions & 4 deletions src/netbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,16 +262,18 @@ CService LookupNumeric(const std::string& name, uint16_t portDefault = 0, DNSLoo
CSubNet LookupSubNet(const std::string& subnet_str);

/**
* Create a TCP or UNIX socket in the given address family.
* @param[in] address_family to use for the socket.
* Create a real socket from the operating system.
* @param[in] domain Communications domain, first argument to the socket(2) syscall.
* @param[in] type Type of the socket, second argument to the socket(2) syscall.
* @param[in] protocol The particular protocol to be used with the socket, third argument to the socket(2) syscall.
* @return pointer to the created Sock object or unique_ptr that owns nothing in case of failure
*/
std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family);
std::unique_ptr<Sock> CreateSockOS(int domain, int type, int protocol);

/**
* Socket factory. Defaults to `CreateSockOS()`, but can be overridden by unit tests.
*/
extern std::function<std::unique_ptr<Sock>(const sa_family_t&)> CreateSock;
extern std::function<std::unique_ptr<Sock>(int, int, int)> CreateSock;

/**
* Create a socket and try to connect to the specified service.
Expand Down
9 changes: 4 additions & 5 deletions src/test/denialofservice_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
peerLogic->InitializeNode(*nodes[0], NODE_NETWORK);
nodes[0]->fSuccessfullyConnected = true;
connman->AddTestNode(*nodes[0]);
peerLogic->UnitTestMisbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD); // Should be discouraged
peerLogic->UnitTestMisbehaving(nodes[0]->GetId()); // Should be discouraged
BOOST_CHECK(peerLogic->SendMessages(nodes[0]));

BOOST_CHECK(banman->IsDiscouraged(addr[0]));
Expand All @@ -350,15 +350,14 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
peerLogic->InitializeNode(*nodes[1], NODE_NETWORK);
nodes[1]->fSuccessfullyConnected = true;
connman->AddTestNode(*nodes[1]);
peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1);
BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
// [0] is still discouraged/disconnected.
BOOST_CHECK(banman->IsDiscouraged(addr[0]));
BOOST_CHECK(nodes[0]->fDisconnect);
// [1] is not discouraged/disconnected yet.
BOOST_CHECK(!banman->IsDiscouraged(addr[1]));
BOOST_CHECK(!nodes[1]->fDisconnect);
peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), 1); // [1] reaches discouragement threshold
peerLogic->UnitTestMisbehaving(nodes[1]->GetId());
BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
// Expect both [0] and [1] to be discouraged/disconnected now.
BOOST_CHECK(banman->IsDiscouraged(addr[0]));
Expand All @@ -381,7 +380,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
peerLogic->InitializeNode(*nodes[2], NODE_NETWORK);
nodes[2]->fSuccessfullyConnected = true;
connman->AddTestNode(*nodes[2]);
peerLogic->UnitTestMisbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD);
peerLogic->UnitTestMisbehaving(nodes[2]->GetId());
BOOST_CHECK(peerLogic->SendMessages(nodes[2]));
BOOST_CHECK(banman->IsDiscouraged(addr[0]));
BOOST_CHECK(banman->IsDiscouraged(addr[1]));
Expand Down Expand Up @@ -423,7 +422,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
peerLogic->InitializeNode(dummyNode, NODE_NETWORK);
dummyNode.fSuccessfullyConnected = true;

peerLogic->UnitTestMisbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD);
peerLogic->UnitTestMisbehaving(dummyNode.GetId());
BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
BOOST_CHECK(banman->IsDiscouraged(addr));

Expand Down
5 changes: 3 additions & 2 deletions src/test/fuzz/fuzz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ void ResetCoverageCounters() {}

void initialize()
{
// Terminate immediately if a fuzzing harness ever tries to create a TCP socket.
CreateSock = [](const sa_family_t&) -> std::unique_ptr<Sock> { std::terminate(); };
// Terminate immediately if a fuzzing harness ever tries to create a socket.
// Individual tests can override this by pointing CreateSock to a mocked alternative.
CreateSock = [](int, int, int) -> std::unique_ptr<Sock> { std::terminate(); };

// Terminate immediately if a fuzzing harness ever tries to perform a DNS lookup.
g_dns_lookup = [](const std::string& name, bool allow_lookup) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/i2p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ FUZZ_TARGET(i2p, .init = initialize_i2p)

// Mock CreateSock() to create FuzzedSock.
auto CreateSockOrig = CreateSock;
CreateSock = [&fuzzed_data_provider](const sa_family_t&) {
CreateSock = [&fuzzed_data_provider](int, int, int) {
return std::make_unique<FuzzedSock>(fuzzed_data_provider);
};

Expand Down
24 changes: 12 additions & 12 deletions src/test/fuzz/rbf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
SetMockTime(ConsumeTime(fuzzed_data_provider));

std::optional<CMutableTransaction> child = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
if (!child) return;
// "Real" virtual size is not important for this test since ConsumeTxMemPoolEntry generates its own virtual size values
// so we construct small transactions for performance reasons. Child simply needs an input for later to perhaps connect to parent.
CMutableTransaction child;
child.vin.resize(1);

bilingual_str error;
CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node), error};
Expand All @@ -113,15 +115,13 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), NUM_ITERS)
{
// Make sure txns only have one input, and that a unique input is given to avoid circular references
std::optional<CMutableTransaction> parent = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
if (!parent) {
return;
}
CMutableTransaction parent;
assert(iter <= g_outpoints.size());
parent->vin.resize(1);
parent->vin[0].prevout = g_outpoints[iter++];
parent.vin.resize(1);
parent.vin[0].prevout = g_outpoints[iter++];
parent.vout.emplace_back(0, CScript());

mempool_txs.emplace_back(*parent);
mempool_txs.emplace_back(parent);
const auto parent_entry = ConsumeTxMemPoolEntry(fuzzed_data_provider, mempool_txs.back());
running_vsize_total += parent_entry.GetTxSize();
if (running_vsize_total > std::numeric_limits<int32_t>::max()) {
Expand All @@ -130,10 +130,10 @@ FUZZ_TARGET(package_rbf, .init = initialize_package_rbf)
break;
}
pool.addUnchecked(parent_entry);
if (fuzzed_data_provider.ConsumeBool() && !child->vin.empty()) {
child->vin[0].prevout = COutPoint{mempool_txs.back().GetHash(), 0};
if (fuzzed_data_provider.ConsumeBool()) {
child.vin[0].prevout = COutPoint{mempool_txs.back().GetHash(), 0};
}
mempool_txs.emplace_back(*child);
mempool_txs.emplace_back(child);
const auto child_entry = ConsumeTxMemPoolEntry(fuzzed_data_provider, mempool_txs.back());
running_vsize_total += child_entry.GetTxSize();
if (running_vsize_total > std::numeric_limits<int32_t>::max()) {
Expand Down
13 changes: 4 additions & 9 deletions src/test/i2p_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,14 @@ class EnvTestingSetup : public BasicTestingSetup

private:
const BCLog::Level m_prev_log_level;
const std::function<std::unique_ptr<Sock>(const sa_family_t&)> m_create_sock_orig;
const decltype(CreateSock) m_create_sock_orig;
};

BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)

BOOST_AUTO_TEST_CASE(unlimited_recv)
{
// Mock CreateSock() to create MockSock.
CreateSock = [](const sa_family_t&) {
CreateSock = [](int, int, int) {
return std::make_unique<StaticContentsSock>(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a'));
};

Expand All @@ -69,7 +68,7 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)
{
size_t num_sockets{0};
CreateSock = [&num_sockets](const sa_family_t&) {
CreateSock = [&num_sockets](int, int, int) {
// clang-format off
++num_sockets;
// First socket is the control socket for creating the session.
Expand Down Expand Up @@ -133,9 +132,7 @@ BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)

BOOST_AUTO_TEST_CASE(damaged_private_key)
{
const auto CreateSockOrig = CreateSock;

CreateSock = [](const sa_family_t&) {
CreateSock = [](int, int, int) {
return std::make_unique<StaticContentsSock>("HELLO REPLY RESULT=OK VERSION=3.1\n"
"SESSION STATUS RESULT=OK DESTINATION=\n");
};
Expand Down Expand Up @@ -172,8 +169,6 @@ BOOST_AUTO_TEST_CASE(damaged_private_key)
BOOST_CHECK(!session.Connect(CService{}, conn, proxy_error));
}
}

CreateSock = CreateSockOrig;
}

BOOST_AUTO_TEST_SUITE_END()
Loading

0 comments on commit afc66ff

Please sign in to comment.