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