Bitcoin Core 31.0.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_time{MockableSteadyClock::INITIAL_MOCK_TIME}
119{
120 ElapseTime(std::chrono::seconds(0)); // start mocking the steady clock.
121}
122
124{
125 // Sock::~Sock() will be called after FuzzedSock::~FuzzedSock() and it will call
126 // close(m_socket) if m_socket is not INVALID_SOCKET.
127 // Avoid closing an arbitrary file descriptor (m_socket is just a random very high number which
128 // theoretically may concide with a real opened file descriptor).
130}
131
132void FuzzedSock::ElapseTime(std::chrono::milliseconds duration) const
133{
134 m_time += duration;
136}
137
139{
140 assert(false && "Move of Sock into FuzzedSock not allowed.");
141 return *this;
142}
143
144ssize_t FuzzedSock::Send(const void* data, size_t len, int flags) const
145{
146 constexpr std::array send_errnos{
147 EACCES,
148 EAGAIN,
149 EALREADY,
150 EBADF,
153 EFAULT,
154 EINTR,
155 EINVAL,
156 EISCONN,
157 EMSGSIZE,
158 ENOBUFS,
159 ENOMEM,
160 ENOTCONN,
161 ENOTSOCK,
163 EPIPE,
165 };
167 return len;
168 }
170 if (r == -1) {
172 }
173 return r;
174}
175
176ssize_t FuzzedSock::Recv(void* buf, size_t len, int flags) const
177{
178 // Have a permanent error at recv_errnos[0] because when the fuzzed data is exhausted
179 // SetFuzzedErrNo() will always return the first element and we want to avoid Recv()
180 // returning -1 and setting errno to EAGAIN repeatedly.
181 constexpr std::array recv_errnos{
183 EAGAIN,
184 EBADF,
185 EFAULT,
186 EINTR,
187 EINVAL,
188 ENOMEM,
189 ENOTCONN,
190 ENOTSOCK,
192 };
193 assert(buf != nullptr || len == 0);
194
195 // Do the latency before any of the "return" statements.
196 if (m_fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) {
197 std::this_thread::sleep_for(std::chrono::milliseconds{2});
198 }
199
200 if (len == 0 || m_fuzzed_data_provider.ConsumeBool()) {
201 const ssize_t r = m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
202 if (r == -1) {
204 }
205 return r;
206 }
207
208 size_t copied_so_far{0};
209
210 if (!m_peek_data.empty()) {
211 // `MSG_PEEK` was used in the preceding `Recv()` call, copy the first bytes from `m_peek_data`.
212 const size_t copy_len{std::min(len, m_peek_data.size())};
213 std::memcpy(buf, m_peek_data.data(), copy_len);
215 if ((flags & MSG_PEEK) == 0) {
216 m_peek_data.erase(m_peek_data.begin(), m_peek_data.begin() + copy_len);
217 }
218 }
219
220 if (copied_so_far == len) {
221 return copied_so_far;
222 }
223
225 if (new_data.empty()) return copied_so_far;
226
227 std::memcpy(reinterpret_cast<uint8_t*>(buf) + copied_so_far, new_data.data(), new_data.size());
228 copied_so_far += new_data.size();
229
230 if ((flags & MSG_PEEK) != 0) {
231 m_peek_data.insert(m_peek_data.end(), new_data.begin(), new_data.end());
232 }
233
235 return copied_so_far;
236 }
237
238 // Pad to len bytes.
239 std::memset(reinterpret_cast<uint8_t*>(buf) + copied_so_far, 0x0, len - copied_so_far);
240
241 return len;
242}
243
245{
246 // Have a permanent error at connect_errnos[0] because when the fuzzed data is exhausted
247 // SetFuzzedErrNo() will always return the first element and we want to avoid Connect()
248 // returning -1 and setting errno to EAGAIN repeatedly.
249 constexpr std::array connect_errnos{
251 EAGAIN,
255 EINTR,
257 ETIMEDOUT,
258 };
261 return -1;
262 }
263 return 0;
264}
265
267{
268 // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
269 // SetFuzzedErrNo() will always set the global errno to bind_errnos[0]. We want to
270 // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
271 // repeatedly because proper code should retry on temporary errors, leading to an
272 // infinite loop.
273 constexpr std::array bind_errnos{
274 EACCES,
277 EAGAIN,
278 };
281 return -1;
282 }
283 return 0;
284}
285
286int FuzzedSock::Listen(int) const
287{
288 // Have a permanent error at listen_errnos[0] because when the fuzzed data is exhausted
289 // SetFuzzedErrNo() will always set the global errno to listen_errnos[0]. We want to
290 // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
291 // repeatedly because proper code should retry on temporary errors, leading to an
292 // infinite loop.
293 constexpr std::array listen_errnos{
295 EINVAL,
297 };
300 return -1;
301 }
302 return 0;
303}
304
305std::unique_ptr<Sock> FuzzedSock::Accept(sockaddr* addr, socklen_t* addr_len) const
306{
307 constexpr std::array accept_errnos{
309 EINTR,
310 ENOMEM,
311 };
314 return std::unique_ptr<FuzzedSock>();
315 }
316 if (addr != nullptr) {
317 // Set a fuzzed address in the output argument addr.
318 memset(addr, 0x00, *addr_len);
320 // IPv4
321 const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in));
322 if (*addr_len >= write_len) {
324 auto addr4 = reinterpret_cast<sockaddr_in*>(addr);
325 addr4->sin_family = AF_INET;
326 const auto sin_addr_bytes{m_fuzzed_data_provider.ConsumeBytes<std::byte>(sizeof(addr4->sin_addr))};
327 std::ranges::copy(sin_addr_bytes, reinterpret_cast<std::byte*>(&addr4->sin_addr));
329 }
330 } else {
331 // IPv6
332 const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in6));
333 if (*addr_len >= write_len) {
335 auto addr6 = reinterpret_cast<sockaddr_in6*>(addr);
336 addr6->sin6_family = AF_INET6;
337 const auto sin_addr_bytes{m_fuzzed_data_provider.ConsumeBytes<std::byte>(sizeof(addr6->sin6_addr))};
338 std::ranges::copy(sin_addr_bytes, reinterpret_cast<std::byte*>(&addr6->sin6_addr));
340 }
341 }
342 }
343 return std::make_unique<FuzzedSock>(m_fuzzed_data_provider);
344}
345
346int FuzzedSock::GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const
347{
348 constexpr std::array getsockopt_errnos{
349 ENOMEM,
350 ENOBUFS,
351 };
354 return -1;
355 }
356 if (opt_val == nullptr) {
357 return 0;
358 }
359 std::memcpy(opt_val,
361 *opt_len);
362 return 0;
363}
364
365int FuzzedSock::SetSockOpt(int, int, const void*, socklen_t) const
366{
367 constexpr std::array setsockopt_errnos{
368 ENOMEM,
369 ENOBUFS,
370 };
373 return -1;
374 }
375 return 0;
376}
377
379{
380 constexpr std::array getsockname_errnos{
382 ENOBUFS,
383 };
386 return -1;
387 }
390 if (bytes.size() < (int)sizeof(sockaddr)) return -1;
391 std::memcpy(name, bytes.data(), bytes.size());
392 *name_len = bytes.size();
393 return 0;
394}
395
397{
398 constexpr std::array setnonblocking_errnos{
399 EBADF,
400 EPERM,
401 };
404 return false;
405 }
406 return true;
407}
408
410{
411 return m_selectable;
412}
413
414bool FuzzedSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
415{
416 constexpr std::array wait_errnos{
417 EBADF,
418 EINTR,
419 EINVAL,
420 };
423 return false;
424 }
425 if (occurred != nullptr) {
426 // We simulate the requested event as occurred when ConsumeBool()
427 // returns false. This avoids simulating endless waiting if the
428 // FuzzedDataProvider runs out of data.
429 *occurred = m_fuzzed_data_provider.ConsumeBool() ? 0 : requested;
430 }
431 ElapseTime(timeout);
432 return true;
433}
434
435bool FuzzedSock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const
436{
437 for (auto& [sock, events] : events_per_sock) {
438 (void)sock;
439 // We simulate the requested event as occurred when ConsumeBool()
440 // returns false. This avoids simulating endless waiting if the
441 // FuzzedDataProvider runs out of data.
442 events.occurred = m_fuzzed_data_provider.ConsumeBool() ? 0 : events.requested;
443 }
444 ElapseTime(timeout);
445 return true;
446}
447
448bool FuzzedSock::IsConnected(std::string& errmsg) const
449{
451 return true;
452 }
453 errmsg = "disconnected at random by the fuzzer";
454 return false;
455}
456
int flags
A CService with information about it as peer.
Definition protocol.h:367
static constexpr SerParams V2_NETWORK
Definition protocol.h:409
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:263
Information about a peer.
Definition net.h:680
Double ended buffer combining vector and stream-like interfaces.
Definition streams.h:133
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:305
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
Definition net.cpp:346
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
int Listen(int backlog) const override
listen(2) wrapper.
Definition net.cpp:286
const bool m_selectable
Whether to pretend that the socket is select(2)-able.
Definition net.h:178
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
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
bool IsConnected(std::string &errmsg) const override
Check if still connected.
Definition net.cpp:448
int Connect(const sockaddr *, socklen_t) const override
connect(2) wrapper.
Definition net.cpp:244
ssize_t Send(const void *data, size_t len, int flags) const override
send(2) wrapper.
Definition net.cpp:144
std::vector< uint8_t > m_peek_data
Data to return when MSG_PEEK is used as a Recv() flag.
Definition net.h:171
FuzzedSock & operator=(Sock &&other) override
Move assignment operator, grab the socket from another object and close ours (if set).
Definition net.cpp:138
FuzzedDataProvider & m_fuzzed_data_provider
Definition net.h:164
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
Definition net.cpp:409
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
Definition net.cpp:396
int SetSockOpt(int level, int opt_name, const void *opt_val, socklen_t opt_len) const override
setsockopt(2) wrapper.
Definition net.cpp:365
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
Definition net.cpp:176
~FuzzedSock() override
Definition net.cpp:123
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
Definition net.cpp:378
std::chrono::milliseconds m_time
Used to mock the steady clock in methods waiting for a given duration.
Definition net.h:183
FuzzedSock(FuzzedDataProvider &fuzzed_data_provider)
Definition net.cpp:114
int Bind(const sockaddr *, socklen_t) const override
bind(2) wrapper.
Definition net.cpp:266
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
Definition sock.h:28
SOCKET m_socket
Contained socket.
Definition sock.h:276
uint8_t Event
Definition sock.h:139
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
#define INVALID_SOCKET
Definition compat.h:67
unsigned int SOCKET
Definition compat.h:57
static constexpr uint8_t CJDNS_PREFIX
All CJDNS addresses start with 0xFC.
Definition netaddress.h:83
static constexpr size_t ADDR_CJDNS_SIZE
Size of CJDNS address (in bytes).
Definition netaddress.h:99
static constexpr size_t ADDR_TORV3_SIZE
Size of TORv3 address (in bytes).
Definition netaddress.h:93
static constexpr size_t ADDR_I2P_SIZE
Size of I2P address (in bytes).
Definition netaddress.h:96
static 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
static constexpr size_t ADDR_IPV6_SIZE
Size of IPv6 address (in bytes).
Definition netaddress.h:89
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
const char * name
Definition rest.cpp:48
Version of SteadyClock that is mockable in the context of tests (set the current value with SetMockTi...
Definition time.h:38
static void SetMockTime(mock_time_point::duration mock_time_in)
Set mock time for testing.
Definition time.cpp:70
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:457
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:128
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
Definition util.h:47
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:252
std::vector< B > ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition util.h:57
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:232
constexpr ServiceFlags ALL_SERVICE_FLAGS[]
Definition net.h:120
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition time.h:25
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:73
assert(!tx.IsCoinBase())
FuzzedDataProvider & fuzzed_data_provider
Definition fees.cpp:38