Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
net.cpp
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
6
7#include <compat/compat.h>
8#include <netaddress.h>
10#include <protocol.h>
12#include <test/fuzz/util.h>
13#include <test/util/net.h>
14#include <util/sock.h>
15#include <util/time.h>
16
17#include <array>
18#include <cassert>
19#include <cerrno>
20#include <cstdint>
21#include <cstdlib>
22#include <cstring>
23#include <ranges>
24#include <thread>
25#include <vector>
26
27class CNode;
28
30{
31 struct NetAux {
34 size_t len;
35 };
36
37 static constexpr std::array<NetAux, 6> nets{
43 NetAux{.net = Network::NET_INTERNAL, .bip155 = CNetAddr::BIP155Network{0}, .len = 0},
44 };
45
46 const size_t nets_index{rand == nullptr
47 ? fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, nets.size() - 1)
48 : static_cast<size_t>(rand->randrange(nets.size()))};
49
50 const auto& aux = nets[nets_index];
51
52 CNetAddr addr;
53
54 if (aux.net == Network::NET_INTERNAL) {
55 if (rand == nullptr) {
57 } else {
58 const auto v = rand->randbytes(32);
59 addr.SetInternal(std::string{v.begin(), v.end()});
60 }
61 return addr;
62 }
63
64 DataStream s;
65
66 s << static_cast<uint8_t>(aux.bip155);
67
68 std::vector<uint8_t> addr_bytes;
69 if (rand == nullptr) {
71 addr_bytes.resize(aux.len);
72 } else {
73 addr_bytes = rand->randbytes(aux.len);
74 }
75 if (aux.net == NET_IPV6 && addr_bytes[0] == CJDNS_PREFIX) { // Avoid generating IPv6 addresses that look like CJDNS.
76 addr_bytes[0] = 0x55; // Just an arbitrary number, anything != CJDNS_PREFIX would do.
77 }
78 if (aux.net == NET_CJDNS) { // Avoid generating CJDNS addresses that don't start with CJDNS_PREFIX because those are !IsValid().
80 }
81 s << addr_bytes;
82
83 s >> CAddress::V2_NETWORK(addr);
84
85 return addr;
86}
87
92
93template <typename P>
95{
96 constexpr std::array ADDR_ENCODINGS{
99 };
100 constexpr std::array ADDR_FORMATS{
103 };
104 if constexpr (std::is_same_v<P, CNetAddr::SerParams>) {
106 }
107 if constexpr (std::is_same_v<P, CAddress::SerParams>) {
109 }
110}
113
115 : Sock{fuzzed_data_provider.ConsumeIntegralInRange<SOCKET>(INVALID_SOCKET - 1, INVALID_SOCKET)},
116 m_fuzzed_data_provider{fuzzed_data_provider},
117 m_selectable{fuzzed_data_provider.ConsumeBool()},
118 m_clock{clock}
119{
120}
121
123{
124 // Sock::~Sock() will be called after FuzzedSock::~FuzzedSock() and it will call
125 // close(m_socket) if m_socket is not INVALID_SOCKET.
126 // Avoid closing an arbitrary file descriptor (m_socket is just a random very high number which
127 // theoretically may concide with a real opened file descriptor).
129}
130
132{
133 assert(false && "Move of Sock into FuzzedSock not allowed.");
134 return *this;
135}
136
137ssize_t FuzzedSock::Send(const void* data, size_t len, int flags) const
138{
139 constexpr std::array send_errnos{
140 EACCES,
141 EAGAIN,
142 EALREADY,
143 EBADF,
146 EFAULT,
147 EINTR,
148 EINVAL,
149 EISCONN,
150 EMSGSIZE,
151 ENOBUFS,
152 ENOMEM,
153 ENOTCONN,
154 ENOTSOCK,
156 EPIPE,
158 };
160 return len;
161 }
163 if (r == -1) {
165 }
166 return r;
167}
168
169ssize_t FuzzedSock::Recv(void* buf, size_t len, int flags) const
170{
171 // Have a permanent error at recv_errnos[0] because when the fuzzed data is exhausted
172 // SetFuzzedErrNo() will always return the first element and we want to avoid Recv()
173 // returning -1 and setting errno to EAGAIN repeatedly.
174 constexpr std::array recv_errnos{
176 EAGAIN,
177 EBADF,
178 EFAULT,
179 EINTR,
180 EINVAL,
181 ENOMEM,
182 ENOTCONN,
183 ENOTSOCK,
185 };
186 assert(buf != nullptr || len == 0);
187
188 // Do the latency before any of the "return" statements.
189 if (m_fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) {
190 std::this_thread::sleep_for(std::chrono::milliseconds{2});
191 }
192
193 if (len == 0 || m_fuzzed_data_provider.ConsumeBool()) {
194 const ssize_t r = m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
195 if (r == -1) {
197 }
198 return r;
199 }
200
201 size_t copied_so_far{0};
202
203 if (!m_peek_data.empty()) {
204 // `MSG_PEEK` was used in the preceding `Recv()` call, copy the first bytes from `m_peek_data`.
205 const size_t copy_len{std::min(len, m_peek_data.size())};
206 std::memcpy(buf, m_peek_data.data(), copy_len);
208 if ((flags & MSG_PEEK) == 0) {
209 m_peek_data.erase(m_peek_data.begin(), m_peek_data.begin() + copy_len);
210 }
211 }
212
213 if (copied_so_far == len) {
214 return copied_so_far;
215 }
216
218 if (new_data.empty()) return copied_so_far;
219
220 std::memcpy(reinterpret_cast<uint8_t*>(buf) + copied_so_far, new_data.data(), new_data.size());
221 copied_so_far += new_data.size();
222
223 if ((flags & MSG_PEEK) != 0) {
224 m_peek_data.insert(m_peek_data.end(), new_data.begin(), new_data.end());
225 }
226
228 return copied_so_far;
229 }
230
231 // Pad to len bytes.
232 std::memset(reinterpret_cast<uint8_t*>(buf) + copied_so_far, 0x0, len - copied_so_far);
233
234 return len;
235}
236
238{
239 // Have a permanent error at connect_errnos[0] because when the fuzzed data is exhausted
240 // SetFuzzedErrNo() will always return the first element and we want to avoid Connect()
241 // returning -1 and setting errno to EAGAIN repeatedly.
242 constexpr std::array connect_errnos{
244 EAGAIN,
248 EINTR,
250 ETIMEDOUT,
251 };
254 return -1;
255 }
256 return 0;
257}
258
260{
261 // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
262 // SetFuzzedErrNo() will always set the global errno to bind_errnos[0]. We want to
263 // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
264 // repeatedly because proper code should retry on temporary errors, leading to an
265 // infinite loop.
266 constexpr std::array bind_errnos{
267 EACCES,
270 EAGAIN,
271 };
274 return -1;
275 }
276 return 0;
277}
278
279int FuzzedSock::Listen(int) const
280{
281 // Have a permanent error at listen_errnos[0] because when the fuzzed data is exhausted
282 // SetFuzzedErrNo() will always set the global errno to listen_errnos[0]. We want to
283 // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
284 // repeatedly because proper code should retry on temporary errors, leading to an
285 // infinite loop.
286 constexpr std::array listen_errnos{
288 EINVAL,
290 };
293 return -1;
294 }
295 return 0;
296}
297
298std::unique_ptr<Sock> FuzzedSock::Accept(sockaddr* addr, socklen_t* addr_len) const
299{
300 constexpr std::array accept_errnos{
302 EINTR,
303 ENOMEM,
304 };
307 return std::unique_ptr<FuzzedSock>();
308 }
309 if (addr != nullptr) {
310 // Set a fuzzed address in the output argument addr.
311 memset(addr, 0x00, *addr_len);
313 // IPv4
314 const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in));
315 if (*addr_len >= write_len) {
317 auto addr4 = reinterpret_cast<sockaddr_in*>(addr);
318 addr4->sin_family = AF_INET;
319 const auto sin_addr_bytes{m_fuzzed_data_provider.ConsumeBytes<std::byte>(sizeof(addr4->sin_addr))};
320 std::ranges::copy(sin_addr_bytes, reinterpret_cast<std::byte*>(&addr4->sin_addr));
322 }
323 } else {
324 // IPv6
325 const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in6));
326 if (*addr_len >= write_len) {
328 auto addr6 = reinterpret_cast<sockaddr_in6*>(addr);
329 addr6->sin6_family = AF_INET6;
330 const auto sin_addr_bytes{m_fuzzed_data_provider.ConsumeBytes<std::byte>(sizeof(addr6->sin6_addr))};
331 std::ranges::copy(sin_addr_bytes, reinterpret_cast<std::byte*>(&addr6->sin6_addr));
333 }
334 }
335 }
336 return std::make_unique<FuzzedSock>(m_fuzzed_data_provider, m_clock);
337}
338
339int FuzzedSock::GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const
340{
341 constexpr std::array getsockopt_errnos{
342 ENOMEM,
343 ENOBUFS,
344 };
347 return -1;
348 }
349 if (opt_val == nullptr) {
350 return 0;
351 }
352 std::memcpy(opt_val,
354 *opt_len);
355 return 0;
356}
357
358int FuzzedSock::SetSockOpt(int, int, const void*, socklen_t) const
359{
360 constexpr std::array setsockopt_errnos{
361 ENOMEM,
362 ENOBUFS,
363 };
366 return -1;
367 }
368 return 0;
369}
370
372{
373 constexpr std::array getsockname_errnos{
375 ENOBUFS,
376 };
379 return -1;
380 }
383 if (bytes.size() < (int)sizeof(sockaddr)) return -1;
384 std::memcpy(name, bytes.data(), bytes.size());
385 *name_len = bytes.size();
386 return 0;
387}
388
390{
391 constexpr std::array setnonblocking_errnos{
392 EBADF,
393 EPERM,
394 };
397 return false;
398 }
399 return true;
400}
401
403{
404 return m_selectable;
405}
406
407bool FuzzedSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
408{
409 constexpr std::array wait_errnos{
410 EBADF,
411 EINTR,
412 EINVAL,
413 };
416 return false;
417 }
418 if (occurred != nullptr) {
419 // We simulate the requested event as occurred when ConsumeBool()
420 // returns false. This avoids simulating endless waiting if the
421 // FuzzedDataProvider runs out of data.
422 *occurred = m_fuzzed_data_provider.ConsumeBool() ? 0 : requested;
423 }
424 m_clock += timeout;
425 return true;
426}
427
428bool FuzzedSock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const
429{
430 for (auto& [sock, events] : events_per_sock) {
431 (void)sock;
432 // We simulate the requested event as occurred when ConsumeBool()
433 // returns false. This avoids simulating endless waiting if the
434 // FuzzedDataProvider runs out of data.
435 events.occurred = m_fuzzed_data_provider.ConsumeBool() ? 0 : events.requested;
436 }
437 m_clock += timeout;
438 return true;
439}
440
441bool FuzzedSock::IsConnected(std::string& errmsg) const
442{
444 return true;
445 }
446 errmsg = "disconnected at random by the fuzzer";
447 return false;
448}
449
int flags
A CService with information about it as peer.
Definition protocol.h:387
static constexpr SerParams V2_NETWORK
Definition protocol.h:429
Network address.
Definition netaddress.h:113
@ V2
BIP155 encoding.
bool SetInternal(const std::string &name)
Create an "internal" address that represents a name or FQDN.
BIP155Network
BIP155 network ids recognized by this software.
Definition netaddress.h:264
Information about a peer.
Definition net.h:686
Double ended buffer combining vector and stream-like interfaces.
Definition streams.h:165
Helper to initialize the global MockableSteadyClock, let a duration elapse, and reset it after use in...
Definition time.h:29
Fast randomness source.
Definition random.h:386
std::string ConsumeBytesAsString(size_t num_bytes)
std::vector< T > ConsumeBytes(size_t num_bytes)
T ConsumeIntegralInRange(T min, T max)
std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const override
accept(2) wrapper.
Definition net.cpp:298
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
Definition net.cpp:339
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:407
FakeSteadyClock & m_clock
Externally-provided context used to mock the steady clock in methods waiting for a given duration.
Definition net.h:188
int Listen(int backlog) const override
listen(2) wrapper.
Definition net.cpp:279
const bool m_selectable
Whether to pretend that the socket is select(2)-able.
Definition net.h:179
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:428
bool IsConnected(std::string &errmsg) const override
Check if still connected.
Definition net.cpp:441
int Connect(const sockaddr *, socklen_t) const override
connect(2) wrapper.
Definition net.cpp:237
ssize_t Send(const void *data, size_t len, int flags) const override
send(2) wrapper.
Definition net.cpp:137
std::vector< uint8_t > m_peek_data
Data to return when MSG_PEEK is used as a Recv() flag.
Definition net.h:172
FuzzedSock & operator=(Sock &&other) override
Move assignment operator, grab the socket from another object and close ours (if set).
Definition net.cpp:131
FuzzedDataProvider & m_fuzzed_data_provider
Definition net.h:165
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
Definition net.cpp:402
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
Definition net.cpp:389
int SetSockOpt(int level, int opt_name, const void *opt_val, socklen_t opt_len) const override
setsockopt(2) wrapper.
Definition net.cpp:358
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
Definition net.cpp:169
FuzzedSock(FuzzedDataProvider &fuzzed_data_provider, FakeSteadyClock &clock)
Definition net.cpp:114
~FuzzedSock() override
Definition net.cpp:122
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
Definition net.cpp:371
int Bind(const sockaddr *, socklen_t) const override
bind(2) wrapper.
Definition net.cpp:259
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
Definition sock.h:35
SOCKET m_socket
Contained socket.
Definition sock.h:293
uint8_t Event
Definition sock.h:146
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:225
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
#define INVALID_SOCKET
Definition compat.h:67
unsigned int SOCKET
Definition compat.h:57
constexpr uint8_t CJDNS_PREFIX
All CJDNS addresses start with 0xFC.
Definition netaddress.h:83
constexpr size_t ADDR_CJDNS_SIZE
Size of CJDNS address (in bytes).
Definition netaddress.h:99
constexpr size_t ADDR_TORV3_SIZE
Size of TORv3 address (in bytes).
Definition netaddress.h:93
constexpr size_t ADDR_I2P_SIZE
Size of I2P address (in bytes).
Definition netaddress.h:96
constexpr size_t ADDR_IPV4_SIZE
Size of IPv4 address (in bytes).
Definition netaddress.h:86
Network
A network type.
Definition netaddress.h:33
@ NET_I2P
I2P.
Definition netaddress.h:47
@ NET_CJDNS
CJDNS.
Definition netaddress.h:50
@ NET_ONION
TOR (v2 or v3)
Definition netaddress.h:44
@ NET_IPV6
IPv6.
Definition netaddress.h:41
@ NET_IPV4
IPv4.
Definition netaddress.h:38
@ NET_INTERNAL
A set of addresses that represent the hash of a string or FQDN.
Definition netaddress.h:54
constexpr size_t ADDR_IPV6_SIZE
Size of IPv6 address (in bytes).
Definition netaddress.h:89
constexpr int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
const char * name
Definition rest.cpp:71
CAddress ConsumeAddress(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition net.cpp:88
P ConsumeDeserializationParams(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition net.cpp:94
CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider, FastRandomContext *rand) noexcept
Create a CNetAddr.
Definition net.cpp:29
void FillNode(FuzzedDataProvider &fuzzed_data_provider, ConnmanTestMsg &connman, CNode &node) noexcept
Definition net.cpp:450
CService ConsumeService(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition net.h:250
WeakEnumType ConsumeWeakEnum(FuzzedDataProvider &fuzzed_data_provider, const WeakEnumType(&all_types)[size]) noexcept
Definition util.h:147
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
Definition util.h:57
std::vector< B > ConsumeFixedLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, const size_t length) noexcept
Returns a byte vector of specified size regardless of the number of remaining bytes available from th...
Definition util.h:280
std::vector< B > ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition util.h:63
void SetFuzzedErrNo(FuzzedDataProvider &fuzzed_data_provider, const std::array< T, size > &errnos)
Sets errno to a value selected from the given std::array errnos.
Definition util.h:260
constexpr ServiceFlags ALL_SERVICE_FLAGS[]
Definition net.h:121
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition time.h:35
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82
assert(!tx.IsCoinBase())
FuzzedDataProvider & fuzzed_data_provider
Definition fees.cpp:46
FakeNodeClock clock