Line data Source code
1 : // Copyright (c) 2012-2016 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 "addrman.h"
6 : #include "chainparams.h"
7 : #include "hash.h"
8 : #include "net.h"
9 : #include "netbase.h"
10 : #include "serialize.h"
11 : #include "span.h"
12 : #include "streams.h"
13 : #include "version.h"
14 :
15 : #include <cstdint>
16 :
17 : #include "test/test_pivx.h"
18 :
19 : #include <ios>
20 : #include <string>
21 :
22 : #include <boost/test/unit_test.hpp>
23 :
24 4 : class CAddrManSerializationMock : public CAddrMan
25 : {
26 : public:
27 : virtual void Serialize(CDataStream::CBaseDataStream& s) const = 0;
28 :
29 : //! Ensure that bucket placement is always the same for testing purposes.
30 2 : void MakeDeterministic()
31 : {
32 2 : nKey.SetNull();
33 2 : SeedInsecureRand(SeedRand::ZEROS);
34 2 : }
35 : };
36 :
37 0 : class CAddrManUncorrupted : public CAddrManSerializationMock
38 : {
39 : public:
40 2 : void Serialize(CDataStream::CBaseDataStream& s) const
41 : {
42 2 : CAddrMan::Serialize(s);
43 2 : }
44 : };
45 :
46 0 : class CAddrManCorrupted : public CAddrManSerializationMock
47 : {
48 : public:
49 2 : void Serialize(CDataStream::CBaseDataStream& s) const
50 : {
51 : // Produces corrupt output that claims addrman has 20 addrs when it only has one addr.
52 2 : unsigned char nVersion = 1;
53 2 : s << nVersion;
54 2 : s << ((unsigned char)32);
55 2 : s << nKey;
56 2 : s << 10; // nNew
57 2 : s << 10; // nTried
58 :
59 2 : int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
60 2 : s << nUBuckets;
61 :
62 2 : CService serv;
63 2 : Lookup("252.1.1.1", serv, 7777, false);
64 4 : CAddress addr = CAddress(serv, NODE_NONE);
65 4 : CNetAddr resolved;
66 2 : LookupHost("252.2.2.2", resolved, false);
67 4 : CAddrInfo info = CAddrInfo(addr, resolved);
68 2 : s << info;
69 2 : }
70 : };
71 :
72 4 : CDataStream AddrmanToStream(CAddrManSerializationMock& addrman)
73 : {
74 4 : CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
75 4 : ssPeersIn << Params().MessageStart();
76 4 : ssPeersIn << addrman;
77 8 : std::string str = ssPeersIn.str();
78 8 : std::vector<unsigned char> vchData(str.begin(), str.end());
79 8 : return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
80 : }
81 :
82 : BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup)
83 :
84 2 : BOOST_AUTO_TEST_CASE(cnode_listen_port)
85 : {
86 : // test default
87 1 : uint16_t port = GetListenPort();
88 2 : BOOST_CHECK(port == Params().GetDefaultPort());
89 : // test set port
90 1 : uint16_t altPort = 12345;
91 2 : BOOST_CHECK(gArgs.SoftSetArg("-port", std::to_string(altPort)));
92 1 : port = GetListenPort();
93 2 : BOOST_CHECK(port == altPort);
94 1 : }
95 :
96 2 : BOOST_AUTO_TEST_CASE(caddrdb_read)
97 : {
98 1 : CAddrManUncorrupted addrmanUncorrupted;
99 1 : addrmanUncorrupted.MakeDeterministic();
100 :
101 2 : CService addr1, addr2, addr3;
102 2 : BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
103 2 : BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
104 2 : BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
105 3 : BOOST_CHECK(Lookup(std::string("250.7.3.3", 9), addr3, 9999, false));
106 4 : BOOST_CHECK(!Lookup(std::string("250.7.3.3\0example.com", 21), addr3, 9999, false));
107 :
108 : // Add three addresses to new table.
109 2 : CService source;
110 1 : Lookup("252.5.1.1", source, 8333, false);
111 2 : addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source);
112 2 : addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source);
113 2 : addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source);
114 :
115 : // Test that the de-serialization does not throw an exception.
116 2 : CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
117 1 : bool exceptionThrown = false;
118 2 : CAddrMan addrman1;
119 :
120 2 : BOOST_CHECK(addrman1.size() == 0);
121 1 : try {
122 1 : unsigned char pchMsgTmp[4];
123 1 : ssPeers1 >> pchMsgTmp;
124 1 : ssPeers1 >> addrman1;
125 0 : } catch (const std::exception& e) {
126 0 : exceptionThrown = true;
127 : }
128 :
129 2 : BOOST_CHECK(addrman1.size() == 3);
130 2 : BOOST_CHECK(exceptionThrown == false);
131 :
132 : // Test that CAddrDB::Read creates an addrman with the correct number of addrs.
133 2 : CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
134 :
135 2 : CAddrMan addrman2;
136 2 : BOOST_CHECK(addrman2.size() == 0);
137 2 : BOOST_CHECK(CAddrDB::Read(addrman2, ssPeers2));
138 2 : BOOST_CHECK(addrman2.size() == 3);
139 1 : }
140 :
141 :
142 2 : BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
143 : {
144 1 : CAddrManCorrupted addrmanCorrupted;
145 1 : addrmanCorrupted.MakeDeterministic();
146 :
147 : // Test that the de-serialization of corrupted addrman throws an exception.
148 2 : CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted);
149 1 : bool exceptionThrown = false;
150 2 : CAddrMan addrman1;
151 2 : BOOST_CHECK(addrman1.size() == 0);
152 1 : try {
153 1 : unsigned char pchMsgTmp[4];
154 1 : ssPeers1 >> pchMsgTmp;
155 1 : ssPeers1 >> addrman1;
156 1 : } catch (const std::exception& e) {
157 1 : exceptionThrown = true;
158 : }
159 : // Even through de-serialization failed addrman is not left in a clean state.
160 2 : BOOST_CHECK(addrman1.size() == 1);
161 2 : BOOST_CHECK(exceptionThrown);
162 :
163 : // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails.
164 2 : CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
165 :
166 2 : CAddrMan addrman2;
167 2 : BOOST_CHECK(addrman2.size() == 0);
168 2 : BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2));
169 2 : BOOST_CHECK(addrman2.size() == 0);
170 1 : }
171 :
172 2 : BOOST_AUTO_TEST_CASE(cnode_simple_test)
173 : {
174 1 : SOCKET hSocket = INVALID_SOCKET;
175 1 : NodeId id = 0;
176 1 : int height = 0;
177 :
178 1 : in_addr ipv4Addr;
179 1 : ipv4Addr.s_addr = 0xa0b0c001;
180 :
181 2 : CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
182 2 : std::string pszDest = "";
183 1 : bool fInboundIn = false;
184 :
185 : // Test that fFeeler is false by default.
186 2 : std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, pszDest, fInboundIn));
187 2 : BOOST_CHECK(pnode1->fInbound == false);
188 2 : BOOST_CHECK(pnode1->fFeeler == false);
189 :
190 1 : fInboundIn = true;
191 2 : std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, pszDest, fInboundIn));
192 2 : BOOST_CHECK(pnode2->fInbound == true);
193 2 : BOOST_CHECK(pnode2->fFeeler == false);
194 1 : }
195 :
196 2 : BOOST_AUTO_TEST_CASE(cnetaddr_basic)
197 : {
198 1 : CNetAddr addr;
199 :
200 : // IPv4, INADDR_ANY
201 2 : BOOST_REQUIRE(LookupHost("0.0.0.0", addr, false));
202 2 : BOOST_REQUIRE(!addr.IsValid());
203 2 : BOOST_REQUIRE(addr.IsIPv4());
204 :
205 2 : BOOST_CHECK(addr.IsBindAny());
206 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
207 1 : BOOST_CHECK_EQUAL(addr.ToString(), "0.0.0.0");
208 :
209 : // IPv4, INADDR_NONE
210 2 : BOOST_REQUIRE(LookupHost("255.255.255.255", addr, false));
211 2 : BOOST_REQUIRE(!addr.IsValid());
212 2 : BOOST_REQUIRE(addr.IsIPv4());
213 :
214 2 : BOOST_CHECK(!addr.IsBindAny());
215 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
216 1 : BOOST_CHECK_EQUAL(addr.ToString(), "255.255.255.255");
217 :
218 : // IPv4, casual
219 2 : BOOST_REQUIRE(LookupHost("12.34.56.78", addr, false));
220 2 : BOOST_REQUIRE(addr.IsValid());
221 2 : BOOST_REQUIRE(addr.IsIPv4());
222 :
223 2 : BOOST_CHECK(!addr.IsBindAny());
224 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
225 1 : BOOST_CHECK_EQUAL(addr.ToString(), "12.34.56.78");
226 :
227 : // IPv6, in6addr_any
228 2 : BOOST_REQUIRE(LookupHost("::", addr, false));
229 2 : BOOST_REQUIRE(!addr.IsValid());
230 2 : BOOST_REQUIRE(addr.IsIPv6());
231 :
232 2 : BOOST_CHECK(addr.IsBindAny());
233 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
234 1 : BOOST_CHECK_EQUAL(addr.ToString(), "::");
235 :
236 : // IPv6, casual
237 3 : BOOST_REQUIRE(LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", addr, false));
238 2 : BOOST_REQUIRE(addr.IsValid());
239 2 : BOOST_REQUIRE(addr.IsIPv6());
240 :
241 2 : BOOST_CHECK(!addr.IsBindAny());
242 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
243 2 : BOOST_CHECK_EQUAL(addr.ToString(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
244 :
245 : // TORv2
246 3 : BOOST_REQUIRE(addr.SetSpecial("6hzph5hv6337r6p2.onion"));
247 2 : BOOST_REQUIRE(addr.IsValid());
248 2 : BOOST_REQUIRE(addr.IsTor());
249 :
250 2 : BOOST_CHECK(!addr.IsBindAny());
251 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
252 2 : BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
253 :
254 : // TORv3
255 1 : const char* torv3_addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion";
256 3 : BOOST_REQUIRE(addr.SetSpecial(torv3_addr));
257 2 : BOOST_REQUIRE(addr.IsValid());
258 2 : BOOST_REQUIRE(addr.IsTor());
259 :
260 2 : BOOST_CHECK(!addr.IsBindAny());
261 2 : BOOST_CHECK(!addr.IsAddrV1Compatible());
262 2 : BOOST_CHECK_EQUAL(addr.ToString(), torv3_addr);
263 :
264 : // TORv3, broken, with wrong checksum
265 3 : BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.onion"));
266 :
267 : // TORv3, broken, with wrong version
268 3 : BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscrye.onion"));
269 :
270 : // TORv3, malicious
271 4 : BOOST_CHECK(!addr.SetSpecial(std::string{
272 : "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd\0wtf.onion", 66}));
273 :
274 : // TOR, bogus length
275 2 : BOOST_CHECK(!addr.SetSpecial(std::string{"mfrggzak.onion"}));
276 :
277 : // TOR, invalid base32
278 2 : BOOST_CHECK(!addr.SetSpecial(std::string{"mf*g zak.onion"}));
279 :
280 : // Internal
281 1 : addr.SetInternal("esffpp");
282 2 : BOOST_REQUIRE(!addr.IsValid()); // "internal" is considered invalid
283 2 : BOOST_REQUIRE(addr.IsInternal());
284 :
285 2 : BOOST_CHECK(!addr.IsBindAny());
286 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
287 2 : BOOST_CHECK_EQUAL(addr.ToString(), "esffpvrt3wpeaygy.internal");
288 :
289 : // Totally bogus
290 2 : BOOST_CHECK(!addr.SetSpecial("totally bogus"));
291 1 : }
292 :
293 2 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
294 : {
295 1 : CNetAddr addr;
296 2 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
297 :
298 1 : s << addr;
299 2 : BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
300 1 : s.clear();
301 :
302 2 : BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
303 1 : s << addr;
304 2 : BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000ffff01020304");
305 1 : s.clear();
306 :
307 3 : BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
308 1 : s << addr;
309 2 : BOOST_CHECK_EQUAL(HexStr(s), "1a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
310 1 : s.clear();
311 :
312 3 : BOOST_REQUIRE(addr.SetSpecial("6hzph5hv6337r6p2.onion"));
313 1 : s << addr;
314 2 : BOOST_CHECK_EQUAL(HexStr(s), "fd87d87eeb43f1f2f3f4f5f6f7f8f9fa");
315 1 : s.clear();
316 :
317 3 : BOOST_REQUIRE(addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
318 1 : s << addr;
319 2 : BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
320 1 : s.clear();
321 :
322 1 : addr.SetInternal("a");
323 1 : s << addr;
324 2 : BOOST_CHECK_EQUAL(HexStr(s), "fd6b88c08724ca978112ca1bbdcafac2");
325 2 : s.clear();
326 1 : }
327 :
328 2 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v2)
329 : {
330 1 : CNetAddr addr;
331 2 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
332 : // Add ADDRV2_FORMAT to the version so that the CNetAddr
333 : // serialize method produces an address in v2 format.
334 1 : s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
335 :
336 1 : s << addr;
337 2 : BOOST_CHECK_EQUAL(HexStr(s), "021000000000000000000000000000000000");
338 1 : s.clear();
339 :
340 2 : BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
341 1 : s << addr;
342 1 : BOOST_CHECK_EQUAL(HexStr(s), "010401020304");
343 1 : s.clear();
344 :
345 3 : BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
346 1 : s << addr;
347 2 : BOOST_CHECK_EQUAL(HexStr(s), "02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
348 1 : s.clear();
349 :
350 3 : BOOST_REQUIRE(addr.SetSpecial("6hzph5hv6337r6p2.onion"));
351 1 : s << addr;
352 2 : BOOST_CHECK_EQUAL(HexStr(s), "030af1f2f3f4f5f6f7f8f9fa");
353 1 : s.clear();
354 :
355 3 : BOOST_REQUIRE(addr.SetSpecial("kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion"));
356 1 : s << addr;
357 2 : BOOST_CHECK_EQUAL(HexStr(s), "042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88");
358 1 : s.clear();
359 :
360 2 : BOOST_REQUIRE(addr.SetInternal("a"));
361 1 : s << addr;
362 2 : BOOST_CHECK_EQUAL(HexStr(s), "0210fd6b88c08724ca978112ca1bbdcafac2");
363 2 : s.clear();
364 1 : }
365 :
366 2 : BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
367 : {
368 1 : CNetAddr addr;
369 2 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
370 : // Add ADDRV2_FORMAT to the version so that the CNetAddr
371 : // unserialize method expects an address in v2 format.
372 1 : s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
373 :
374 : // Valid IPv4.
375 1 : s << MakeSpan(ParseHex("01" // network type (IPv4)
376 : "04" // address length
377 1 : "01020304")); // address
378 1 : s >> addr;
379 2 : BOOST_CHECK(addr.IsValid());
380 2 : BOOST_CHECK(addr.IsIPv4());
381 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
382 1 : BOOST_CHECK_EQUAL(addr.ToString(), "1.2.3.4");
383 2 : BOOST_REQUIRE(s.empty());
384 :
385 : // Invalid IPv4, valid length but address itself is shorter.
386 1 : s << MakeSpan(ParseHex("01" // network type (IPv4)
387 : "04" // address length
388 1 : "0102")); // address
389 3 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure, HasReason("end of data"));
390 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
391 1 : s.clear();
392 :
393 : // Invalid IPv4, with bogus length.
394 1 : s << MakeSpan(ParseHex("01" // network type (IPv4)
395 : "05" // address length
396 1 : "01020304")); // address
397 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
398 : HasReason("BIP155 IPv4 address with length 5 (should be 4)"));
399 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
400 1 : s.clear();
401 :
402 : // Invalid IPv4, with extreme length.
403 1 : s << MakeSpan(ParseHex("01" // network type (IPv4)
404 : "fd0102" // address length (513 as CompactSize)
405 1 : "01020304")); // address
406 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
407 : HasReason("Address too long: 513 > 512"));
408 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
409 1 : s.clear();
410 :
411 : // Valid IPv6.
412 1 : s << MakeSpan(ParseHex("02" // network type (IPv6)
413 : "10" // address length
414 1 : "0102030405060708090a0b0c0d0e0f10")); // address
415 1 : s >> addr;
416 2 : BOOST_CHECK(addr.IsValid());
417 2 : BOOST_CHECK(addr.IsIPv6());
418 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
419 2 : BOOST_CHECK_EQUAL(addr.ToString(), "102:304:506:708:90a:b0c:d0e:f10");
420 2 : BOOST_REQUIRE(s.empty());
421 :
422 : // Valid IPv6, contains embedded "internal".
423 1 : s << MakeSpan(ParseHex(
424 : "02" // network type (IPv6)
425 : "10" // address length
426 1 : "fd6b88c08724ca978112ca1bbdcafac2")); // address: 0xfd + sha256("bitcoin")[0:5] +
427 : // sha256(name)[0:10]
428 1 : s >> addr;
429 2 : BOOST_CHECK(addr.IsInternal());
430 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
431 2 : BOOST_CHECK_EQUAL(addr.ToString(), "zklycewkdo64v6wc.internal");
432 2 : BOOST_REQUIRE(s.empty());
433 :
434 : // Invalid IPv6, with bogus length.
435 1 : s << MakeSpan(ParseHex("02" // network type (IPv6)
436 : "04" // address length
437 1 : "00")); // address
438 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
439 : HasReason("BIP155 IPv6 address with length 4 (should be 16)"));
440 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
441 1 : s.clear();
442 :
443 : // Invalid IPv6, contains embedded IPv4.
444 1 : s << MakeSpan(ParseHex("02" // network type (IPv6)
445 : "10" // address length
446 1 : "00000000000000000000ffff01020304")); // address
447 1 : s >> addr;
448 2 : BOOST_CHECK(!addr.IsValid());
449 2 : BOOST_REQUIRE(s.empty());
450 :
451 : // Invalid IPv6, contains embedded TORv2.
452 1 : s << MakeSpan(ParseHex("02" // network type (IPv6)
453 : "10" // address length
454 1 : "fd87d87eeb430102030405060708090a")); // address
455 1 : s >> addr;
456 2 : BOOST_CHECK(!addr.IsValid());
457 2 : BOOST_REQUIRE(s.empty());
458 :
459 : // Valid TORv2.
460 1 : s << MakeSpan(ParseHex("03" // network type (TORv2)
461 : "0a" // address length
462 1 : "f1f2f3f4f5f6f7f8f9fa")); // address
463 1 : s >> addr;
464 2 : BOOST_CHECK(addr.IsValid());
465 2 : BOOST_CHECK(addr.IsTor());
466 2 : BOOST_CHECK(addr.IsAddrV1Compatible());
467 2 : BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
468 2 : BOOST_REQUIRE(s.empty());
469 :
470 : // Invalid TORv2, with bogus length.
471 1 : s << MakeSpan(ParseHex("03" // network type (TORv2)
472 : "07" // address length
473 1 : "00")); // address
474 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
475 : HasReason("BIP155 TORv2 address with length 7 (should be 10)"));
476 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
477 1 : s.clear();
478 :
479 : // Valid TORv3.
480 1 : s << MakeSpan(ParseHex("04" // network type (TORv3)
481 : "20" // address length
482 : "79bcc625184b05194975c28b66b66b04" // address
483 : "69f7f6556fb1ac3189a79b40dda32f1f"
484 1 : ));
485 1 : s >> addr;
486 2 : BOOST_CHECK(addr.IsValid());
487 2 : BOOST_CHECK(addr.IsTor());
488 2 : BOOST_CHECK(!addr.IsAddrV1Compatible());
489 2 : BOOST_CHECK_EQUAL(addr.ToString(),
490 : "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion");
491 2 : BOOST_REQUIRE(s.empty());
492 :
493 : // Invalid TORv3, with bogus length.
494 1 : s << MakeSpan(ParseHex("04" // network type (TORv3)
495 : "00" // address length
496 : "00" // address
497 1 : ));
498 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
499 : HasReason("BIP155 TORv3 address with length 0 (should be 32)"));
500 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
501 1 : s.clear();
502 :
503 : // Valid I2P.
504 1 : s << MakeSpan(ParseHex("05" // network type (I2P)
505 : "20" // address length
506 : "a2894dabaec08c0051a481a6dac88b64" // address
507 1 : "f98232ae42d4b6fd2fa81952dfe36a87"));
508 1 : s >> addr;
509 2 : BOOST_CHECK(addr.IsValid());
510 2 : BOOST_CHECK(addr.IsI2P());
511 2 : BOOST_CHECK(!addr.IsAddrV1Compatible());
512 2 : BOOST_CHECK_EQUAL(addr.ToString(),
513 : "ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p");
514 2 : BOOST_REQUIRE(s.empty());
515 :
516 : // Invalid I2P, with bogus length.
517 1 : s << MakeSpan(ParseHex("05" // network type (I2P)
518 : "03" // address length
519 : "00" // address
520 1 : ));
521 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
522 : HasReason("BIP155 I2P address with length 3 (should be 32)"));
523 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
524 1 : s.clear();
525 :
526 : // Valid CJDNS.
527 1 : s << MakeSpan(ParseHex("06" // network type (CJDNS)
528 : "10" // address length
529 : "fc000001000200030004000500060007" // address
530 1 : ));
531 1 : s >> addr;
532 2 : BOOST_CHECK(addr.IsValid());
533 2 : BOOST_CHECK(addr.IsCJDNS());
534 2 : BOOST_CHECK(!addr.IsAddrV1Compatible());
535 2 : BOOST_CHECK_EQUAL(addr.ToString(), "fc00:1:2:3:4:5:6:7");
536 2 : BOOST_REQUIRE(s.empty());
537 :
538 : // Invalid CJDNS, with bogus length.
539 1 : s << MakeSpan(ParseHex("06" // network type (CJDNS)
540 : "01" // address length
541 : "00" // address
542 1 : ));
543 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
544 : HasReason("BIP155 CJDNS address with length 1 (should be 16)"));
545 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
546 1 : s.clear();
547 :
548 : // Unknown, with extreme length.
549 1 : s << MakeSpan(ParseHex("aa" // network type (unknown)
550 : "fe00000002" // address length (CompactSize's MAX_SIZE)
551 : "01020304050607" // address
552 1 : ));
553 5 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
554 : HasReason("Address too long: 33554432 > 512"));
555 2 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
556 1 : s.clear();
557 :
558 : // Unknown, with reasonable length.
559 1 : s << MakeSpan(ParseHex("aa" // network type (unknown)
560 : "04" // address length
561 : "01020304" // address
562 1 : ));
563 1 : s >> addr;
564 2 : BOOST_CHECK(!addr.IsValid());
565 2 : BOOST_REQUIRE(s.empty());
566 :
567 : // Unknown, with zero length.
568 1 : s << MakeSpan(ParseHex("aa" // network type (unknown)
569 : "00" // address length
570 : "" // address
571 1 : ));
572 1 : s >> addr;
573 2 : BOOST_CHECK(!addr.IsValid());
574 2 : BOOST_REQUIRE(s.empty());
575 1 : }
576 :
577 : // prior to PR #14728, this test triggers an undefined behavior
578 2 : BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
579 : {
580 : // set up local addresses; all that's necessary to reproduce the bug is
581 : // that a normal IPv4 address is among the entries, but if this address is
582 : // !IsRoutable the undefined behavior is easier to trigger deterministically
583 1 : {
584 1 : LOCK(cs_mapLocalHost);
585 1 : in_addr ipv4AddrLocal;
586 1 : ipv4AddrLocal.s_addr = 0x0100007f;
587 2 : CNetAddr addr = CNetAddr(ipv4AddrLocal);
588 1 : LocalServiceInfo lsi;
589 1 : lsi.nScore = 23;
590 1 : lsi.nPort = 42;
591 1 : mapLocalHost[addr] = lsi;
592 : }
593 :
594 : // create a peer with an IPv4 address
595 1 : in_addr ipv4AddrPeer;
596 1 : ipv4AddrPeer.s_addr = 0xa0b0c001;
597 2 : CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
598 2 : std::unique_ptr<CNode> pnode = std::make_unique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, std::string{}, false);
599 1 : pnode->fSuccessfullyConnected.store(true);
600 :
601 : // the peer claims to be reaching us via IPv6
602 1 : in6_addr ipv6AddrLocal;
603 1 : memset(ipv6AddrLocal.s6_addr, 0, 16);
604 1 : ipv6AddrLocal.s6_addr[0] = 0xcc;
605 3 : CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
606 1 : pnode->SetAddrLocal(addrLocal);
607 :
608 : // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
609 1 : AdvertiseLocal(&*pnode);
610 :
611 : // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
612 2 : BOOST_CHECK(1);
613 1 : }
614 :
615 :
616 2 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
617 : {
618 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
619 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
620 1 : BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
621 :
622 1 : SetReachable(NET_IPV4, false);
623 1 : SetReachable(NET_IPV6, false);
624 1 : SetReachable(NET_ONION, false);
625 :
626 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
627 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
628 1 : BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
629 :
630 1 : SetReachable(NET_IPV4, true);
631 1 : SetReachable(NET_IPV6, true);
632 1 : SetReachable(NET_ONION, true);
633 :
634 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
635 1 : BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
636 1 : BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
637 1 : }
638 :
639 2 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
640 : {
641 1 : BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
642 1 : BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
643 :
644 1 : SetReachable(NET_UNROUTABLE, false);
645 1 : SetReachable(NET_INTERNAL, false);
646 :
647 1 : BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); // Ignored for both networks
648 1 : BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
649 1 : }
650 :
651 2 : CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
652 : {
653 2 : unsigned char ip[] = {p1, p2, p3, p4};
654 :
655 2 : struct sockaddr_in sa;
656 2 : memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
657 2 : memcpy(&(sa.sin_addr), &ip, sizeof(ip));
658 2 : return CNetAddr(sa.sin_addr);
659 : }
660 :
661 :
662 2 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
663 : {
664 1 : CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
665 :
666 1 : SetReachable(NET_IPV4, true);
667 1 : BOOST_CHECK_EQUAL(IsReachable(addr), true);
668 :
669 1 : SetReachable(NET_IPV4, false);
670 1 : BOOST_CHECK_EQUAL(IsReachable(addr), false);
671 :
672 1 : SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
673 1 : }
674 :
675 :
676 2 : BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
677 : {
678 1 : CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
679 :
680 1 : SetReachable(NET_IPV4, true);
681 :
682 1 : BOOST_CHECK_EQUAL(IsLocal(addr), false);
683 1 : BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
684 1 : BOOST_CHECK_EQUAL(IsLocal(addr), true);
685 :
686 1 : RemoveLocal(addr);
687 1 : BOOST_CHECK_EQUAL(IsLocal(addr), false);
688 1 : }
689 :
690 2 : BOOST_AUTO_TEST_CASE(PoissonNextSend)
691 : {
692 1 : g_mock_deterministic_tests = true;
693 :
694 1 : int64_t now = 5000;
695 1 : int average_interval_seconds = 600;
696 :
697 1 : auto poisson = ::PoissonNextSend(now, average_interval_seconds);
698 1 : std::chrono::microseconds poisson_chrono = ::PoissonNextSend(std::chrono::microseconds{now}, std::chrono::seconds{average_interval_seconds});
699 :
700 1 : BOOST_CHECK_EQUAL(poisson, poisson_chrono.count());
701 :
702 1 : g_mock_deterministic_tests = false;
703 1 : }
704 :
705 : BOOST_AUTO_TEST_SUITE_END()
|