Bitcoin ABC  0.22.12
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 <netaddress.h>
9 #include <node/ui_interface.h>
10 #include <util/system.h>
11 #include <util/time.h>
12 #include <util/translation.h>
13 
14 BanMan::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) {
19  if (m_client_interface) {
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
32  SweepBanned();
33 
35  "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
36  banmap.size(), GetTimeMillis() - n_start);
37  } else {
38  LogPrintf("Invalid or missing banlist.dat; recreating\n");
39  // force write
40  SetBannedSetDirty(true);
41  DumpBanlist();
42  }
43 }
44 
46  DumpBanlist();
47 }
48 
50  // clean unused entries (if bantime has expired)
51  SweepBanned();
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
78  DumpBanlist();
79  if (m_client_interface) {
80  m_client_interface->BannedListChanged();
81  }
82 }
83 
84 bool BanMan::IsDiscouraged(const CNetAddr &net_addr) {
86  return m_discouraged.contains(net_addr.GetAddrBytes());
87 }
88 
89 bool 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 
103 bool BanMan::IsBanned(const CSubNet &sub_net) {
104  auto current_time = GetTime();
105  LOCK(m_cs_banned);
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 
116 void 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 
122 void BanMan::Discourage(const CNetAddr &net_addr) {
123  LOCK(m_cs_banned);
124  m_discouraged.insert(net_addr.GetAddrBytes());
125 }
126 
127 void 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  {
141  LOCK(m_cs_banned);
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 
157 bool BanMan::Unban(const CNetAddr &net_addr) {
158  CSubNet sub_net(net_addr);
159  return Unban(sub_net);
160 }
161 
162 bool BanMan::Unban(const CSubNet &sub_net) {
163  {
164  LOCK(m_cs_banned);
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 
180  LOCK(m_cs_banned);
181  // Sweep the banlist so expired bans are not returned
182  SweepBanned();
183  // create a thread safe copy
184  banmap = m_banned;
185 }
186 
187 void BanMan::SetBanned(const banmap_t &banmap) {
188  LOCK(m_cs_banned);
189  m_banned = banmap;
190  m_is_dirty = true;
191 }
192 
194  int64_t now = GetTime();
195  bool notify_ui = false;
196  {
197  LOCK(m_cs_banned);
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 (now > ban_entry.nBanUntil) {
203  m_banned.erase(it++);
204  m_is_dirty = true;
205  notify_ui = true;
206  LogPrint(
207  BCLog::NET,
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 
222  LOCK(m_cs_banned);
223  return m_is_dirty;
224 }
225 
226 void BanMan::SetBannedSetDirty(bool dirty) {
227  // reuse m_banned lock for the m_is_dirty flag
228  LOCK(m_cs_banned);
229  m_is_dirty = dirty;
230 }
void Ban(const CNetAddr &net_addr, int64_t ban_time_offset=0, bool since_unix_epoch=false)
Definition: banman.cpp:116
void Discourage(const CNetAddr &net_addr)
Definition: banman.cpp:122
#define LogPrint(category,...)
Definition: logging.h:189
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:59
void SetBanned(const banmap_t &banmap)
Definition: banman.cpp:187
CClientUIInterface * m_client_interface
Definition: banman.h:95
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:171
BanMan(fs::path ban_file, const CChainParams &chainparams, CClientUIInterface *client_interface, int64_t default_ban_time)
Definition: banman.cpp:14
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:47
void SetBannedSetDirty(bool dirty=true)
set the "dirty" flag for the banlist
Definition: banman.cpp:226
Signals for UI communication.
Definition: ui_interface.h:24
~BanMan()
Definition: banman.cpp:45
std::vector< uint8_t > GetAddrBytes() const
Definition: netaddress.h:115
void ClearBanned()
Definition: banman.cpp:70
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
Definition: banman.cpp:84
void SweepBanned()
clean unused entries (if bantime has expired)
Definition: banman.cpp:193
#define LOCK(cs)
Definition: sync.h:230
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:55
bool BannedSetIsDirty()
Definition: banman.cpp:221
RecursiveMutex m_cs_banned
Definition: banman.h:92
CBanDB m_ban_db
Definition: banman.h:96
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:125
void DumpBanlist()
Definition: banman.cpp:49
int64_t nBanUntil
Definition: addrdb.h:26
void GetBanned(banmap_t &banmap)
Definition: banman.cpp:179
bool Match(const CNetAddr &addr) const
Definition: netaddress.cpp:845
const int64_t m_default_ban_time
Definition: banman.h:97
bool Read(banmap_t &banSet)
Definition: addrdb.cpp:129
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:30
std::string ToString() const
Definition: netaddress.cpp:886
bool Unban(const CNetAddr &net_addr)
Definition: banman.cpp:157
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:13
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
Definition: banman.cpp:89
Definition: addrdb.h:21
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:27