Bitcoin Core  29.1.0
P2P Digital Currency
net.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2022 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 <cstdint>
25 #include <limits>
26 #include <memory>
27 #include <optional>
28 #include <string>
29 
38 CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider, FastRandomContext* rand = nullptr) noexcept;
39 
41 {
42 public:
43  explicit AddrManDeterministic(const NetGroupManager& netgroupman, FuzzedDataProvider& fuzzed_data_provider, int32_t check_ratio)
44  : AddrMan(netgroupman, /*deterministic=*/true, check_ratio)
45  {
46  WITH_LOCK(m_impl->cs, m_impl->insecure_rand.Reseed(ConsumeUInt256(fuzzed_data_provider)));
47  }
48 
56  bool operator==(const AddrManDeterministic& other) const
57  {
58  LOCK2(m_impl->cs, other.m_impl->cs);
59 
60  if (m_impl->mapInfo.size() != other.m_impl->mapInfo.size() || m_impl->nNew != other.m_impl->nNew ||
61  m_impl->nTried != other.m_impl->nTried) {
62  return false;
63  }
64 
65  // Check that all values in `mapInfo` are equal to all values in `other.mapInfo`.
66  // Keys may be different.
67 
68  auto addrinfo_hasher = [](const AddrInfo& a) {
69  CSipHasher hasher(0, 0);
70  auto addr_key = a.GetKey();
71  auto source_key = a.source.GetAddrBytes();
72  hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
73  hasher.Write(a.nAttempts);
74  hasher.Write(a.nRefCount);
75  hasher.Write(a.fInTried);
76  hasher.Write(a.GetNetwork());
77  hasher.Write(a.source.GetNetwork());
78  hasher.Write(addr_key.size());
79  hasher.Write(source_key.size());
80  hasher.Write(addr_key);
81  hasher.Write(source_key);
82  return (size_t)hasher.Finalize();
83  };
84 
85  auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
86  return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
87  std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
88  };
89 
90  using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
91 
92  const size_t num_addresses{m_impl->mapInfo.size()};
93 
94  Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
95  for (const auto& [id, addr] : m_impl->mapInfo) {
96  addresses.insert(addr);
97  }
98 
99  Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
100  for (const auto& [id, addr] : other.m_impl->mapInfo) {
101  other_addresses.insert(addr);
102  }
103 
104  if (addresses != other_addresses) {
105  return false;
106  }
107 
108  auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
109  if (id == -1 && other_id == -1) {
110  return true;
111  }
112  if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
113  return false;
114  }
115  return m_impl->mapInfo.at(id) == other.m_impl->mapInfo.at(other_id);
116  };
117 
118  // Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
119  // contains just an id and the address is to be found in `mapInfo.at(id)`. The ids
120  // themselves may differ between `vvNew` and `other.vvNew`.
121  for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
122  for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
123  if (!IdsReferToSameAddress(m_impl->vvNew[i][j], other.m_impl->vvNew[i][j])) {
124  return false;
125  }
126  }
127  }
128 
129  // Same for `vvTried`.
130  for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
131  for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
132  if (!IdsReferToSameAddress(m_impl->vvTried[i][j], other.m_impl->vvTried[i][j])) {
133  return false;
134  }
135  }
136  }
137 
138  return true;
139  }
140 };
141 
142 class FuzzedSock : public Sock
143 {
145 
151  mutable std::vector<uint8_t> m_peek_data;
152 
158  const bool m_selectable;
159 
163  mutable std::chrono::milliseconds m_time;
164 
168  void ElapseTime(std::chrono::milliseconds duration) const;
169 
170 public:
171  explicit FuzzedSock(FuzzedDataProvider& fuzzed_data_provider);
172 
173  ~FuzzedSock() override;
174 
175  FuzzedSock& operator=(Sock&& other) override;
176 
177  ssize_t Send(const void* data, size_t len, int flags) const override;
178 
179  ssize_t Recv(void* buf, size_t len, int flags) const override;
180 
181  int Connect(const sockaddr*, socklen_t) const override;
182 
183  int Bind(const sockaddr*, socklen_t) const override;
184 
185  int Listen(int backlog) const override;
186 
187  std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
188 
189  int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
190 
191  int SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt_len) const override;
192 
193  int GetSockName(sockaddr* name, socklen_t* name_len) const override;
194 
195  bool SetNonBlocking() const override;
196 
197  bool IsSelectable() const override;
198 
199  bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
200 
201  bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
202 
203  bool IsConnected(std::string& errmsg) const override;
204 };
205 
206 [[nodiscard]] inline FuzzedSock ConsumeSock(FuzzedDataProvider& fuzzed_data_provider)
207 {
208  return FuzzedSock{fuzzed_data_provider};
209 }
210 
211 [[nodiscard]] inline NetGroupManager ConsumeNetGroupManager(FuzzedDataProvider& fuzzed_data_provider) noexcept
212 {
213  std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
214  if (!SanityCheckASMap(asmap, 128)) asmap.clear();
215  return NetGroupManager(asmap);
216 }
217 
218 inline CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept
219 {
220  return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint8_t>()};
221 }
222 
223 inline CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept
224 {
225  return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
226 }
227 
228 CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept;
229 
230 template <bool ReturnUniquePtr = false>
231 auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<NodeId>& node_id_in = std::nullopt) noexcept
232 {
233  const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegralInRange<NodeId>(0, std::numeric_limits<NodeId>::max()));
234  const auto sock = std::make_shared<FuzzedSock>(fuzzed_data_provider);
235  const CAddress address = ConsumeAddress(fuzzed_data_provider);
236  const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
237  const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
238  const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider);
239  const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
240  const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES);
241  const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
242  NetPermissionFlags permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
243  if constexpr (ReturnUniquePtr) {
244  return std::make_unique<CNode>(node_id,
245  sock,
246  address,
247  keyed_net_group,
248  local_host_nonce,
249  addr_bind,
250  addr_name,
251  conn_type,
252  inbound_onion,
253  CNodeOptions{ .permission_flags = permission_flags });
254  } else {
255  return CNode{node_id,
256  sock,
257  address,
258  keyed_net_group,
259  local_host_nonce,
260  addr_bind,
261  addr_name,
262  conn_type,
263  inbound_onion,
264  CNodeOptions{ .permission_flags = permission_flags }};
265  }
266 }
267 inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = std::nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
268 
270 
271 #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:1011
const std::unique_ptr< AddrManImpl > m_impl
Definition: addrman.h:91
void FillNode(FuzzedDataProvider &fuzzed_data_provider, ConnmanTestMsg &connman, CNode &node) noexcept
Definition: net.cpp:429
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:137
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
Definition: siphash.cpp:28
NetPermissionFlags permission_flags
Definition: net.h:664
FuzzedSock ConsumeSock(FuzzedDataProvider &fuzzed_data_provider)
Definition: net.h:206
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:133
bool SanityCheckASMap(const std::vector< bool > &asmap, int bits)
Definition: asmap.cpp:133
constexpr NetPermissionFlags ALL_NET_PERMISSION_FLAGS[]
Definition: net.h:105
std::vector< uint8_t > m_peek_data
Data to return when MSG_PEEK is used as a Recv() flag.
Definition: net.h:151
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:267
int SetSockOpt(int level, int opt_name, const void *opt_val, socklen_t opt_len) const override
setsockopt(2) wrapper.
Definition: net.cpp:337
std::chrono::milliseconds m_time
Used to mock the steady clock in methods waiting for a given duration.
Definition: net.h:163
auto ConsumeNode(FuzzedDataProvider &fuzzed_data_provider, const std::optional< NodeId > &node_id_in=std::nullopt) noexcept
Definition: net.h:231
bool IsConnected(std::string &errmsg) const override
Check if still connected.
Definition: net.cpp:420
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
Definition: net.cpp:175
NetGroupManager ConsumeNetGroupManager(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:211
NetPermissionFlags
Netgroup manager.
Definition: netgroup.h:16
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:143
int nAttempts
connection attempts since last successful attempt
Definition: addrman_impl.h:61
constexpr ConnectionType ALL_CONNECTION_TYPES[]
Definition: net.h:118
#define LOCK2(cs1, cs2)
Definition: sync.h:258
int nRefCount
reference count in new sets (memory only)
Definition: addrman_impl.h:64
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:386
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:208
const char * name
Definition: rest.cpp:49
CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider, FastRandomContext *rand=nullptr) noexcept
Create a CNetAddr.
Definition: net.cpp:28
AddrManDeterministic(const NetGroupManager &netgroupman, FuzzedDataProvider &fuzzed_data_provider, int32_t check_ratio)
Definition: net.h:43
CService ConsumeService(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:223
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:530
Fast randomness source.
Definition: random.h:376
Extended statistics about a CAddress.
Definition: addrman_impl.h:45
A CService with information about it as peer.
Definition: protocol.h:366
std::vector< bool > ConsumeRandomLengthBitVector(FuzzedDataProvider &fuzzed_data_provider, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition: util.h:68
int64_t NodeId
Definition: net.h:97
~FuzzedSock() override
Definition: net.cpp:122
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:77
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
Definition: net.cpp:318
std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const override
accept(2) wrapper.
Definition: net.cpp:304
uint8_t Event
Definition: sock.h:138
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
int Connect(const sockaddr *, socklen_t) const override
connect(2) wrapper.
Definition: net.cpp:243
FuzzedSock(FuzzedDataProvider &fuzzed_data_provider)
Definition: net.cpp:113
Definition: messages.h:20
int flags
Definition: bitcoin-tx.cpp:536
CNetAddr source
where knowledge about this address first came from
Definition: addrman_impl.h:55
Network address.
Definition: netaddress.h:111
FuzzedDataProvider & m_fuzzed_data_provider
Definition: net.h:144
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
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:131
bool operator==(const AddrManDeterministic &other) const
Compare with another AddrMan.
Definition: net.h:56
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:407
SipHash-2-4.
Definition: siphash.h:14
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:26
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
Definition: net.cpp:368
const bool m_selectable
Whether to pretend that the socket is select(2)-able.
Definition: net.h:158
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
Definition: net.cpp:350
Information about a peer.
Definition: net.h:672
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
Definition: net.cpp:381
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.h:171
int Bind(const sockaddr *, socklen_t) const override
bind(2) wrapper.
Definition: net.cpp:265
NodeSeconds m_last_success
last successful connection by us
Definition: addrman_impl.h:58
int Listen(int backlog) const override
listen(2) wrapper.
Definition: net.cpp:285
CSubNet ConsumeSubNet(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:218
CAddress ConsumeAddress(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.cpp:87