Line data Source code
1 : // Copyright (c) 2012-2020 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 : #include <addrdb.h>
6 : #include <addrman.h>
7 : #include <chainparams.h>
8 : #include <clientversion.h>
9 : #include <cstdint>
10 : #include <net.h>
11 : #include <netbase.h>
12 : #include <serialize.h>
13 : #include <streams.h>
14 : #include <test/util/setup_common.h>
15 : #include <util/memory.h>
16 : #include <util/strencodings.h>
17 : #include <util/string.h>
18 : #include <util/system.h>
19 : #include <version.h>
20 :
21 : #include <boost/test/unit_test.hpp>
22 :
23 : #include <memory>
24 : #include <string>
25 :
26 4 : class CAddrManSerializationMock : public CAddrMan
27 : {
28 : public:
29 : virtual void Serialize(CDataStream& s) const = 0;
30 :
31 : //! Ensure that bucket placement is always the same for testing purposes.
32 2 : void MakeDeterministic()
33 : {
34 2 : nKey.SetNull();
35 2 : insecure_rand = FastRandomContext(true);
36 2 : }
37 : };
38 :
39 4 : class CAddrManUncorrupted : public CAddrManSerializationMock
40 : {
41 : public:
42 2 : void Serialize(CDataStream& s) const override
43 : {
44 2 : CAddrMan::Serialize(s);
45 2 : }
46 : };
47 :
48 4 : class CAddrManCorrupted : public CAddrManSerializationMock
49 : {
50 : public:
51 2 : void Serialize(CDataStream& s) const override
52 : {
53 : // Produces corrupt output that claims addrman has 20 addrs when it only has one addr.
54 2 : unsigned char nVersion = 1;
55 2 : s << nVersion;
56 2 : s << ((unsigned char)32);
57 2 : s << nKey;
58 2 : s << 10; // nNew
59 2 : s << 10; // nTried
60 :
61 2 : int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
62 2 : s << nUBuckets;
63 :
64 2 : CService serv;
65 2 : BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false));
66 2 : CAddress addr = CAddress(serv, NODE_NONE);
67 2 : CNetAddr resolved;
68 2 : BOOST_CHECK(LookupHost("252.2.2.2", resolved, false));
69 2 : CAddrInfo info = CAddrInfo(addr, resolved);
70 2 : s << info;
71 2 : }
72 : };
73 :
74 4 : static CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
75 : {
76 4 : CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
77 4 : ssPeersIn << Params().MessageStart();
78 4 : ssPeersIn << _addrman;
79 4 : std::string str = ssPeersIn.str();
80 4 : std::vector<unsigned char> vchData(str.begin(), str.end());
81 4 : return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
82 4 : }
83 :
84 89 : BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup)
85 :
86 95 : BOOST_AUTO_TEST_CASE(cnode_listen_port)
87 : {
88 : // test default
89 1 : uint16_t port = GetListenPort();
90 1 : BOOST_CHECK(port == Params().GetDefaultPort());
91 : // test set port
92 1 : uint16_t altPort = 12345;
93 1 : BOOST_CHECK(gArgs.SoftSetArg("-port", ToString(altPort)));
94 1 : port = GetListenPort();
95 1 : BOOST_CHECK(port == altPort);
96 1 : }
97 :
98 95 : BOOST_AUTO_TEST_CASE(caddrdb_read)
99 : {
100 1 : CAddrManUncorrupted addrmanUncorrupted;
101 1 : addrmanUncorrupted.MakeDeterministic();
102 :
103 1 : CService addr1, addr2, addr3;
104 1 : BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
105 1 : BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
106 1 : BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
107 1 : BOOST_CHECK(Lookup(std::string("250.7.3.3", 9), addr3, 9999, false));
108 1 : BOOST_CHECK(!Lookup(std::string("250.7.3.3\0example.com", 21), addr3, 9999, false));
109 :
110 : // Add three addresses to new table.
111 1 : CService source;
112 1 : BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
113 1 : BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source));
114 1 : BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source));
115 1 : BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source));
116 :
117 : // Test that the de-serialization does not throw an exception.
118 1 : CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
119 : bool exceptionThrown = false;
120 1 : CAddrMan addrman1;
121 :
122 1 : BOOST_CHECK(addrman1.size() == 0);
123 : try {
124 1 : unsigned char pchMsgTmp[4];
125 1 : ssPeers1 >> pchMsgTmp;
126 1 : ssPeers1 >> addrman1;
127 1 : } catch (const std::exception&) {
128 : exceptionThrown = true;
129 0 : }
130 :
131 1 : BOOST_CHECK(addrman1.size() == 3);
132 1 : BOOST_CHECK(exceptionThrown == false);
133 :
134 : // Test that CAddrDB::Read creates an addrman with the correct number of addrs.
135 1 : CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
136 :
137 1 : CAddrMan addrman2;
138 1 : BOOST_CHECK(addrman2.size() == 0);
139 1 : BOOST_CHECK(CAddrDB::Read(addrman2, ssPeers2));
140 1 : BOOST_CHECK(addrman2.size() == 3);
141 1 : }
142 :
143 :
144 95 : BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
145 : {
146 1 : CAddrManCorrupted addrmanCorrupted;
147 1 : addrmanCorrupted.MakeDeterministic();
148 :
149 : // Test that the de-serialization of corrupted addrman throws an exception.
150 1 : CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted);
151 : bool exceptionThrown = false;
152 1 : CAddrMan addrman1;
153 1 : BOOST_CHECK(addrman1.size() == 0);
154 : try {
155 1 : unsigned char pchMsgTmp[4];
156 1 : ssPeers1 >> pchMsgTmp;
157 1 : ssPeers1 >> addrman1;
158 1 : } catch (const std::exception&) {
159 : exceptionThrown = true;
160 1 : }
161 : // Even through de-serialization failed addrman is not left in a clean state.
162 1 : BOOST_CHECK(addrman1.size() == 1);
163 1 : BOOST_CHECK(exceptionThrown);
164 :
165 : // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails.
166 1 : CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
167 :
168 1 : CAddrMan addrman2;
169 1 : BOOST_CHECK(addrman2.size() == 0);
170 1 : BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2));
171 1 : BOOST_CHECK(addrman2.size() == 0);
172 2 : }
173 :
174 95 : BOOST_AUTO_TEST_CASE(cnode_simple_test)
175 : {
176 1 : SOCKET hSocket = INVALID_SOCKET;
177 : NodeId id = 0;
178 1 : int height = 0;
179 :
180 1 : in_addr ipv4Addr;
181 1 : ipv4Addr.s_addr = 0xa0b0c001;
182 :
183 1 : CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
184 1 : std::string pszDest;
185 :
186 1 : std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY);
187 1 : BOOST_CHECK(pnode1->IsFullOutboundConn() == true);
188 1 : BOOST_CHECK(pnode1->IsManualConn() == false);
189 1 : BOOST_CHECK(pnode1->IsBlockOnlyConn() == false);
190 1 : BOOST_CHECK(pnode1->IsFeelerConn() == false);
191 1 : BOOST_CHECK(pnode1->IsAddrFetchConn() == false);
192 1 : BOOST_CHECK(pnode1->IsInboundConn() == false);
193 :
194 1 : std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, ConnectionType::INBOUND);
195 1 : BOOST_CHECK(pnode2->IsFullOutboundConn() == false);
196 1 : BOOST_CHECK(pnode2->IsManualConn() == false);
197 1 : BOOST_CHECK(pnode2->IsBlockOnlyConn() == false);
198 1 : BOOST_CHECK(pnode2->IsFeelerConn() == false);
199 1 : BOOST_CHECK(pnode2->IsAddrFetchConn() == false);
200 1 : BOOST_CHECK(pnode2->IsInboundConn() == true);
201 1 : }
202 :
203 95 : BOOST_AUTO_TEST_CASE(cnetaddr_basic)
204 : {
205 1 : CNetAddr addr;
206 :
207 : // IPv4, INADDR_ANY
208 1 : BOOST_REQUIRE(LookupHost("0.0.0.0", addr, false));
209 1 : BOOST_REQUIRE(!addr.IsValid());
210 1 : BOOST_REQUIRE(addr.IsIPv4());
211 :
212 1 : BOOST_CHECK(addr.IsBindAny());
213 1 : BOOST_CHECK_EQUAL(addr.ToString(), "0.0.0.0");
214 :
215 : // IPv4, INADDR_NONE
216 1 : BOOST_REQUIRE(LookupHost("255.255.255.255", addr, false));
217 1 : BOOST_REQUIRE(!addr.IsValid());
218 1 : BOOST_REQUIRE(addr.IsIPv4());
219 :
220 1 : BOOST_CHECK(!addr.IsBindAny());
221 1 : BOOST_CHECK_EQUAL(addr.ToString(), "255.255.255.255");
222 :
223 : // IPv4, casual
224 1 : BOOST_REQUIRE(LookupHost("12.34.56.78", addr, false));
225 1 : BOOST_REQUIRE(addr.IsValid());
226 1 : BOOST_REQUIRE(addr.IsIPv4());
227 :
228 1 : BOOST_CHECK(!addr.IsBindAny());
229 1 : BOOST_CHECK_EQUAL(addr.ToString(), "12.34.56.78");
230 :
231 : // IPv6, in6addr_any
232 1 : BOOST_REQUIRE(LookupHost("::", addr, false));
233 1 : BOOST_REQUIRE(!addr.IsValid());
234 1 : BOOST_REQUIRE(addr.IsIPv6());
235 :
236 1 : BOOST_CHECK(addr.IsBindAny());
237 1 : BOOST_CHECK_EQUAL(addr.ToString(), "::");
238 :
239 : // IPv6, casual
240 1 : BOOST_REQUIRE(LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", addr, false));
241 1 : BOOST_REQUIRE(addr.IsValid());
242 1 : BOOST_REQUIRE(addr.IsIPv6());
243 :
244 1 : BOOST_CHECK(!addr.IsBindAny());
245 1 : BOOST_CHECK_EQUAL(addr.ToString(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
246 :
247 : // TORv2
248 1 : addr.SetSpecial("6hzph5hv6337r6p2.onion");
249 1 : BOOST_REQUIRE(addr.IsValid());
250 1 : BOOST_REQUIRE(addr.IsTor());
251 :
252 1 : BOOST_CHECK(!addr.IsBindAny());
253 1 : BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
254 :
255 : // Internal
256 1 : addr.SetInternal("esffpp");
257 1 : BOOST_REQUIRE(!addr.IsValid()); // "internal" is considered invalid
258 1 : BOOST_REQUIRE(addr.IsInternal());
259 :
260 1 : BOOST_CHECK(!addr.IsBindAny());
261 1 : BOOST_CHECK_EQUAL(addr.ToString(), "esffpvrt3wpeaygy.internal");
262 1 : }
263 :
264 95 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize)
265 : {
266 1 : CNetAddr addr;
267 1 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
268 :
269 1 : addr.SetInternal("a");
270 1 : s << addr;
271 1 : BOOST_CHECK_EQUAL(HexStr(s), "fd6b88c08724ca978112ca1bbdcafac2");
272 1 : s.clear();
273 1 : }
274 :
275 : // prior to PR #14728, this test triggers an undefined behavior
276 95 : BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
277 : {
278 : // set up local addresses; all that's necessary to reproduce the bug is
279 : // that a normal IPv4 address is among the entries, but if this address is
280 : // !IsRoutable the undefined behavior is easier to trigger deterministically
281 : {
282 1 : LOCK(cs_mapLocalHost);
283 1 : in_addr ipv4AddrLocal;
284 1 : ipv4AddrLocal.s_addr = 0x0100007f;
285 1 : CNetAddr addr = CNetAddr(ipv4AddrLocal);
286 : LocalServiceInfo lsi;
287 : lsi.nScore = 23;
288 : lsi.nPort = 42;
289 1 : mapLocalHost[addr] = lsi;
290 1 : }
291 :
292 : // create a peer with an IPv4 address
293 1 : in_addr ipv4AddrPeer;
294 1 : ipv4AddrPeer.s_addr = 0xa0b0c001;
295 1 : CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
296 1 : std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY);
297 1 : pnode->fSuccessfullyConnected.store(true);
298 :
299 : // the peer claims to be reaching us via IPv6
300 1 : in6_addr ipv6AddrLocal;
301 1 : memset(ipv6AddrLocal.s6_addr, 0, 16);
302 1 : ipv6AddrLocal.s6_addr[0] = 0xcc;
303 1 : CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
304 1 : pnode->SetAddrLocal(addrLocal);
305 :
306 : // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
307 1 : AdvertiseLocal(&*pnode);
308 :
309 : // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
310 1 : BOOST_CHECK(1);
311 1 : }
312 :
313 :
314 95 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
315 : {
316 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
317 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
318 1 : BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
319 :
320 1 : SetReachable(NET_IPV4, false);
321 1 : SetReachable(NET_IPV6, false);
322 1 : SetReachable(NET_ONION, false);
323 :
324 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
325 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
326 1 : BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
327 :
328 1 : SetReachable(NET_IPV4, true);
329 1 : SetReachable(NET_IPV6, true);
330 1 : SetReachable(NET_ONION, true);
331 :
332 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
333 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
334 1 : BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
335 1 : }
336 :
337 95 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
338 : {
339 1 : BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
340 1 : BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
341 :
342 1 : SetReachable(NET_UNROUTABLE, false);
343 1 : SetReachable(NET_INTERNAL, false);
344 :
345 1 : BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); // Ignored for both networks
346 1 : BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
347 1 : }
348 :
349 2 : CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
350 : {
351 : unsigned char ip[] = {p1, p2, p3, p4};
352 :
353 2 : struct sockaddr_in sa;
354 2 : memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
355 2 : memcpy(&(sa.sin_addr), &ip, sizeof(ip));
356 2 : return CNetAddr(sa.sin_addr);
357 2 : }
358 :
359 :
360 95 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
361 : {
362 1 : CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
363 :
364 1 : SetReachable(NET_IPV4, true);
365 1 : BOOST_CHECK_EQUAL(IsReachable(addr), true);
366 :
367 1 : SetReachable(NET_IPV4, false);
368 1 : BOOST_CHECK_EQUAL(IsReachable(addr), false);
369 :
370 1 : SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
371 1 : }
372 :
373 :
374 95 : BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
375 : {
376 1 : CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
377 :
378 1 : SetReachable(NET_IPV4, true);
379 :
380 1 : BOOST_CHECK_EQUAL(IsLocal(addr), false);
381 1 : BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
382 1 : BOOST_CHECK_EQUAL(IsLocal(addr), true);
383 :
384 1 : RemoveLocal(addr);
385 1 : BOOST_CHECK_EQUAL(IsLocal(addr), false);
386 1 : }
387 :
388 95 : BOOST_AUTO_TEST_CASE(PoissonNextSend)
389 : {
390 1 : g_mock_deterministic_tests = true;
391 :
392 1 : int64_t now = 5000;
393 1 : int average_interval_seconds = 600;
394 :
395 1 : auto poisson = ::PoissonNextSend(now, average_interval_seconds);
396 1 : std::chrono::microseconds poisson_chrono = ::PoissonNextSend(std::chrono::microseconds{now}, std::chrono::seconds{average_interval_seconds});
397 :
398 1 : BOOST_CHECK_EQUAL(poisson, poisson_chrono.count());
399 :
400 1 : g_mock_deterministic_tests = false;
401 1 : }
402 :
403 89 : BOOST_AUTO_TEST_SUITE_END()
|