Line data Source code
1 : // Copyright (c) 2009-2019 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 4480 : const std::vector<std::string> NET_PERMISSIONS_DOC{
12 640 : "bloomfilter (allow requesting BIP37 filtered blocks and transactions)",
13 640 : "noban (do not ban for misbehavior; implies download)",
14 640 : "forcerelay (relay transactions that are already in the mempool; implies relay)",
15 640 : "relay (relay even in -blocksonly mode)",
16 640 : "mempool (allow requesting BIP35 mempool contents)",
17 640 : "download (allow getheaders during IBD, no disconnect after maxuploadtarget limit)",
18 640 : "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 : // The parse the following format "perm1,perm2@xxxxxx"
24 82 : bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, size_t& readen, bilingual_str& error)
25 : {
26 82 : NetPermissionFlags flags = PF_NONE;
27 82 : const auto atSeparator = str.find('@');
28 :
29 : // if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
30 82 : if (atSeparator == std::string::npos) {
31 11 : NetPermissions::AddFlag(flags, PF_ISIMPLICIT);
32 11 : readen = 0;
33 11 : }
34 : // else (ie, "perm1,perm2@xxxxx"), let's enumerate the permissions by splitting by ',' and calculate the flags
35 : else {
36 71 : readen = 0;
37 : // permissions == perm1,perm2
38 71 : const auto permissions = str.substr(0, atSeparator);
39 164 : while (readen < permissions.length()) {
40 95 : const auto commaSeparator = permissions.find(',', readen);
41 95 : const auto len = commaSeparator == std::string::npos ? permissions.length() - readen : commaSeparator - readen;
42 : // permission == perm1
43 95 : const auto permission = permissions.substr(readen, len);
44 95 : readen += len; // We read "perm1"
45 95 : if (commaSeparator != std::string::npos) readen++; // We read ","
46 :
47 95 : if (permission == "bloomfilter" || permission == "bloom") NetPermissions::AddFlag(flags, PF_BLOOMFILTER);
48 84 : else if (permission == "noban") NetPermissions::AddFlag(flags, PF_NOBAN);
49 26 : else if (permission == "forcerelay") NetPermissions::AddFlag(flags, PF_FORCERELAY);
50 17 : else if (permission == "mempool") NetPermissions::AddFlag(flags, PF_MEMPOOL);
51 14 : else if (permission == "download") NetPermissions::AddFlag(flags, PF_DOWNLOAD);
52 13 : else if (permission == "all") NetPermissions::AddFlag(flags, PF_ALL);
53 11 : else if (permission == "relay") NetPermissions::AddFlag(flags, PF_RELAY);
54 6 : else if (permission == "addr") NetPermissions::AddFlag(flags, PF_ADDR);
55 6 : else if (permission.length() == 0); // Allow empty entries
56 : else {
57 2 : error = strprintf(_("Invalid P2P permission: '%s'"), permission);
58 2 : return false;
59 : }
60 95 : }
61 69 : readen++;
62 71 : }
63 :
64 80 : output = flags;
65 80 : error = Untranslated("");
66 80 : return true;
67 82 : }
68 :
69 : }
70 :
71 8636 : std::vector<std::string> NetPermissions::ToStrings(NetPermissionFlags flags)
72 : {
73 8636 : std::vector<std::string> strings;
74 8636 : if (NetPermissions::HasFlag(flags, PF_BLOOMFILTER)) strings.push_back("bloomfilter");
75 8636 : if (NetPermissions::HasFlag(flags, PF_NOBAN)) strings.push_back("noban");
76 8636 : if (NetPermissions::HasFlag(flags, PF_FORCERELAY)) strings.push_back("forcerelay");
77 8636 : if (NetPermissions::HasFlag(flags, PF_RELAY)) strings.push_back("relay");
78 8636 : if (NetPermissions::HasFlag(flags, PF_MEMPOOL)) strings.push_back("mempool");
79 8636 : if (NetPermissions::HasFlag(flags, PF_DOWNLOAD)) strings.push_back("download");
80 8636 : if (NetPermissions::HasFlag(flags, PF_ADDR)) strings.push_back("addr");
81 : return strings;
82 8636 : }
83 :
84 17 : bool NetWhitebindPermissions::TryParse(const std::string str, NetWhitebindPermissions& output, bilingual_str& error)
85 : {
86 17 : NetPermissionFlags flags;
87 17 : size_t offset;
88 17 : if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
89 :
90 16 : const std::string strBind = str.substr(offset);
91 16 : CService addrBind;
92 16 : if (!Lookup(strBind, addrBind, 0, false)) {
93 3 : error = ResolveErrMsg("whitebind", strBind);
94 3 : return false;
95 : }
96 13 : if (addrBind.GetPort() == 0) {
97 1 : error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind);
98 1 : return false;
99 : }
100 :
101 12 : output.m_flags = flags;
102 12 : output.m_service = addrBind;
103 12 : error = Untranslated("");
104 12 : return true;
105 17 : }
106 :
107 65 : bool NetWhitelistPermissions::TryParse(const std::string str, NetWhitelistPermissions& output, bilingual_str& error)
108 : {
109 65 : NetPermissionFlags flags;
110 65 : size_t offset;
111 65 : if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
112 :
113 64 : const std::string net = str.substr(offset);
114 64 : CSubNet subnet;
115 64 : LookupSubNet(net, subnet);
116 64 : if (!subnet.IsValid()) {
117 2 : error = strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net);
118 2 : return false;
119 : }
120 :
121 62 : output.m_flags = flags;
122 62 : output.m_subnet = subnet;
123 62 : error = Untranslated("");
124 62 : return true;
125 65 : }
|