LCOV - code coverage report
Current view: top level - src - netaddress.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 495 556 89.0 %
Date: 2026-06-25 07:23:51 Functions: 80 88 90.9 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include <netaddress.h>
       7             : #include <netbase.h>
       8             : #include <crypto/common.h>
       9             : #include <crypto/sha3.h>
      10             : #include <hash.h>
      11             : #include <prevector.h>
      12             : #include <tinyformat.h>
      13             : #include <util/strencodings.h>
      14             : #include <util/string.h>
      15             : 
      16             : #include <algorithm>
      17             : #include <array>
      18             : #include <cstdint>
      19             : #include <ios>
      20             : #include <tuple>
      21             : 
      22          40 : CNetAddr::BIP155Network CNetAddr::GetBIP155Network() const
      23             : {
      24          40 :     switch (m_net) {
      25             :     case NET_IPV4:
      26          23 :         return BIP155Network::IPV4;
      27             :     case NET_IPV6:
      28          14 :         return BIP155Network::IPV6;
      29             :     case NET_ONION:
      30           3 :         return BIP155Network::TORV3;
      31             :     case NET_I2P:
      32           0 :         return BIP155Network::I2P;
      33             :     case NET_CJDNS:
      34           0 :         return BIP155Network::CJDNS;
      35             :     case NET_INTERNAL:   // should have been handled before calling this function
      36             :     case NET_UNROUTABLE: // m_net is never and should not be set to NET_UNROUTABLE
      37             :     case NET_MAX:        // m_net is never and should not be set to NET_MAX
      38           0 :         assert(false);
      39             :     } // no default case, so the compiler can warn about missing cases
      40             : 
      41           0 :     assert(false);
      42          40 : }
      43             : 
      44          56 : bool CNetAddr::SetNetFromBIP155Network(uint8_t possible_bip155_net, size_t address_size)
      45             : {
      46          56 :     switch (possible_bip155_net) {
      47             :     case BIP155Network::IPV4:
      48          25 :         if (address_size == ADDR_IPV4_SIZE) {
      49          24 :             m_net = NET_IPV4;
      50          24 :             return true;
      51             :         }
      52           5 :         throw std::ios_base::failure(
      53           1 :             strprintf("BIP155 IPv4 address with length %u (should be %u)", address_size,
      54             :                       ADDR_IPV4_SIZE));
      55             :     case BIP155Network::IPV6:
      56          17 :         if (address_size == ADDR_IPV6_SIZE) {
      57          16 :             m_net = NET_IPV6;
      58          16 :             return true;
      59             :         }
      60           1 :         throw std::ios_base::failure(
      61           1 :             strprintf("BIP155 IPv6 address with length %u (should be %u)", address_size,
      62             :                       ADDR_IPV6_SIZE));
      63             :     case BIP155Network::TORV3:
      64           4 :         if (address_size == ADDR_TORV3_SIZE) {
      65           3 :             m_net = NET_ONION;
      66           3 :             return true;
      67             :         }
      68           1 :         throw std::ios_base::failure(
      69           1 :             strprintf("BIP155 TORv3 address with length %u (should be %u)", address_size,
      70             :                       ADDR_TORV3_SIZE));
      71             :     case BIP155Network::I2P:
      72           2 :         if (address_size == ADDR_I2P_SIZE) {
      73           1 :             m_net = NET_I2P;
      74           1 :             return true;
      75             :         }
      76           1 :         throw std::ios_base::failure(
      77           1 :             strprintf("BIP155 I2P address with length %u (should be %u)", address_size,
      78             :                       ADDR_I2P_SIZE));
      79             :     case BIP155Network::CJDNS:
      80           3 :         if (address_size == ADDR_CJDNS_SIZE) {
      81           2 :             m_net = NET_CJDNS;
      82           2 :             return true;
      83             :         }
      84           1 :         throw std::ios_base::failure(
      85           1 :             strprintf("BIP155 CJDNS address with length %u (should be %u)", address_size,
      86             :                       ADDR_CJDNS_SIZE));
      87             :     }
      88             : 
      89             :     // Don't throw on addresses with unknown network ids (maybe from the future).
      90             :     // Instead silently drop them and have the unserialization code consume
      91             :     // subsequent ones which may be known to us.
      92           5 :     return false;
      93          56 : }
      94             : 
      95             : bool fAllowPrivateNet = DEFAULT_ALLOWPRIVATENET;
      96             : 
      97             : /**
      98             :  * Construct an unspecified IPv6 network address (::/128).
      99             :  *
     100             :  * @note This address is considered invalid by CNetAddr::IsValid()
     101             :  */
     102       58640 : CNetAddr::CNetAddr() = default;
     103             : 
     104           3 : void CNetAddr::SetIP(const CNetAddr& ipIn)
     105             : {
     106             :     // Size check.
     107           3 :     switch (ipIn.m_net) {
     108             :     case NET_IPV4:
     109           2 :         assert(ipIn.m_addr.size() == ADDR_IPV4_SIZE);
     110           2 :         break;
     111             :     case NET_IPV6:
     112           1 :         assert(ipIn.m_addr.size() == ADDR_IPV6_SIZE);
     113           1 :         break;
     114             :     case NET_ONION:
     115           0 :         assert(ipIn.m_addr.size() == ADDR_TORV3_SIZE);
     116           0 :         break;
     117             :     case NET_I2P:
     118           0 :         assert(ipIn.m_addr.size() == ADDR_I2P_SIZE);
     119           0 :         break;
     120             :     case NET_CJDNS:
     121           0 :         assert(ipIn.m_addr.size() == ADDR_CJDNS_SIZE);
     122           0 :         break;
     123             :     case NET_INTERNAL:
     124           0 :         assert(ipIn.m_addr.size() == ADDR_INTERNAL_SIZE);
     125           0 :         break;
     126             :     case NET_UNROUTABLE:
     127             :     case NET_MAX:
     128           0 :         assert(false);
     129             :     } // no default case, so the compiler can warn about missing cases
     130             : 
     131           3 :     m_net = ipIn.m_net;
     132           3 :     m_addr = ipIn.m_addr;
     133           3 : }
     134             : 
     135         849 : void CNetAddr::SetLegacyIPv6(Span<const uint8_t> ipv6)
     136             : {
     137         849 :     assert(ipv6.size() == ADDR_IPV6_SIZE);
     138             : 
     139         849 :     size_t skip{0};
     140             : 
     141         849 :     if (HasPrefix(ipv6, IPV4_IN_IPV6_PREFIX)) {
     142             :         // IPv4-in-IPv6
     143         267 :         m_net = NET_IPV4;
     144         267 :         skip = sizeof(IPV4_IN_IPV6_PREFIX);
     145         849 :     } else if (HasPrefix(ipv6, TORV2_IN_IPV6_PREFIX)) {
     146             :         // TORv2-in-IPv6 (unsupported). Unserialize as !IsValid(), thus ignoring them.
     147             :         // Mimic a default-constructed CNetAddr object which is !IsValid() and thus
     148             :         // will not be gossiped, but continue reading next addresses from the stream.
     149           0 :         m_net = NET_IPV6;
     150           0 :         m_addr.assign(ADDR_IPV6_SIZE, 0x0);
     151           0 :         return;
     152         582 :     } else if (HasPrefix(ipv6, INTERNAL_IN_IPV6_PREFIX)) {
     153             :         // Internal-in-IPv6
     154           1 :         m_net = NET_INTERNAL;
     155           1 :         skip = sizeof(INTERNAL_IN_IPV6_PREFIX);
     156           1 :     } else {
     157             :         // IPv6
     158         581 :         m_net = NET_IPV6;
     159             :     }
     160             : 
     161         849 :     m_addr.assign(ipv6.begin() + skip, ipv6.end());
     162         849 : }
     163             : 
     164             : /**
     165             :  * Create an "internal" address that represents a name or FQDN. AddrMan uses
     166             :  * these fake addresses to keep track of which DNS seeds were used.
     167             :  * @returns Whether or not the operation was successful.
     168             :  * @see NET_INTERNAL, INTERNAL_IN_IPV6_PREFIX, CNetAddr::IsInternal(), CNetAddr::IsRFC4193()
     169             :  */
     170         207 : bool CNetAddr::SetInternal(const std::string &name)
     171             : {
     172         207 :     if (name.empty()) {
     173           0 :         return false;
     174             :     }
     175         207 :     m_net = NET_INTERNAL;
     176         207 :     unsigned char hash[32] = {};
     177         207 :     CSHA256().Write((const unsigned char*)name.data(), name.size()).Finalize(hash);
     178         207 :     m_addr.assign(hash, hash + ADDR_INTERNAL_SIZE);
     179         207 :     return true;
     180         207 : }
     181             : 
     182             : namespace torv3 {
     183             : // https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt?id=7116c9cdaba248aae07a3f1d0e15d9dd102f62c5#n2175
     184             : static constexpr size_t CHECKSUM_LEN = 2;
     185             : static const unsigned char VERSION[] = {3};
     186             : static constexpr size_t TOTAL_LEN = ADDR_TORV3_SIZE + CHECKSUM_LEN + sizeof(VERSION);
     187             : 
     188          50 : static void Checksum(Span<const uint8_t> addr_pubkey, uint8_t (&checksum)[CHECKSUM_LEN])
     189             : {
     190             :     // TORv3 CHECKSUM = H(".onion checksum" | PUBKEY | VERSION)[:2]
     191             :     static const unsigned char prefix[] = ".onion checksum";
     192             :     static constexpr size_t prefix_len = 15;
     193             : 
     194          50 :     SHA3_256 hasher;
     195             : 
     196          50 :     hasher.Write(Span{prefix}.first(prefix_len));
     197          50 :     hasher.Write(addr_pubkey);
     198          50 :     hasher.Write(VERSION);
     199             : 
     200             :     uint8_t checksum_full[SHA3_256::OUTPUT_SIZE];
     201             : 
     202          50 :     hasher.Finalize(checksum_full);
     203             : 
     204          50 :     memcpy(checksum, checksum_full, sizeof(checksum));
     205          50 : }
     206             : 
     207             : }; // namespace torv3
     208             : 
     209       14016 : bool CNetAddr::SetSpecial(const std::string& addr)
     210             : {
     211       14016 :     if (!ContainsNoNUL(addr)) {
     212           2 :         return false;
     213             :     }
     214             : 
     215       14014 :     if (SetTor(addr)) {
     216          25 :         return true;
     217             :     }
     218             : 
     219       13989 :     if (SetI2P(addr)) {
     220          13 :         return true;
     221             :     }
     222             : 
     223       13976 :     return false;
     224       14016 : }
     225             : 
     226       14014 : bool CNetAddr::SetTor(const std::string& addr)
     227             : {
     228             :     static const char* suffix{".onion"};
     229             :     static constexpr size_t suffix_len{6};
     230             : 
     231       14014 :     if (addr.size() <= suffix_len || addr.substr(addr.size() - suffix_len) != suffix) {
     232       13982 :         return false;
     233             :     }
     234             : 
     235          32 :     auto input = DecodeBase32(std::string_view{addr}.substr(0, addr.size() - suffix_len));
     236             : 
     237          32 :     if (!input) {
     238           1 :         return false;
     239             :     }
     240             : 
     241          31 :     if (input->size() == torv3::TOTAL_LEN) {
     242          27 :         Span<const uint8_t> input_pubkey{input->data(), ADDR_TORV3_SIZE};
     243          27 :         Span<const uint8_t> input_checksum{input->data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
     244          27 :         Span<const uint8_t> input_version{input->data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)};
     245             : 
     246          27 :         if (input_version != torv3::VERSION) {
     247           1 :             return false;
     248             :         }
     249             : 
     250             :         uint8_t calculated_checksum[torv3::CHECKSUM_LEN];
     251          26 :         torv3::Checksum(input_pubkey, calculated_checksum);
     252             : 
     253          26 :         if (input_checksum != calculated_checksum) {
     254           1 :             return false;
     255             :         }
     256             : 
     257          25 :         m_net = NET_ONION;
     258          25 :         m_addr.assign(input_pubkey.begin(), input_pubkey.end());
     259          25 :         return true;
     260             :     }
     261             : 
     262           4 :     return false;
     263       14014 : }
     264             : 
     265       13989 : bool CNetAddr::SetI2P(const std::string& addr)
     266             : {
     267             :     // I2P addresses that we support consist of 52 base32 characters + ".b32.i2p".
     268             :     static constexpr size_t b32_len{52};
     269             :     static const char* suffix{".b32.i2p"};
     270             :     static constexpr size_t suffix_len{8};
     271             : 
     272       13989 :     if (addr.size() != b32_len + suffix_len || ToLower(addr.substr(b32_len)) != suffix) {
     273       13975 :         return false;
     274             :     }
     275             : 
     276             :     // Remove the ".b32.i2p" suffix and pad to a multiple of 8 chars, so DecodeBase32()
     277             :     // can decode it.
     278          14 :     const std::string b32_padded = addr.substr(0, b32_len) + "====";
     279             : 
     280          14 :     auto address_bytes = DecodeBase32(b32_padded);
     281             : 
     282          14 :     if (!address_bytes || address_bytes->size() != ADDR_I2P_SIZE) {
     283           1 :         return false;
     284             :     }
     285             : 
     286          13 :     m_net = NET_I2P;
     287          13 :     m_addr.assign(address_bytes->begin(), address_bytes->end());
     288             : 
     289          13 :     return true;
     290       13989 : }
     291             : 
     292       27623 : CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
     293       13807 : {
     294             :     m_net = NET_IPV4;
     295             :     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&ipv4Addr);
     296             :     m_addr.assign(ptr, ptr + ADDR_IPV4_SIZE);
     297       13807 : }
     298             : 
     299        1147 : CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
     300         570 : {
     301             :     SetLegacyIPv6({reinterpret_cast<const uint8_t*>(&ipv6Addr), sizeof(ipv6Addr)});
     302             :     m_scope_id = scope;
     303         570 : }
     304             : 
     305          10 : bool CNetAddr::IsBindAny() const
     306             : {
     307          10 :     if (!IsIPv4() && !IsIPv6()) {
     308           3 :         return false;
     309             :     }
     310          32 :     return std::all_of(m_addr.begin(), m_addr.end(), [](uint8_t b) { return b == 0; });
     311          10 : }
     312             : 
     313      152638 : bool CNetAddr::IsRFC1918() const
     314             : {
     315      304845 :     return IsIPv4() && (
     316      152207 :         m_addr[0] == 10 ||
     317      304383 :         (m_addr[0] == 192 && m_addr[1] == 168) ||
     318      152191 :         (m_addr[0] == 172 && m_addr[1] >= 16 && m_addr[1] <= 31));
     319             : }
     320             : 
     321      152623 : bool CNetAddr::IsRFC2544() const
     322             : {
     323      152895 :     return IsIPv4() && m_addr[0] == 198 && (m_addr[1] == 18 || m_addr[1] == 19);
     324             : }
     325             : 
     326      152622 : bool CNetAddr::IsRFC3927() const
     327             : {
     328      152622 :     return IsIPv4() && HasPrefix(m_addr, std::array<uint8_t, 2>{169, 254});
     329             : }
     330             : 
     331      152618 : bool CNetAddr::IsRFC6598() const
     332             : {
     333      152618 :     return IsIPv4() && m_addr[0] == 100 && m_addr[1] >= 64 && m_addr[1] <= 127;
     334             : }
     335             : 
     336      152618 : bool CNetAddr::IsRFC5737() const
     337             : {
     338      304805 :     return IsIPv4() && (HasPrefix(m_addr, std::array<uint8_t, 3>{192, 0, 2}) ||
     339      152187 :                         HasPrefix(m_addr, std::array<uint8_t, 3>{198, 51, 100}) ||
     340      152187 :                         HasPrefix(m_addr, std::array<uint8_t, 3>{203, 0, 113}));
     341             : }
     342             : 
     343      153575 : bool CNetAddr::IsRFC3849() const
     344             : {
     345      153575 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 4>{0x20, 0x01, 0x0D, 0xB8});
     346             : }
     347             : 
     348         145 : bool CNetAddr::IsRFC3964() const
     349             : {
     350         145 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 2>{0x20, 0x02});
     351             : }
     352             : 
     353         144 : bool CNetAddr::IsRFC6052() const
     354             : {
     355         204 :     return IsIPv6() &&
     356          60 :            HasPrefix(m_addr, std::array<uint8_t, 12>{0x00, 0x64, 0xFF, 0x9B, 0x00, 0x00,
     357             :                                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
     358             : }
     359             : 
     360         165 : bool CNetAddr::IsRFC4380() const
     361             : {
     362         165 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 4>{0x20, 0x01, 0x00, 0x00});
     363             : }
     364             : 
     365      152619 : bool CNetAddr::IsRFC4862() const
     366             : {
     367      152619 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 8>{0xFE, 0x80, 0x00, 0x00,
     368             :                                                                 0x00, 0x00, 0x00, 0x00});
     369             : }
     370             : 
     371      152619 : bool CNetAddr::IsRFC4193() const
     372             : {
     373      152619 :     return IsIPv6() && (m_addr[0] & 0xFE) == 0xFC;
     374             : }
     375             : 
     376         145 : bool CNetAddr::IsRFC6145() const
     377             : {
     378         206 :     return IsIPv6() &&
     379          61 :            HasPrefix(m_addr, std::array<uint8_t, 12>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     380             :                                                      0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00});
     381             : }
     382             : 
     383      152619 : bool CNetAddr::IsRFC4843() const
     384             : {
     385      152662 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 3>{0x20, 0x01, 0x00}) &&
     386          43 :            (m_addr[3] & 0xF0) == 0x10;
     387             : }
     388             : 
     389      152619 : bool CNetAddr::IsRFC7343() const
     390             : {
     391      152662 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 3>{0x20, 0x01, 0x00}) &&
     392          43 :            (m_addr[3] & 0xF0) == 0x20;
     393             : }
     394             : 
     395           2 : bool CNetAddr::IsHeNet() const
     396             : {
     397           2 :     return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 4>{0x20, 0x01, 0x04, 0x70});
     398             : }
     399             : 
     400      167910 : bool CNetAddr::IsLocal() const
     401             : {
     402             :     // IPv4 loopback (127.0.0.0/8 or 0.0.0.0/8)
     403      167910 :     if (IsIPv4() && (m_addr[0] == 127 || m_addr[0] == 0)) {
     404          28 :         return true;
     405             :     }
     406             : 
     407             :     // IPv6 loopback (::1/128)
     408             :     static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
     409      167882 :     if (IsIPv6() && memcmp(m_addr.data(), pchLocal, sizeof(pchLocal)) == 0) {
     410           2 :         return true;
     411             :     }
     412             : 
     413      167880 :     return false;
     414      167910 : }
     415             : 
     416             : /**
     417             :  * @returns Whether or not this network address is a valid address that @a could
     418             :  *          be used to refer to an actual host.
     419             :  *
     420             :  * @note A valid address may or may not be publicly routable on the global
     421             :  *       internet. As in, the set of valid addresses is a superset of the set of
     422             :  *       publicly routable addresses.
     423             :  *
     424             :  * @see CNetAddr::IsRoutable()
     425             :  */
     426      153743 : bool CNetAddr::IsValid() const
     427             : {
     428             :     // unspecified IPv6 address (::/128)
     429      153743 :     unsigned char ipNone6[16] = {};
     430      153743 :     if (IsIPv6() && memcmp(m_addr.data(), ipNone6, sizeof(ipNone6)) == 0) {
     431         168 :         return false;
     432             :     }
     433             : 
     434      153575 :     if (IsCJDNS() && !HasCJDNSPrefix()) {
     435           1 :         return false;
     436             :     }
     437             : 
     438             :     // documentation IPv6 address
     439      153574 :     if (IsRFC3849())
     440           0 :         return false;
     441             : 
     442      153574 :     if (IsInternal())
     443           1 :         return false;
     444             : 
     445      153573 :     if (IsIPv4()) {
     446      153033 :         const uint32_t addr = ReadBE32(m_addr.data());
     447      153033 :         if (addr == INADDR_ANY || addr == INADDR_NONE) {
     448          12 :             return false;
     449             :         }
     450      153021 :     }
     451             : 
     452      153561 :     return true;
     453      153743 : }
     454             : 
     455             : /**
     456             :  * @returns Whether or not this network address is publicly routable on the
     457             :  *          global internet.
     458             :  *
     459             :  * @note A routable address is always valid. As in, the set of routable addresses
     460             :  *       is a subset of the set of valid addresses.
     461             :  *
     462             :  * @see CNetAddr::IsValid()
     463             :  */
     464      152727 : bool CNetAddr::IsRoutable() const
     465             : {
     466      152727 :     if (!IsValid())
     467          92 :         return false;
     468      152635 :     if (!fAllowPrivateNet && IsRFC1918())
     469          14 :         return false;
     470      152621 :     return !(IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || IsRFC4193() || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal());
     471      152727 : }
     472             : 
     473             : /**
     474             :  * @returns Whether or not this is a dummy address that represents a name.
     475             :  *
     476             :  * @see CNetAddr::SetInternal(const std::string &)
     477             :  */
     478      414383 : bool CNetAddr::IsInternal() const
     479             : {
     480      414383 :    return m_net == NET_INTERNAL;
     481             : }
     482             : 
     483       50381 : bool CNetAddr::IsAddrV1Compatible() const
     484             : {
     485       50381 :     switch (m_net) {
     486             :     case NET_IPV4:
     487             :     case NET_IPV6:
     488             :     case NET_INTERNAL:
     489       50343 :         return true;
     490             :     case NET_ONION:
     491             :     case NET_I2P:
     492             :     case NET_CJDNS:
     493          38 :         return false;
     494             :     case NET_UNROUTABLE: // m_net is never and should not be set to NET_UNROUTABLE
     495             :     case NET_MAX:        // m_net is never and should not be set to NET_MAX
     496           0 :         assert(false);
     497             :     } // no default case, so the compiler can warn about missing cases
     498             : 
     499           0 :     assert(false);
     500       50381 : }
     501             : 
     502       42349 : enum Network CNetAddr::GetNetwork() const
     503             : {
     504       42349 :     if (IsInternal())
     505           1 :         return NET_INTERNAL;
     506             : 
     507       42348 :     if (!IsRoutable())
     508           6 :         return NET_UNROUTABLE;
     509             : 
     510       42342 :     return m_net;
     511       42349 : }
     512             : 
     513        4723 : static std::string IPv4ToString(Span<const uint8_t> a)
     514             : {
     515        4723 :     return strprintf("%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
     516             : }
     517             : 
     518             : // Return an IPv6 address text representation with zero compression as described in RFC 5952
     519             : // ("A Recommendation for IPv6 Address Text Representation").
     520         171 : static std::string IPv6ToString(Span<const uint8_t> a, uint32_t scope_id)
     521             : {
     522         171 :     assert(a.size() == ADDR_IPV6_SIZE);
     523         171 :     const std::array groups{
     524        1368 :         ReadBE16(&a[0]),
     525         171 :         ReadBE16(&a[2]),
     526         171 :         ReadBE16(&a[4]),
     527         171 :         ReadBE16(&a[6]),
     528         171 :         ReadBE16(&a[8]),
     529         171 :         ReadBE16(&a[10]),
     530         171 :         ReadBE16(&a[12]),
     531         171 :         ReadBE16(&a[14]),
     532             :     };
     533             : 
     534             :     // The zero compression implementation is inspired by Rust's std::net::Ipv6Addr, see
     535             :     // https://github.com/rust-lang/rust/blob/cc4103089f40a163f6d143f06359cba7043da29b/library/std/src/net/ip.rs#L1635-L1683
     536         342 :     struct ZeroSpan {
     537         342 :         size_t start_index{0};
     538         342 :         size_t len{0};
     539             :     };
     540             : 
     541             :     // Find longest sequence of consecutive all-zero fields. Use first zero sequence if two or more
     542             :     // zero sequences of equal length are found.
     543         171 :     ZeroSpan longest, current;
     544        1539 :     for (size_t i{0}; i < groups.size(); ++i) {
     545        1368 :         if (groups[i] != 0) {
     546         429 :             current = {i + 1, 0};
     547         429 :             continue;
     548             :         }
     549         939 :         current.len += 1;
     550         939 :         if (current.len > longest.len) {
     551         916 :             longest = current;
     552         916 :         }
     553         939 :     }
     554             : 
     555         171 :     std::string r;
     556         171 :     r.reserve(39);
     557        1539 :     for (size_t i{0}; i < groups.size(); ++i) {
     558             :         // Replace the longest sequence of consecutive all-zero fields with two colons ("::").
     559        1368 :         if (longest.len >= 2 && i >= longest.start_index && i < longest.start_index + longest.len) {
     560         908 :             if (i == longest.start_index) {
     561         133 :                 r += "::";
     562         133 :             }
     563         908 :             continue;
     564             :         }
     565         460 :         r += strprintf("%s%x", ((!r.empty() && r.back() != ':') ? ":" : ""), groups[i]);
     566         460 :     }
     567             : 
     568         171 :     if (scope_id != 0) {
     569           1 :         r += strprintf("%%%u", scope_id);
     570           1 :     }
     571             : 
     572         171 :     return r;
     573         171 : }
     574             : 
     575          24 : std::string OnionToString(Span<const uint8_t> addr)
     576             : {
     577             :     uint8_t checksum[torv3::CHECKSUM_LEN];
     578          24 :     torv3::Checksum(addr, checksum);
     579             :     // TORv3 onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion"
     580          24 :     prevector<torv3::TOTAL_LEN, uint8_t> address{addr.begin(), addr.end()};
     581          24 :     address.insert(address.end(), checksum, checksum + torv3::CHECKSUM_LEN);
     582          24 :     address.insert(address.end(), torv3::VERSION, torv3::VERSION + sizeof(torv3::VERSION));
     583          24 :     return EncodeBase32(address) + ".onion";
     584          24 : }
     585             : 
     586        4940 : std::string CNetAddr::ToStringAddr() const
     587             : {
     588        4940 :     switch (m_net) {
     589             :     case NET_IPV4:
     590        4723 :         return IPv4ToString(m_addr);
     591             :     case NET_IPV6: {
     592         161 :         return IPv6ToString(m_addr, m_scope_id);
     593             :     }
     594             :     case NET_ONION:
     595          21 :         return OnionToString(m_addr);
     596             :     case NET_I2P:
     597          23 :         return EncodeBase32(m_addr, false /* don't pad with = */) + ".b32.i2p";
     598             :     case NET_CJDNS:
     599          10 :         return IPv6ToString(m_addr, 0);
     600             :     case NET_INTERNAL:
     601           2 :         return EncodeBase32(m_addr) + ".internal";
     602             :     case NET_UNROUTABLE: // m_net is never and should not be set to NET_UNROUTABLE
     603             :     case NET_MAX:        // m_net is never and should not be set to NET_MAX
     604           0 :         assert(false);
     605             :     } // no default case, so the compiler can warn about missing cases
     606             : 
     607           0 :     assert(false);
     608        4940 : }
     609             : 
     610       43802 : bool operator==(const CNetAddr& a, const CNetAddr& b)
     611             : {
     612       43802 :     return a.m_net == b.m_net && a.m_addr == b.m_addr;
     613             : }
     614             : 
     615        2085 : bool operator<(const CNetAddr& a, const CNetAddr& b)
     616             : {
     617        2085 :     return std::tie(a.m_net, a.m_addr) < std::tie(b.m_net, b.m_addr);
     618             : }
     619             : 
     620             : /**
     621             :  * Try to get our IPv4 address.
     622             :  *
     623             :  * @param[out] pipv4Addr The in_addr struct to which to copy.
     624             :  *
     625             :  * @returns Whether or not the operation was successful, in particular, whether
     626             :  *          or not our address was an IPv4 address.
     627             :  *
     628             :  * @see CNetAddr::IsIPv4()
     629             :  */
     630           1 : bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
     631             : {
     632           1 :     if (!IsIPv4())
     633           0 :         return false;
     634           1 :     assert(sizeof(*pipv4Addr) == m_addr.size());
     635           1 :     memcpy(pipv4Addr, m_addr.data(), m_addr.size());
     636           1 :     return true;
     637           1 : }
     638             : 
     639             : /**
     640             :  * Try to get our IPv6 (or CJDNS) address.
     641             :  *
     642             :  * @param[out] pipv6Addr The in6_addr struct to which to copy.
     643             :  *
     644             :  * @returns Whether or not the operation was successful, in particular, whether
     645             :  *          or not our address was an IPv6 address.
     646             :  *
     647             :  * @see CNetAddr::IsIPv6()
     648             :  */
     649          15 : bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
     650             : {
     651          15 :     if (!IsIPv6() && !IsCJDNS()) {
     652           0 :         return false;
     653             :     }
     654          15 :     assert(sizeof(*pipv6Addr) == m_addr.size());
     655          15 :     memcpy(pipv6Addr, m_addr.data(), m_addr.size());
     656          15 :     return true;
     657          15 : }
     658             : 
     659       55785 : bool CNetAddr::HasLinkedIPv4() const
     660             : {
     661      111570 :     return IsRoutable() && (IsIPv4() || IsRFC6145() || IsRFC6052() || IsRFC3964() || IsRFC4380());
     662             : }
     663             : 
     664       19343 : uint32_t CNetAddr::GetLinkedIPv4() const
     665             : {
     666       19343 :     if (IsIPv4()) {
     667       19339 :         return ReadBE32(m_addr.data());
     668           4 :     } else if (IsRFC6052() || IsRFC6145()) {
     669             :         // mapped IPv4, SIIT translated IPv4: the IPv4 address is the last 4 bytes of the address
     670           2 :         return ReadBE32(Span{m_addr}.last(ADDR_IPV4_SIZE).data());
     671           2 :     } else if (IsRFC3964()) {
     672             :         // 6to4 tunneled IPv4: the IPv4 address is in bytes 2-6
     673           1 :         return ReadBE32(Span{m_addr}.subspan(2, ADDR_IPV4_SIZE).data());
     674           1 :     } else if (IsRFC4380()) {
     675             :         // Teredo tunneled IPv4: the IPv4 address is in the last 4 bytes of the address, but bitflipped
     676           1 :         return ~ReadBE32(Span{m_addr}.last(ADDR_IPV4_SIZE).data());
     677             :     }
     678           0 :     assert(false);
     679       19343 : }
     680             : 
     681       36488 : Network CNetAddr::GetNetClass() const
     682             : {
     683             :     // Make sure that if we return NET_IPV6, then IsIPv6() is true. The callers expect that.
     684             : 
     685             :     // Check for "internal" first because such addresses are also !IsRoutable()
     686             :     // and we don't want to return NET_UNROUTABLE in that case.
     687       36488 :     if (IsInternal()) {
     688           2 :         return NET_INTERNAL;
     689             :     }
     690       36486 :     if (!IsRoutable()) {
     691          56 :         return NET_UNROUTABLE;
     692             :     }
     693       36430 :     if (HasLinkedIPv4()) {
     694       36361 :         return NET_IPV4;
     695             :     }
     696          69 :     return m_net;
     697       36488 : }
     698             : 
     699       49580 : std::vector<unsigned char> CNetAddr::GetAddrBytes() const
     700             : {
     701       49580 :     if (IsAddrV1Compatible()) {
     702             :         uint8_t serialized[V1_SERIALIZATION_SIZE];
     703       49551 :         SerializeV1Array(serialized);
     704       49551 :         return {std::begin(serialized), std::end(serialized)};
     705             :     }
     706          29 :     return std::vector<unsigned char>(m_addr.begin(), m_addr.end());
     707       49580 : }
     708             : 
     709             : // private extensions to enum Network, only returned by GetExtNetwork,
     710             : // and only used in GetReachabilityFrom
     711             : static const int NET_TEREDO = NET_MAX;
     712          68 : int static GetExtNetwork(const CNetAddr& addr)
     713             : {
     714          68 :     if (addr.IsRFC4380())
     715          11 :         return NET_TEREDO;
     716          57 :     return addr.GetNetwork();
     717          68 : }
     718             : 
     719             : /** Calculates a metric for how reachable (*this) is from a given partner */
     720          35 : int CNetAddr::GetReachabilityFrom(const CNetAddr& paddrPartner) const
     721             : {
     722             :     enum Reachability {
     723             :         REACH_UNREACHABLE,
     724             :         REACH_DEFAULT,
     725             :         REACH_TEREDO,
     726             :         REACH_IPV6_WEAK,
     727             :         REACH_IPV4,
     728             :         REACH_IPV6_STRONG,
     729             :         REACH_PRIVATE
     730             :     };
     731             : 
     732          35 :     if (!IsRoutable() || IsInternal())
     733           1 :         return REACH_UNREACHABLE;
     734             : 
     735          34 :     int ourNet = GetExtNetwork(*this);
     736          34 :     int theirNet = GetExtNetwork(paddrPartner);
     737          34 :     bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
     738             : 
     739          34 :     switch(theirNet) {
     740             :     case NET_IPV4:
     741           6 :         switch(ourNet) {
     742           4 :         default:       return REACH_DEFAULT;
     743           2 :         case NET_IPV4: return REACH_IPV4;
     744             :         }
     745             :     case NET_IPV6:
     746          12 :         switch(ourNet) {
     747           2 :         default:         return REACH_DEFAULT;
     748           2 :         case NET_TEREDO: return REACH_TEREDO;
     749           4 :         case NET_IPV4:   return REACH_IPV4;
     750           4 :         case NET_IPV6:   return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
     751             :         }
     752             :     case NET_ONION:
     753           2 :         switch(ourNet) {
     754           0 :         default:         return REACH_DEFAULT;
     755           0 :         case NET_IPV4:   return REACH_IPV4; // Tor users can connect to IPv4 as well
     756           2 :         case NET_ONION:    return REACH_PRIVATE;
     757             :         }
     758             :     case NET_I2P:
     759           2 :         switch (ourNet) {
     760           2 :         case NET_I2P: return REACH_PRIVATE;
     761           0 :         default: return REACH_DEFAULT;
     762             :         }
     763             :     case NET_CJDNS:
     764           6 :         switch (ourNet) {
     765           1 :         case NET_CJDNS: return REACH_PRIVATE;
     766           5 :         default: return REACH_DEFAULT;
     767             :         }
     768             :     case NET_TEREDO:
     769           6 :         switch(ourNet) {
     770           1 :         default:          return REACH_DEFAULT;
     771           1 :         case NET_TEREDO:  return REACH_TEREDO;
     772           2 :         case NET_IPV6:    return REACH_IPV6_WEAK;
     773           2 :         case NET_IPV4:    return REACH_IPV4;
     774             :         }
     775           0 :     case NET_UNROUTABLE:
     776             :     default:
     777           0 :         switch(ourNet) {
     778           0 :         default:          return REACH_DEFAULT;
     779           0 :         case NET_TEREDO:  return REACH_TEREDO;
     780           0 :         case NET_IPV6:    return REACH_IPV6_WEAK;
     781           0 :         case NET_IPV4:    return REACH_IPV4;
     782           0 :         case NET_ONION:     return REACH_PRIVATE; // either from Tor, or don't care about our address
     783             :         }
     784             :     }
     785          35 : }
     786             : 
     787       20317 : CService::CService() : port(0)
     788        8953 : {
     789       20317 : }
     790             : 
     791       14866 : CService::CService(const CNetAddr& cip, uint16_t portIn) : CNetAddr(cip), port(portIn)
     792        7433 : {
     793       14866 : }
     794             : 
     795          18 : CService::CService(const struct in_addr& ipv4Addr, uint16_t portIn) : CNetAddr(ipv4Addr), port(portIn)
     796           9 : {
     797          18 : }
     798             : 
     799          14 : CService::CService(const struct in6_addr& ipv6Addr, uint16_t portIn) : CNetAddr(ipv6Addr), port(portIn)
     800           7 : {
     801          14 : }
     802             : 
     803           0 : CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
     804           0 : {
     805           0 :     assert(addr.sin_family == AF_INET);
     806           0 : }
     807             : 
     808           0 : CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
     809           0 : {
     810           0 :    assert(addr.sin6_family == AF_INET6);
     811           0 : }
     812             : 
     813           0 : bool CService::SetSockAddr(const struct sockaddr *paddr)
     814             : {
     815           0 :     switch (paddr->sa_family) {
     816             :     case AF_INET:
     817           0 :         *this = CService(*(const struct sockaddr_in*)paddr);
     818           0 :         return true;
     819             :     case AF_INET6:
     820           0 :         *this = CService(*(const struct sockaddr_in6*)paddr);
     821           0 :         return true;
     822             :     default:
     823           0 :         return false;
     824             :     }
     825           0 : }
     826             : 
     827          16 : sa_family_t CService::GetSAFamily() const
     828             : {
     829          16 :     switch (m_net) {
     830             :     case NET_IPV4:
     831           1 :         return AF_INET;
     832             :     case NET_IPV6:
     833             :     case NET_CJDNS:
     834          15 :         return AF_INET6;
     835             :     default:
     836           0 :         return AF_UNSPEC;
     837             :     }
     838          16 : }
     839             : 
     840         327 : uint16_t CService::GetPort() const
     841             : {
     842         327 :     return port;
     843             : }
     844             : 
     845       40902 : bool operator==(const CService& a, const CService& b)
     846             : {
     847       40902 :     return static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) && a.port == b.port;
     848           0 : }
     849             : 
     850         122 : bool operator<(const CService& a, const CService& b)
     851             : {
     852         122 :     return static_cast<CNetAddr>(a) < static_cast<CNetAddr>(b) || (static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) && a.port < b.port);
     853           0 : }
     854             : 
     855             : /**
     856             :  * Obtain the IPv4/6 socket address this represents.
     857             :  *
     858             :  * @param[out] paddr The obtained socket address.
     859             :  * @param[in,out] addrlen The size, in bytes, of the address structure pointed
     860             :  *                        to by paddr. The value that's pointed to by this
     861             :  *                        parameter might change after calling this function if
     862             :  *                        the size of the corresponding address structure
     863             :  *                        changed.
     864             :  *
     865             :  * @returns Whether or not the operation was successful.
     866             :  */
     867          16 : bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
     868             : {
     869          16 :     if (IsIPv4()) {
     870           1 :         if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
     871           0 :             return false;
     872           1 :         *addrlen = sizeof(struct sockaddr_in);
     873           1 :         struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
     874           1 :         memset(paddrin, 0, *addrlen);
     875           1 :         if (!GetInAddr(&paddrin->sin_addr))
     876           0 :             return false;
     877           1 :         paddrin->sin_family = AF_INET;
     878           1 :         paddrin->sin_port = htons(port);
     879           1 :         return true;
     880             :     }
     881          15 :     if (IsIPv6() || IsCJDNS()) {
     882          15 :         if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
     883           0 :             return false;
     884          15 :         *addrlen = sizeof(struct sockaddr_in6);
     885          15 :         struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
     886          15 :         memset(paddrin6, 0, *addrlen);
     887          15 :         if (!GetIn6Addr(&paddrin6->sin6_addr))
     888           0 :             return false;
     889          15 :         paddrin6->sin6_scope_id = m_scope_id;
     890          15 :         paddrin6->sin6_family = AF_INET6;
     891          15 :         paddrin6->sin6_port = htons(port);
     892          15 :         return true;
     893             :     }
     894           0 :     return false;
     895          16 : }
     896             : 
     897             : /**
     898             :  * @returns An identifier unique to this service's address and port number.
     899             :  */
     900       49524 : std::vector<unsigned char> CService::GetKey() const
     901             : {
     902       49524 :     auto key = GetAddrBytes();
     903       49524 :     key.push_back(port / 0x100); // most significant byte of our port
     904       49524 :     key.push_back(port & 0x0FF); // least significant byte of our port
     905       49524 :     return key;
     906       49524 : }
     907             : 
     908        2493 : std::string CService::ToStringAddrPort() const
     909             : {
     910        2493 :     const auto port_str = strprintf("%u", port);
     911             : 
     912        2493 :     if (IsIPv4() || IsTor() || IsI2P() || IsInternal()) {
     913        2384 :         return ToStringAddr() + ":" + port_str;
     914             :     } else {
     915         109 :         return "[" + ToStringAddr() + "]:" + port_str;
     916             :     }
     917        2493 : }
     918             : 
     919         444 : CSubNet::CSubNet():
     920         222 :     valid(false)
     921         222 : {
     922         222 :     memset(netmask, 0, sizeof(netmask));
     923         444 : }
     924             : 
     925          36 : CSubNet::CSubNet(const CNetAddr& addr, uint8_t mask) : CSubNet()
     926             : {
     927          48 :     valid = (addr.IsIPv4() && mask <= ADDR_IPV4_SIZE * 8) ||
     928          12 :             (addr.IsIPv6() && mask <= ADDR_IPV6_SIZE * 8);
     929          36 :     if (!valid) {
     930           3 :         return;
     931             :     }
     932             : 
     933          33 :     assert(mask <= sizeof(netmask) * 8);
     934             : 
     935          33 :     network = addr;
     936             : 
     937          33 :     uint8_t n = mask;
     938         273 :     for (size_t i = 0; i < network.m_addr.size(); ++i) {
     939         240 :         const uint8_t bits = n < 8 ? n : 8;
     940         240 :         netmask[i] = (uint8_t)((uint8_t)0xFF << (8 - bits)); // Set first bits.
     941         240 :         network.m_addr[i] &= netmask[i]; // Normalize network according to netmask.
     942         240 :         n -= bits;
     943         240 :     }
     944          36 : }
     945             : 
     946             : /**
     947             :  * @returns The number of 1-bits in the prefix of the specified subnet mask. If
     948             :  *          the specified subnet mask is not a valid one, -1.
     949             :  */
     950         464 : static inline int NetmaskBits(uint8_t x)
     951             : {
     952         464 :     switch(x) {
     953         108 :     case 0x00: return 0;
     954           8 :     case 0x80: return 1;
     955           8 :     case 0xc0: return 2;
     956           8 :     case 0xe0: return 3;
     957           8 :     case 0xf0: return 4;
     958           8 :     case 0xf8: return 5;
     959          11 :     case 0xfc: return 6;
     960           9 :     case 0xfe: return 7;
     961         294 :     case 0xff: return 8;
     962           2 :     default: return -1;
     963             :     }
     964         464 : }
     965             : 
     966          50 : CSubNet::CSubNet(const CNetAddr& addr, const CNetAddr& mask) : CSubNet()
     967             : {
     968          50 :     valid = (addr.IsIPv4() || addr.IsIPv6()) && addr.m_net == mask.m_net;
     969          50 :     if (!valid) {
     970           3 :         return;
     971             :     }
     972             :     // Check if `mask` contains 1-bits after 0-bits (which is an invalid netmask).
     973          47 :     bool zeros_found = false;
     974         281 :     for (auto b : mask.m_addr) {
     975         238 :         const int num_bits = NetmaskBits(b);
     976         238 :         if (num_bits == -1 || (zeros_found && num_bits != 0)) {
     977           4 :             valid = false;
     978           4 :             return;
     979             :         }
     980         234 :         if (num_bits < 8) {
     981         138 :             zeros_found = true;
     982         138 :         }
     983             :     }
     984             : 
     985          43 :     assert(mask.m_addr.size() <= sizeof(netmask));
     986             : 
     987          43 :     memcpy(netmask, mask.m_addr.data(), mask.m_addr.size());
     988             : 
     989          43 :     network = addr;
     990             : 
     991             :     // Normalize network according to netmask
     992         263 :     for (size_t x = 0; x < network.m_addr.size(); ++x) {
     993         220 :         network.m_addr[x] &= netmask[x];
     994         220 :     }
     995          50 : }
     996             : 
     997          25 : CSubNet::CSubNet(const CNetAddr& addr) : CSubNet()
     998             : {
     999          25 :     switch (addr.m_net) {
    1000             :     case NET_IPV4:
    1001             :     case NET_IPV6:
    1002          22 :         valid = true;
    1003          22 :         assert(addr.m_addr.size() <= sizeof(netmask));
    1004          22 :         memset(netmask, 0xFF, addr.m_addr.size());
    1005          22 :         break;
    1006             :     case NET_ONION:
    1007             :     case NET_I2P:
    1008             :     case NET_CJDNS:
    1009           3 :         valid = true;
    1010           3 :         break;
    1011             :     case NET_INTERNAL:
    1012             :     case NET_UNROUTABLE:
    1013             :     case NET_MAX:
    1014           0 :         return;
    1015             :     }
    1016             : 
    1017          25 :     network = addr;
    1018          25 : }
    1019             : 
    1020             : /**
    1021             :  * @returns True if this subnet is valid, the specified address is valid, and
    1022             :  *          the specified address belongs in this subnet.
    1023             :  */
    1024          39 : bool CSubNet::Match(const CNetAddr &addr) const
    1025             : {
    1026          39 :     if (!valid || !addr.IsValid() || network.m_net != addr.m_net)
    1027          11 :         return false;
    1028             : 
    1029          28 :     switch (network.m_net) {
    1030             :     case NET_IPV4:
    1031             :     case NET_IPV6:
    1032          25 :         break;
    1033             :     case NET_ONION:
    1034             :     case NET_I2P:
    1035             :     case NET_CJDNS:
    1036             :     case NET_INTERNAL:
    1037           3 :         return addr == network;
    1038             :     case NET_UNROUTABLE:
    1039             :     case NET_MAX:
    1040           0 :         return false;
    1041             :     }
    1042             : 
    1043          25 :     assert(network.m_addr.size() == addr.m_addr.size());
    1044         180 :     for (size_t x = 0; x < addr.m_addr.size(); ++x) {
    1045         162 :         if ((addr.m_addr[x] & netmask[x]) != network.m_addr[x]) {
    1046           7 :             return false;
    1047             :         }
    1048         155 :     }
    1049          18 :     return true;
    1050          39 : }
    1051             : 
    1052          59 : std::string CSubNet::ToString() const
    1053             : {
    1054          59 :     std::string suffix;
    1055             : 
    1056          59 :     switch (network.m_net) {
    1057             :     case NET_IPV4:
    1058             :     case NET_IPV6: {
    1059          58 :         assert(network.m_addr.size() <= sizeof(netmask));
    1060             : 
    1061          58 :         uint8_t cidr = 0;
    1062             : 
    1063         284 :         for (size_t i = 0; i < network.m_addr.size(); ++i) {
    1064         264 :             if (netmask[i] == 0x00) {
    1065          38 :                 break;
    1066             :             }
    1067         226 :             cidr += NetmaskBits(netmask[i]);
    1068         226 :         }
    1069             : 
    1070          58 :         suffix = strprintf("/%u", cidr);
    1071          58 :         break;
    1072             :     }
    1073             :     case NET_ONION:
    1074             :     case NET_I2P:
    1075             :     case NET_CJDNS:
    1076             :     case NET_INTERNAL:
    1077             :     case NET_UNROUTABLE:
    1078             :     case NET_MAX:
    1079           1 :         break;
    1080             :     }
    1081             : 
    1082          59 :     return network.ToStringAddr() + suffix;
    1083          59 : }
    1084             : 
    1085         156 : bool CSubNet::IsValid() const
    1086             : {
    1087         156 :     return valid;
    1088             : }
    1089             : 
    1090           2 : bool operator==(const CSubNet& a, const CSubNet& b)
    1091             : {
    1092           2 :     return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
    1093             : }
    1094             : 
    1095          18 : bool operator<(const CSubNet& a, const CSubNet& b)
    1096             : {
    1097          18 :     return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
    1098             : }

Generated by: LCOV version 1.16