Bitcoin Core  31.0.0
P2P Digital Currency
net.h
Go to the documentation of this file.
1 // Copyright (c) 2009-present The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef BITCOIN_TEST_FUZZ_UTIL_NET_H
6 #define BITCOIN_TEST_FUZZ_UTIL_NET_H
7 
8 #include <addrman.h>
9 #include <addrman_impl.h>
10 #include <net.h>
11 #include <net_permissions.h>
12 #include <netaddress.h>
13 #include <node/connection_types.h>
14 #include <node/eviction.h>
15 #include <protocol.h>
17 #include <test/fuzz/util.h>
18 #include <test/util/net.h>
19 #include <threadsafety.h>
20 #include <util/asmap.h>
21 #include <util/sock.h>
22 
23 #include <chrono>
24 #include <cstddef>
25 #include <cstdint>
26 #include <limits>
27 #include <memory>
28 #include <optional>
29 #include <string>
30 
40 
42 {
43 public:
44  explicit AddrManDeterministic(const NetGroupManager& netgroupman, FuzzedDataProvider& fuzzed_data_provider, int32_t check_ratio)
45  : AddrMan(netgroupman, /*deterministic=*/true, check_ratio)
46  {
47  WITH_LOCK(m_impl->cs, m_impl->insecure_rand.Reseed(ConsumeUInt256(fuzzed_data_provider)));
48  }
49 
57  bool operator==(const AddrManDeterministic& other) const
58  {
59  LOCK2(m_impl->cs, other.m_impl->cs);
60 
61  if (m_impl->mapInfo.size() != other.m_impl->mapInfo.size() || m_impl->nNew != other.m_impl->nNew ||
62  m_impl->nTried != other.m_impl->nTried) {
63  return false;
64  }
65 
66  // Check that all values in `mapInfo` are equal to all values in `other.mapInfo`.
67  // Keys may be different.
68 
69  auto addrinfo_hasher = [](const AddrInfo& a) {
70  CSipHasher hasher(0, 0);
71  auto addr_key = a.GetKey();
72  auto source_key = a.source.GetAddrBytes();
73  hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
74  hasher.Write(a.nAttempts);
75  hasher.Write(a.nRefCount);
76  hasher.Write(a.fInTried);
77  hasher.Write(a.GetNetwork());
78  hasher.Write(a.source.GetNetwork());
79  hasher.Write(addr_key.size());
80  hasher.Write(source_key.size());
81  hasher.Write(addr_key);
82  hasher.Write(source_key);
83  return (size_t)hasher.Finalize();
84  };
85 
86  auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
87  return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
88  std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
89  };
90 
91  using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
92 
93  const size_t num_addresses{m_impl->mapInfo.size()};
94 
95  Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
96  for (const auto& [id, addr] : m_impl->mapInfo) {
97  addresses.insert(addr);
98  }
99 
100  Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
101  for (const auto& [id, addr] : other.m_impl->mapInfo) {
102  other_addresses.insert(addr);
103  }
104 
105  if (addresses != other_addresses) {
106  return false;
107  }
108 
109  auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
110  if (id == -1 && other_id == -1) {
111  return true;
112  }
113  if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
114  return false;
115  }
116  return m_impl->mapInfo.at(id) == other.m_impl->mapInfo.at(other_id);
117  };
118 
119  // Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
120  // contains just an id and the address is to be found in `mapInfo.at(id)`. The ids
121  // themselves may differ between `vvNew` and `other.vvNew`.
122  for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
123  for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
124  if (!IdsReferToSameAddress(m_impl->vvNew[i][j], other.m_impl->vvNew[i][j])) {
125  return false;
126  }
127  }
128  }
129 
130  // Same for `vvTried`.
131  for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
132  for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
133  if (!IdsReferToSameAddress(m_impl->vvTried[i][j], other.m_impl->vvTried[i][j])) {
134  return false;
135  }
136  }
137  }
138 
139  return true;
140  }
141 };
142 
144 {
145 public:
147 
148  virtual void InitializeNode(const CNode&, ServiceFlags) override {}
149 
150  virtual void FinalizeNode(const CNode&) override {}
151 
152  virtual bool HasAllDesirableServiceFlags(ServiceFlags) const override { return m_fdp.ConsumeBool(); }
153 
154  virtual bool ProcessMessages(CNode&, std::atomic<bool>&) override { return m_fdp.ConsumeBool(); }
155 
156  virtual bool SendMessages(CNode&) override { return m_fdp.ConsumeBool(); }
157 
158 private:
160 };
161 
162 class FuzzedSock : public Sock
163 {
165 
171  mutable std::vector<uint8_t> m_peek_data;
172 
178  const bool m_selectable;
179 
183  mutable std::chrono::milliseconds m_time;
184 
188  void ElapseTime(std::chrono::milliseconds duration) const;
189 
190 public:
192 
193  ~FuzzedSock() override;
194 
195  FuzzedSock& operator=(Sock&& other) override;
196 
197  ssize_t Send(const void* data, size_t len, int flags) const override;
198 
199  ssize_t Recv(void* buf, size_t len, int flags) const override;
200 
201  int Connect(const sockaddr*, socklen_t) const override;
202 
203  int Bind(const sockaddr*, socklen_t) const override;
204 
205  int Listen(int backlog) const override;
206 
207  std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
208 
209  int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
210 
211  int SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt_len) const override;
212 
213  int GetSockName(sockaddr* name, socklen_t* name_len) const override;
214 
215  bool SetNonBlocking() const override;
216 
217  bool IsSelectable() const override;
218 
219  bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
220 
221  bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
222 
223  bool IsConnected(std::string& errmsg) const override;
224 };
225 
226 [[nodiscard]] inline FuzzedNetEvents ConsumeNetEvents(FuzzedDataProvider& fdp) noexcept
227 {
228  return FuzzedNetEvents{fdp};
229 }
230 
232 {
234 }
235 
237 {
238  std::vector<std::byte> asmap{ConsumeRandomLengthByteVector<std::byte>(fuzzed_data_provider)};
239  if (!CheckStandardAsmap(asmap)) {
240  return NetGroupManager::NoAsmap();
241  }
242  return NetGroupManager::WithLoadedAsmap(std::move(asmap));
243 }
244 
246 {
248 }
249 
251 {
253 }
254 
256  size_t max_vector_size = 5) noexcept
257 {
258  std::vector<CService> ret;
259  const size_t size = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
260  ret.reserve(size);
261  for (size_t i = 0; i < size; ++i) {
262  ret.emplace_back(ConsumeService(fuzzed_data_provider));
263  }
264  return ret;
265 }
266 
268 
269 template <bool ReturnUniquePtr = false>
270 auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<NodeId>& node_id_in = std::nullopt) noexcept
271 {
272  const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegralInRange<NodeId>(0, std::numeric_limits<NodeId>::max()));
273  const auto sock = std::make_shared<FuzzedSock>(fuzzed_data_provider);
275  const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
276  const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
277  const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider);
278  const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
280  const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
281  const uint64_t network_id = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
282 
284  if constexpr (ReturnUniquePtr) {
285  return std::make_unique<CNode>(node_id,
286  sock,
287  address,
288  keyed_net_group,
289  local_host_nonce,
290  addr_bind,
291  addr_name,
292  conn_type,
293  inbound_onion,
294  network_id,
295  CNodeOptions{ .permission_flags = permission_flags });
296  } else {
297  return CNode{node_id,
298  sock,
299  address,
300  keyed_net_group,
301  local_host_nonce,
302  addr_bind,
303  addr_name,
304  conn_type,
305  inbound_onion,
306  network_id,
307  CNodeOptions{ .permission_flags = permission_flags }};
308  }
309 }
310 inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = std::nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
311 
313 
314 #endif // BITCOIN_TEST_FUZZ_UTIL_NET_H
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
Definition: net.h:1031
virtual void InitializeNode(const CNode &, ServiceFlags) override
Initialize a peer (setup state)
Definition: net.h:148
const std::unique_ptr< AddrManImpl > m_impl
Definition: addrman.h:91
int ret
void FillNode(FuzzedDataProvider &fuzzed_data_provider, ConnmanTestMsg &connman, CNode &node) noexcept
Definition: net.cpp:457
ServiceFlags
nServices flags
Definition: protocol.h:309
Inbound connections are those initiated by a peer.
FuzzedSock & operator=(Sock &&other) override
Move assignment operator, grab the socket from another object and close ours (if set).
Definition: net.cpp:138
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Definition: siphash.cpp:24
NetPermissionFlags permission_flags
Definition: net.h:671
FuzzedSock ConsumeSock(FuzzedDataProvider &fuzzed_data_provider)
Definition: net.h:231
static constexpr int ADDRMAN_BUCKET_SIZE
Definition: addrman_impl.h:33
WeakEnumType ConsumeWeakEnum(FuzzedDataProvider &fuzzed_data_provider, const WeakEnumType(&all_types)[size]) noexcept
Definition: util.h:128
constexpr NetPermissionFlags ALL_NET_PERMISSION_FLAGS[]
Definition: net.h:130
std::vector< uint8_t > m_peek_data
Data to return when MSG_PEEK is used as a Recv() flag.
Definition: net.h:171
int64_t nid_type
User-defined type for the internally used nIds This used to be int, making it feasible for attackers ...
Definition: addrman_impl.h:40
static constexpr int ADDRMAN_TRIED_BUCKET_COUNT
Definition: addrman_impl.h:27
std::unique_ptr< CNode > ConsumeNodeAsUniquePtr(FuzzedDataProvider &fdp, const std::optional< NodeId > &node_id_in=std::nullopt)
Definition: net.h:310
int SetSockOpt(int level, int opt_name, const void *opt_val, socklen_t opt_len) const override
setsockopt(2) wrapper.
Definition: net.cpp:365
std::chrono::milliseconds m_time
Used to mock the steady clock in methods waiting for a given duration.
Definition: net.h:183
Interface for message handling.
Definition: net.h:1027
virtual bool SendMessages(CNode &) override
Send queued protocol messages to a given node.
Definition: net.h:156
auto ConsumeNode(FuzzedDataProvider &fuzzed_data_provider, const std::optional< NodeId > &node_id_in=std::nullopt) noexcept
Definition: net.h:270
bool IsConnected(std::string &errmsg) const override
Check if still connected.
Definition: net.cpp:448
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
Definition: net.cpp:176
NetGroupManager ConsumeNetGroupManager(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:236
NetPermissionFlags
Netgroup manager.
Definition: netgroup.h:17
Stochastic address manager.
Definition: addrman.h:88
ssize_t Send(const void *data, size_t len, int flags) const override
send(2) wrapper.
Definition: net.cpp:144
int nAttempts
connection attempts since last successful attempt
Definition: addrman_impl.h:61
constexpr ConnectionType ALL_CONNECTION_TYPES[]
Definition: net.h:143
#define LOCK2(cs1, cs2)
Definition: sync.h:259
int nRefCount
reference count in new sets (memory only)
Definition: addrman_impl.h:64
static NetGroupManager NoAsmap()
Definition: netgroup.h:32
bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const override
Wait for readiness for input (recv) or output (send).
Definition: net.cpp:414
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
Definition: sock.h:209
const char * name
Definition: rest.cpp:48
CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider, FastRandomContext *rand=nullptr) noexcept
Create a CNetAddr.
Definition: net.cpp:29
AddrManDeterministic(const NetGroupManager &netgroupman, FuzzedDataProvider &fuzzed_data_provider, int32_t check_ratio)
Definition: net.h:44
CService ConsumeService(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:250
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:529
Fast randomness source.
Definition: random.h:385
Extended statistics about a CAddress.
Definition: addrman_impl.h:45
std::string ConsumeRandomLengthString(size_t max_length)
FuzzedNetEvents(FuzzedDataProvider &fdp)
Definition: net.h:146
A CService with information about it as peer.
Definition: protocol.h:366
static NetGroupManager WithLoadedAsmap(std::vector< std::byte > &&asmap)
Definition: netgroup.h:28
int64_t NodeId
Definition: net.h:103
~FuzzedSock() override
Definition: net.cpp:123
std::vector< CService > ConsumeServiceVector(FuzzedDataProvider &fuzzed_data_provider, size_t max_vector_size=5) noexcept
Definition: net.h:255
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:73
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
Definition: net.cpp:346
std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const override
accept(2) wrapper.
Definition: net.cpp:305
uint8_t Event
Definition: sock.h:139
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:289
int Connect(const sockaddr *, socklen_t) const override
connect(2) wrapper.
Definition: net.cpp:244
FuzzedSock(FuzzedDataProvider &fuzzed_data_provider)
Definition: net.cpp:114
Definition: messages.h:21
int flags
Definition: bitcoin-tx.cpp:529
CNetAddr source
where knowledge about this address first came from
Definition: addrman_impl.h:55
Network address.
Definition: netaddress.h:112
FuzzedDataProvider & m_fuzzed_data_provider
Definition: net.h:164
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
FuzzedNetEvents ConsumeNetEvents(FuzzedDataProvider &fdp) noexcept
Definition: net.h:226
static constexpr int ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman_impl.h:30
void ElapseTime(std::chrono::milliseconds duration) const
Set the value of the mocked steady clock such as that many ms have passed.
Definition: net.cpp:132
virtual bool HasAllDesirableServiceFlags(ServiceFlags) const override
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
Definition: net.h:152
bool operator==(const AddrManDeterministic &other) const
Compare with another AddrMan.
Definition: net.h:57
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock &events_per_sock) const override
Same as Wait(), but wait on many sockets within the same timeout.
Definition: net.cpp:435
FuzzedDataProvider & fuzzed_data_provider
Definition: fees.cpp:38
General SipHash-2-4 implementation.
Definition: siphash.h:26
ConnectionType
Different types of connections to a peer.
bool fInTried
in tried set? (memory only)
Definition: addrman_impl.h:67
RAII helper class that manages a socket and closes it automatically when it goes out of scope...
Definition: sock.h:27
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
Definition: net.cpp:396
const bool m_selectable
Whether to pretend that the socket is select(2)-able.
Definition: net.h:178
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
Definition: net.cpp:378
Information about a peer.
Definition: net.h:679
T ConsumeIntegralInRange(T min, T max)
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
Definition: net.cpp:409
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.h:167
T PickValueInArray(const T(&array)[size])
int Bind(const sockaddr *, socklen_t) const override
bind(2) wrapper.
Definition: net.cpp:266
NodeSeconds m_last_success
last successful connection by us
Definition: addrman_impl.h:58
FuzzedDataProvider & m_fdp
Definition: net.h:159
int Listen(int backlog) const override
listen(2) wrapper.
Definition: net.cpp:286
CSubNet ConsumeSubNet(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:245
CAddress ConsumeAddress(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.cpp:88
virtual void FinalizeNode(const CNode &) override
Handle removal of a peer (clear state)
Definition: net.h:150
bool CheckStandardAsmap(const std::span< const std::byte > data)
Provides a safe interface for validating ASMap data before use.
Definition: asmap.cpp:310
virtual bool ProcessMessages(CNode &, std::atomic< bool > &) override
Process protocol messages received from a given node.
Definition: net.h:154