LCOV - code coverage report
Current view: top level - src - net_permissions.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 79 79 100.0 %
Date: 2026-06-25 07:23:43 Functions: 5 5 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2021 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 <net_permissions.h>
       6             : #include <netbase.h>
       7             : #include <util/error.h>
       8             : #include <util/system.h>
       9             : #include <util/translation.h>
      10             : 
      11        3308 : const std::vector<std::string> NET_PERMISSIONS_DOC{
      12        3308 :     "bloomfilter (allow requesting BIP37 filtered blocks and transactions)",
      13        3308 :     "noban (do not ban for misbehavior; implies download)",
      14        3308 :     "forcerelay (relay transactions that are already in the mempool; implies relay)",
      15        3308 :     "relay (relay even in -blocksonly mode)",
      16        3308 :     "mempool (allow requesting BIP35 mempool contents)",
      17        3308 :     "download (allow getheaders during IBD, no disconnect after maxuploadtarget limit)",
      18        3308 :     "addr (responses to GETADDR avoid hitting the cache and contain random records with the most up-to-date info)"
      19             : };
      20             : 
      21             : namespace {
      22             : 
      23             : // Parse the following format: "perm1,perm2@xxxxxx"
      24         436 : bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output, size_t& readen, bilingual_str& error)
      25             : {
      26         436 :     NetPermissionFlags flags = NetPermissionFlags::None;
      27         436 :     const auto atSeparator = str.find('@');
      28             : 
      29             :     // if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
      30         436 :     if (atSeparator == std::string::npos) {
      31          69 :         NetPermissions::AddFlag(flags, NetPermissionFlags::Implicit);
      32          69 :         readen = 0;
      33          69 :     }
      34             :     // else (ie, "perm1,perm2@xxxxx"), let's enumerate the permissions by splitting by ',' and calculate the flags
      35             :     else {
      36         367 :         readen = 0;
      37             :         // permissions == perm1,perm2
      38         367 :         const auto permissions = str.substr(0, atSeparator);
      39         761 :         while (readen < permissions.length()) {
      40         397 :             const auto commaSeparator = permissions.find(',', readen);
      41         397 :             const auto len = commaSeparator == std::string::npos ? permissions.length() - readen : commaSeparator - readen;
      42             :             // permission == perm1
      43         397 :             const auto permission = permissions.substr(readen, len);
      44         397 :             readen += len; // We read "perm1"
      45         397 :             if (commaSeparator != std::string::npos) readen++; // We read ","
      46             : 
      47         397 :             if (permission == "bloomfilter" || permission == "bloom") NetPermissions::AddFlag(flags, NetPermissionFlags::BloomFilter);
      48         383 :             else if (permission == "noban") NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
      49          50 :             else if (permission == "forcerelay") NetPermissions::AddFlag(flags, NetPermissionFlags::ForceRelay);
      50          38 :             else if (permission == "mempool") NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
      51          33 :             else if (permission == "download") NetPermissions::AddFlag(flags, NetPermissionFlags::Download);
      52          27 :             else if (permission == "all") NetPermissions::AddFlag(flags, NetPermissionFlags::All);
      53          24 :             else if (permission == "relay") NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
      54          17 :             else if (permission == "addr") NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
      55           7 :             else if (permission.length() == 0); // Allow empty entries
      56             :             else {
      57           3 :                 error = strprintf(_("Invalid P2P permission: '%s'"), permission);
      58           3 :                 return false;
      59             :             }
      60         397 :         }
      61         364 :         readen++;
      62         367 :     }
      63             : 
      64         433 :     output = flags;
      65         433 :     error = Untranslated("");
      66         433 :     return true;
      67         436 : }
      68             : 
      69             : }
      70             : 
      71       86140 : std::vector<std::string> NetPermissions::ToStrings(NetPermissionFlags flags)
      72             : {
      73       86140 :     std::vector<std::string> strings;
      74       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.emplace_back("bloomfilter");
      75       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.emplace_back("noban");
      76       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.emplace_back("forcerelay");
      77       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.emplace_back("relay");
      78       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.emplace_back("mempool");
      79       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.emplace_back("download");
      80       86140 :     if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.emplace_back("addr");
      81       86140 :     return strings;
      82       86140 : }
      83             : 
      84          25 : bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermissions& output, bilingual_str& error)
      85             : {
      86             :     NetPermissionFlags flags;
      87             :     size_t offset;
      88          25 :     if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
      89             : 
      90          24 :     const std::string strBind = str.substr(offset);
      91          24 :     const std::optional<CService> addrBind{Lookup(strBind, 0, false)};
      92          24 :     if (!addrBind.has_value()) {
      93           4 :         error = ResolveErrMsg("whitebind", strBind);
      94           4 :         return false;
      95             :     }
      96          20 :     if (addrBind.value().GetPort() == 0) {
      97           1 :         error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind);
      98           1 :         return false;
      99             :     }
     100             : 
     101          19 :     output.m_flags = flags;
     102          19 :     output.m_service = addrBind.value();
     103          19 :     error = Untranslated("");
     104          19 :     return true;
     105          25 : }
     106             : 
     107         411 : bool NetWhitelistPermissions::TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error)
     108             : {
     109             :     NetPermissionFlags flags;
     110             :     size_t offset;
     111         411 :     if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
     112             : 
     113         409 :     const std::string net = str.substr(offset);
     114         409 :     const CSubNet subnet{LookupSubNet(net)};
     115         409 :     if (!subnet.IsValid()) {
     116           3 :         error = strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net);
     117           3 :         return false;
     118             :     }
     119             : 
     120         406 :     output.m_flags = flags;
     121         406 :     output.m_subnet = subnet;
     122         406 :     error = Untranslated("");
     123         406 :     return true;
     124         411 : }

Generated by: LCOV version 1.16