Bitcoin Core  22.99.0
P2P Digital Currency
banman.cpp
Go to the documentation of this file.
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 <banman.h>
7 
8 #include <netaddress.h>
9 #include <node/ui_interface.h>
10 #include <sync.h>
11 #include <util/system.h>
12 #include <util/time.h>
13 #include <util/translation.h>
14 
15 
16 BanMan::BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t default_ban_time)
17  : m_client_interface(client_interface), m_ban_db(std::move(ban_file)), m_default_ban_time(default_ban_time)
18 {
19  if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist…").translated);
20 
21  int64_t n_start = GetTimeMillis();
22  if (m_ban_db.Read(m_banned)) {
23  SweepBanned(); // sweep out unused entries
24 
25  LogPrint(BCLog::NET, "Loaded %d banned node addresses/subnets %dms\n", m_banned.size(),
26  GetTimeMillis() - n_start);
27  } else {
28  LogPrintf("Recreating the banlist database\n");
29  m_banned = {};
30  m_is_dirty = true;
31  }
32 
33  DumpBanlist();
34 }
35 
37 {
38  DumpBanlist();
39 }
40 
42 {
43  static Mutex dump_mutex;
44  LOCK(dump_mutex);
45 
46  banmap_t banmap;
47  {
49  SweepBanned();
50  if (!BannedSetIsDirty()) return;
51  banmap = m_banned;
52  SetBannedSetDirty(false);
53  }
54 
55  int64_t n_start = GetTimeMillis();
56  if (!m_ban_db.Write(banmap)) {
57  SetBannedSetDirty(true);
58  }
59 
60  LogPrint(BCLog::NET, "Flushed %d banned node addresses/subnets to disk %dms\n", banmap.size(),
61  GetTimeMillis() - n_start);
62 }
63 
65 {
66  {
68  m_banned.clear();
69  m_is_dirty = true;
70  }
71  DumpBanlist(); //store banlist to disk
72  if (m_client_interface) m_client_interface->BannedListChanged();
73 }
74 
75 bool BanMan::IsDiscouraged(const CNetAddr& net_addr)
76 {
78  return m_discouraged.contains(net_addr.GetAddrBytes());
79 }
80 
81 bool BanMan::IsBanned(const CNetAddr& net_addr)
82 {
83  auto current_time = GetTime();
85  for (const auto& it : m_banned) {
86  CSubNet sub_net = it.first;
87  CBanEntry ban_entry = it.second;
88 
89  if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
90  return true;
91  }
92  }
93  return false;
94 }
95 
96 bool BanMan::IsBanned(const CSubNet& sub_net)
97 {
98  auto current_time = GetTime();
100  banmap_t::iterator i = m_banned.find(sub_net);
101  if (i != m_banned.end()) {
102  CBanEntry ban_entry = (*i).second;
103  if (current_time < ban_entry.nBanUntil) {
104  return true;
105  }
106  }
107  return false;
108 }
109 
110 void BanMan::Ban(const CNetAddr& net_addr, int64_t ban_time_offset, bool since_unix_epoch)
111 {
112  CSubNet sub_net(net_addr);
113  Ban(sub_net, ban_time_offset, since_unix_epoch);
114 }
115 
116 void BanMan::Discourage(const CNetAddr& net_addr)
117 {
118  LOCK(m_cs_banned);
119  m_discouraged.insert(net_addr.GetAddrBytes());
120 }
121 
122 void BanMan::Ban(const CSubNet& sub_net, int64_t ban_time_offset, bool since_unix_epoch)
123 {
124  CBanEntry ban_entry(GetTime());
125 
126  int64_t normalized_ban_time_offset = ban_time_offset;
127  bool normalized_since_unix_epoch = since_unix_epoch;
128  if (ban_time_offset <= 0) {
129  normalized_ban_time_offset = m_default_ban_time;
130  normalized_since_unix_epoch = false;
131  }
132  ban_entry.nBanUntil = (normalized_since_unix_epoch ? 0 : GetTime()) + normalized_ban_time_offset;
133 
134  {
135  LOCK(m_cs_banned);
136  if (m_banned[sub_net].nBanUntil < ban_entry.nBanUntil) {
137  m_banned[sub_net] = ban_entry;
138  m_is_dirty = true;
139  } else
140  return;
141  }
142  if (m_client_interface) m_client_interface->BannedListChanged();
143 
144  //store banlist to disk immediately
145  DumpBanlist();
146 }
147 
148 bool BanMan::Unban(const CNetAddr& net_addr)
149 {
150  CSubNet sub_net(net_addr);
151  return Unban(sub_net);
152 }
153 
154 bool BanMan::Unban(const CSubNet& sub_net)
155 {
156  {
157  LOCK(m_cs_banned);
158  if (m_banned.erase(sub_net) == 0) return false;
159  m_is_dirty = true;
160  }
161  if (m_client_interface) m_client_interface->BannedListChanged();
162  DumpBanlist(); //store banlist to disk immediately
163  return true;
164 }
165 
167 {
168  LOCK(m_cs_banned);
169  // Sweep the banlist so expired bans are not returned
170  SweepBanned();
171  banmap = m_banned; //create a thread safe copy
172 }
173 
175 {
176  int64_t now = GetTime();
177  bool notify_ui = false;
178  {
179  LOCK(m_cs_banned);
180  banmap_t::iterator it = m_banned.begin();
181  while (it != m_banned.end()) {
182  CSubNet sub_net = (*it).first;
183  CBanEntry ban_entry = (*it).second;
184  if (!sub_net.IsValid() || now > ban_entry.nBanUntil) {
185  m_banned.erase(it++);
186  m_is_dirty = true;
187  notify_ui = true;
188  LogPrint(BCLog::NET, "Removed banned node address/subnet: %s\n", sub_net.ToString());
189  } else
190  ++it;
191  }
192  }
193  // update UI
194  if (notify_ui && m_client_interface) {
195  m_client_interface->BannedListChanged();
196  }
197 }
198 
200 {
201  LOCK(m_cs_banned);
202  return m_is_dirty;
203 }
204 
206 {
207  LOCK(m_cs_banned); //reuse m_banned lock for the m_is_dirty flag
208  m_is_dirty = dirty;
209 }
CBanDB::Read
bool Read(banmap_t &banSet)
Read the banlist from disk.
Definition: addrdb.cpp:144
BanMan::IsBanned
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
Definition: banman.cpp:81
_
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:63
BanMan::ClearBanned
void ClearBanned()
Definition: banman.cpp:64
BanMan::IsDiscouraged
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
Definition: banman.cpp:75
CClientUIInterface
Signals for UI communication.
Definition: ui_interface.h:24
CNetAddr::GetAddrBytes
std::vector< unsigned char > GetAddrBytes() const
Definition: netaddress.cpp:826
sync.h
BanMan::Unban
bool Unban(const CNetAddr &net_addr)
Definition: banman.cpp:148
CNetAddr
Network address.
Definition: netaddress.h:118
CBanDB::Write
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:131
GetTime
int64_t GetTime()
DEPRECATED Use either GetTimeSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:26
BanMan::m_ban_db
CBanDB m_ban_db
Definition: banman.h:93
AnnotatedMixin< std::mutex >
BanMan::m_client_interface
CClientUIInterface * m_client_interface
Definition: banman.h:92
CSubNet::Match
bool Match(const CNetAddr &addr) const
Definition: netaddress.cpp:1158
BanMan::DumpBanlist
void DumpBanlist()
Definition: banman.cpp:41
banman.h
fs::path
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:29
netaddress.h
BanMan::BanMan
BanMan(fs::path ban_file, CClientUIInterface *client_interface, int64_t default_ban_time)
Definition: banman.cpp:16
time.h
LogPrintf
#define LogPrintf(...)
Definition: logging.h:188
CSubNet
Definition: netaddress.h:475
BanMan::GetBanned
void GetBanned(banmap_t &banmap)
Definition: banman.cpp:166
BanMan::m_cs_banned
RecursiveMutex m_cs_banned
Definition: banman.h:89
BanMan::SweepBanned
void SweepBanned()
clean unused entries (if bantime has expired)
Definition: banman.cpp:174
LogPrint
#define LogPrint(category,...)
Definition: logging.h:192
BanMan::SetBannedSetDirty
void SetBannedSetDirty(bool dirty=true)
set the "dirty" flag for the banlist
Definition: banman.cpp:205
BanMan::m_default_ban_time
const int64_t m_default_ban_time
Definition: banman.h:94
ui_interface.h
system.h
BanMan::Ban
void Ban(const CNetAddr &net_addr, int64_t ban_time_offset=0, bool since_unix_epoch=false)
Definition: banman.cpp:110
translation.h
CSubNet::ToString
std::string ToString() const
Definition: netaddress.cpp:1186
LOCK
#define LOCK(cs)
Definition: sync.h:226
std
Definition: setup_common.h:33
CBanEntry
Definition: net_types.h:14
CBanEntry::nBanUntil
int64_t nBanUntil
Definition: net_types.h:20
BanMan::~BanMan
~BanMan()
Definition: banman.cpp:36
CSubNet::IsValid
bool IsValid() const
Definition: netaddress.cpp:1219
banmap_t
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:41
BCLog::NET
@ NET
Definition: logging.h:39
BanMan::Discourage
void Discourage(const CNetAddr &net_addr)
Definition: banman.cpp:116
GetTimeMillis
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:117
BanMan::BannedSetIsDirty
bool BannedSetIsDirty()
Definition: banman.cpp:199