Bitcoin Core  31.0.0
P2P Digital Currency
pcp.cpp
Go to the documentation of this file.
1 // Copyright (c) 2024-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 #include <test/fuzz/fuzz.h>
7 #include <test/fuzz/util.h>
8 #include <test/fuzz/util/net.h>
9 
10 #include <common/pcp.h>
11 #include <util/check.h>
12 #include <util/threadinterrupt.h>
13 
14 using namespace std::literals;
15 
17 constexpr PCPMappingNonce PCP_NONCE{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
18 
20 constexpr int NUM_TRIES{5};
21 
23 constexpr std::chrono::duration TIMEOUT{100ms};
24 
26 {
28 }
29 
30 FUZZ_TARGET(pcp_request_port_map, .init = port_map_target_init)
31 {
32  FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
33 
34  // Create a mocked socket between random (and potentially invalid) client and gateway addresses.
35  CreateSock = [&](int domain, int type, int protocol) {
36  if ((domain == AF_INET || domain == AF_INET6) && type == SOCK_DGRAM && protocol == IPPROTO_UDP) {
37  return std::make_unique<FuzzedSock>(fuzzed_data_provider);
38  }
39  return std::unique_ptr<FuzzedSock>();
40  };
41 
42  // Perform the port mapping request. The mocked socket will return fuzzer-provided data.
43  const auto gateway_addr{ConsumeNetAddr(fuzzed_data_provider)};
44  const auto local_addr{ConsumeNetAddr(fuzzed_data_provider)};
45  const auto port{fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
46  const auto lifetime{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
47  CThreadInterrupt interrupt;
48  const auto res{PCPRequestPortMap(PCP_NONCE, gateway_addr, local_addr, port, lifetime, interrupt, NUM_TRIES, TIMEOUT)};
49 
50  // In case of success the mapping must be consistent with the request.
51  if (const MappingResult* mapping = std::get_if<MappingResult>(&res)) {
52  Assert(mapping);
53  Assert(mapping->internal.GetPort() == port);
54  mapping->ToString();
55  }
56 }
57 
58 FUZZ_TARGET(natpmp_request_port_map, .init = port_map_target_init)
59 {
60  FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
61 
62  // Create a mocked socket between random (and potentially invalid) client and gateway addresses.
63  CreateSock = [&](int domain, int type, int protocol) {
64  if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) {
65  return std::make_unique<FuzzedSock>(fuzzed_data_provider);
66  }
67  return std::unique_ptr<FuzzedSock>();
68  };
69 
70  // Perform the port mapping request. The mocked socket will return fuzzer-provided data.
71  const auto gateway_addr{ConsumeNetAddr(fuzzed_data_provider)};
72  const auto port{fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
73  const auto lifetime{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
74  CThreadInterrupt interrupt;
75  const auto res{NATPMPRequestPortMap(gateway_addr, port, lifetime, interrupt, NUM_TRIES, TIMEOUT)};
76 
77  // In case of success the mapping must be consistent with the request.
78  if (const MappingResult* mapping = std::get_if<MappingResult>(&res)) {
79  Assert(mapping);
80  Assert(mapping->internal.GetPort() == port);
81  mapping->ToString();
82  }
83 }
FUZZ_TARGET(pcp_request_port_map,.init=port_map_target_init)
Definition: pcp.cpp:30
void port_map_target_init()
Definition: pcp.cpp:25
void DisableLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Disable logging This offers a slight speedup and slightly smaller memory usage compared to leaving th...
Definition: logging.cpp:111
constexpr PCPMappingNonce PCP_NONCE
Fixed nonce to use in PCP port mapping requests.
Definition: pcp.cpp:17
std::array< uint8_t, PCP_MAP_NONCE_SIZE > PCPMappingNonce
PCP mapping nonce. Arbitrary data chosen by the client to identify a mapping.
Definition: pcp.h:20
BCLog::Logger & LogInstance()
Definition: logging.cpp:26
constexpr std::chrono::duration TIMEOUT
Timeout for each attempt to request a port mapping.
Definition: pcp.cpp:23
std::variant< MappingResult, MappingError > PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, CThreadInterrupt &interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6887 Port Control Protocol (PCP).
Definition: pcp.cpp:406
A helper class for interruptible sleeps.
CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider, FastRandomContext *rand) noexcept
Create a CNetAddr.
Definition: net.cpp:29
std::variant< MappingResult, MappingError > NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, CThreadInterrupt &interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6886 NAT-PMP.
Definition: pcp.cpp:282
FuzzedDataProvider & fuzzed_data_provider
Definition: fees.cpp:38
std::function< std::unique_ptr< Sock >int, int, int)> CreateSock
Socket factory.
Definition: netbase.cpp:577
#define Assert(val)
Identity function.
Definition: check.h:113
Successful response to a port mapping.
Definition: pcp.h:31
constexpr int NUM_TRIES
Number of attempts to request a NAT-PMP or PCP port mapping to the gateway.
Definition: pcp.cpp:20