Bitcoin ABC 0.30.5
P2P Digital Currency
banman.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2017 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 <banman.h>
7
8#include <logging.h>
9#include <netaddress.h>
10#include <node/ui_interface.h>
11#include <util/time.h>
12#include <util/translation.h>
13
14BanMan::BanMan(fs::path ban_file, const CChainParams &chainparams,
15 CClientUIInterface *client_interface, int64_t default_ban_time)
16 : m_client_interface(client_interface),
17 m_ban_db(std::move(ban_file), chainparams),
18 m_default_ban_time(default_ban_time) {
20 m_client_interface->InitMessage(_("Loading banlist...").translated);
21 }
22
23 int64_t n_start = GetTimeMillis();
24 m_is_dirty = false;
25 banmap_t banmap;
26 if (m_ban_db.Read(banmap)) {
27 // thread save setter
28 SetBanned(banmap);
29 // no need to write down, just read data
30 SetBannedSetDirty(false);
31 // sweep out unused entries
33
35 "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
36 m_banned.size(), GetTimeMillis() - n_start);
37 } else {
38 LogPrintf("Recreating banlist.dat\n");
39 // force write
42 }
43}
44
47}
48
50 // clean unused entries (if bantime has expired)
52
53 if (!BannedSetIsDirty()) {
54 return;
55 }
56
57 int64_t n_start = GetTimeMillis();
58
59 banmap_t banmap;
60 GetBanned(banmap);
61 if (m_ban_db.Write(banmap)) {
62 SetBannedSetDirty(false);
63 }
64
66 "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
67 banmap.size(), GetTimeMillis() - n_start);
68}
69
71 {
73 m_discouraged.reset();
74 m_banned.clear();
75 m_is_dirty = true;
76 }
77 // store banlist to disk
80 m_client_interface->BannedListChanged();
81 }
82}
83
84bool BanMan::IsDiscouraged(const CNetAddr &net_addr) {
86 return m_discouraged.contains(net_addr.GetAddrBytes());
87}
88
89bool BanMan::IsBanned(const CNetAddr &net_addr) {
90 auto current_time = GetTime();
92 for (const auto &it : m_banned) {
93 CSubNet sub_net = it.first;
94 CBanEntry ban_entry = it.second;
95
96 if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
97 return true;
98 }
99 }
100 return false;
101}
102
103bool BanMan::IsBanned(const CSubNet &sub_net) {
104 auto current_time = GetTime();
106 banmap_t::iterator i = m_banned.find(sub_net);
107 if (i != m_banned.end()) {
108 CBanEntry ban_entry = (*i).second;
109 if (current_time < ban_entry.nBanUntil) {
110 return true;
111 }
112 }
113 return false;
114}
115
116void BanMan::Ban(const CNetAddr &net_addr, int64_t ban_time_offset,
117 bool since_unix_epoch) {
118 CSubNet sub_net(net_addr);
119 Ban(sub_net, ban_time_offset, since_unix_epoch);
120}
121
122void BanMan::Discourage(const CNetAddr &net_addr) {
124 m_discouraged.insert(net_addr.GetAddrBytes());
125}
126
127void BanMan::Ban(const CSubNet &sub_net, int64_t ban_time_offset,
128 bool since_unix_epoch) {
129 CBanEntry ban_entry(GetTime());
130
131 int64_t normalized_ban_time_offset = ban_time_offset;
132 bool normalized_since_unix_epoch = since_unix_epoch;
133 if (ban_time_offset <= 0) {
134 normalized_ban_time_offset = m_default_ban_time;
135 normalized_since_unix_epoch = false;
136 }
137 ban_entry.nBanUntil = (normalized_since_unix_epoch ? 0 : GetTime()) +
138 normalized_ban_time_offset;
139
140 {
142 if (m_banned[sub_net].nBanUntil < ban_entry.nBanUntil) {
143 m_banned[sub_net] = ban_entry;
144 m_is_dirty = true;
145 } else {
146 return;
147 }
148 }
149 if (m_client_interface) {
150 m_client_interface->BannedListChanged();
151 }
152
153 // store banlist to disk immediately
154 DumpBanlist();
155}
156
157bool BanMan::Unban(const CNetAddr &net_addr) {
158 CSubNet sub_net(net_addr);
159 return Unban(sub_net);
160}
161
162bool BanMan::Unban(const CSubNet &sub_net) {
163 {
165 if (m_banned.erase(sub_net) == 0) {
166 return false;
167 }
168 m_is_dirty = true;
169 }
170 if (m_client_interface) {
171 m_client_interface->BannedListChanged();
172 }
173
174 // store banlist to disk immediately
175 DumpBanlist();
176 return true;
177}
178
181 // Sweep the banlist so expired bans are not returned
182 SweepBanned();
183 // create a thread safe copy
184 banmap = m_banned;
185}
186
187void BanMan::SetBanned(const banmap_t &banmap) {
189 m_banned = banmap;
190 m_is_dirty = true;
191}
192
194 int64_t now = GetTime();
195 bool notify_ui = false;
196 {
198 banmap_t::iterator it = m_banned.begin();
199 while (it != m_banned.end()) {
200 CSubNet sub_net = (*it).first;
201 CBanEntry ban_entry = (*it).second;
202 if (!sub_net.IsValid() || now > ban_entry.nBanUntil) {
203 m_banned.erase(it++);
204 m_is_dirty = true;
205 notify_ui = true;
206 LogPrint(
208 "%s: Removed banned node ip/subnet from banlist.dat: %s\n",
209 __func__, sub_net.ToString());
210 } else {
211 ++it;
212 }
213 }
214 }
215 // update UI
216 if (notify_ui && m_client_interface) {
217 m_client_interface->BannedListChanged();
218 }
219}
220
223 return m_is_dirty;
224}
225
227 // reuse m_banned lock for the m_is_dirty flag
229 m_is_dirty = dirty;
230}
void Discourage(const CNetAddr &net_addr)
Definition: banman.cpp:122
void Ban(const CNetAddr &net_addr, int64_t ban_time_offset=0, bool since_unix_epoch=false)
Definition: banman.cpp:116
const int64_t m_default_ban_time
Definition: banman.h:97
void GetBanned(banmap_t &banmap)
Definition: banman.cpp:179
void ClearBanned()
Definition: banman.cpp:70
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
Definition: banman.cpp:89
RecursiveMutex m_cs_banned
Definition: banman.h:92
void SetBanned(const banmap_t &banmap)
Definition: banman.cpp:187
bool BannedSetIsDirty()
Definition: banman.cpp:221
CClientUIInterface * m_client_interface
Definition: banman.h:95
bool Unban(const CNetAddr &net_addr)
Definition: banman.cpp:157
BanMan(fs::path ban_file, const CChainParams &chainparams, CClientUIInterface *client_interface, int64_t default_ban_time)
Definition: banman.cpp:14
CBanDB m_ban_db
Definition: banman.h:96
void SetBannedSetDirty(bool dirty=true)
set the "dirty" flag for the banlist
Definition: banman.cpp:226
~BanMan()
Definition: banman.cpp:45
void SweepBanned()
clean unused entries (if bantime has expired)
Definition: banman.cpp:193
void DumpBanlist()
Definition: banman.cpp:49
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
Definition: banman.cpp:84
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:131
bool Read(banmap_t &banSet)
Definition: addrdb.cpp:136
Definition: addrdb.h:30
int64_t nBanUntil
Definition: addrdb.h:35
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:80
Signals for UI communication.
Definition: ui_interface.h:24
Network address.
Definition: netaddress.h:121
std::vector< uint8_t > GetAddrBytes() const
Definition: netaddress.cpp:861
std::string ToString() const
bool IsValid() const
bool Match(const CNetAddr &addr) const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
#define LogPrint(category,...)
Definition: logging.h:211
#define LogPrintf(...)
Definition: logging.h:207
@ NET
Definition: logging.h:40
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:13
#define LOCK(cs)
Definition: sync.h:306
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:101
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:109
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68