Bitcoin Core  0.18.99
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 <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  m_is_dirty = false;
22  banmap_t banmap;
23  if (m_ban_db.Read(banmap)) {
24  SetBanned(banmap); // thread save setter
25  SetBannedSetDirty(false); // no need to write down, just read data
26  SweepBanned(); // sweep out unused entries
27 
28  LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
29  banmap.size(), GetTimeMillis() - n_start);
30  } else {
31  LogPrintf("Invalid or missing banlist.dat; recreating\n");
32  SetBannedSetDirty(true); // force write
33  DumpBanlist();
34  }
35 }
36 
38 {
39  DumpBanlist();
40 }
41 
43 {
44  SweepBanned(); // clean unused entries (if bantime has expired)
45 
46  if (!BannedSetIsDirty()) return;
47 
48  int64_t n_start = GetTimeMillis();
49 
50  banmap_t banmap;
51  GetBanned(banmap);
52  if (m_ban_db.Write(banmap)) {
53  SetBannedSetDirty(false);
54  }
55 
56  LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
57  banmap.size(), GetTimeMillis() - n_start);
58 }
59 
61 {
62  {
64  m_banned.clear();
65  m_is_dirty = true;
66  }
67  DumpBanlist(); //store banlist to disk
68  if (m_client_interface) m_client_interface->BannedListChanged();
69 }
70 
72 {
73  // Returns the most severe level of banning that applies to this address.
74  // 0 - Not banned
75  // 1 - Automatic misbehavior ban
76  // 2 - Any other ban
77  int level = 0;
78  auto current_time = GetTime();
80  for (const auto& it : m_banned) {
81  CSubNet sub_net = it.first;
82  CBanEntry ban_entry = it.second;
83 
84  if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
85  if (ban_entry.banReason != BanReasonNodeMisbehaving) return 2;
86  level = 1;
87  }
88  }
89  return level;
90 }
91 
92 bool BanMan::IsBanned(CNetAddr net_addr)
93 {
94  auto current_time = GetTime();
96  for (const auto& it : m_banned) {
97  CSubNet sub_net = it.first;
98  CBanEntry ban_entry = it.second;
99 
100  if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
101  return true;
102  }
103  }
104  return false;
105 }
106 
108 {
109  auto current_time = GetTime();
110  LOCK(m_cs_banned);
111  banmap_t::iterator i = m_banned.find(sub_net);
112  if (i != m_banned.end()) {
113  CBanEntry ban_entry = (*i).second;
114  if (current_time < ban_entry.nBanUntil) {
115  return true;
116  }
117  }
118  return false;
119 }
120 
121 void BanMan::Ban(const CNetAddr& net_addr, const BanReason& ban_reason, int64_t ban_time_offset, bool since_unix_epoch)
122 {
123  CSubNet sub_net(net_addr);
124  Ban(sub_net, ban_reason, ban_time_offset, since_unix_epoch);
125 }
126 
127 void BanMan::Ban(const CSubNet& sub_net, const BanReason& ban_reason, int64_t ban_time_offset, bool since_unix_epoch)
128 {
129  CBanEntry ban_entry(GetTime(), ban_reason);
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()) + normalized_ban_time_offset;
138 
139  {
140  LOCK(m_cs_banned);
141  if (m_banned[sub_net].nBanUntil < ban_entry.nBanUntil) {
142  m_banned[sub_net] = ban_entry;
143  m_is_dirty = true;
144  } else
145  return;
146  }
147  if (m_client_interface) m_client_interface->BannedListChanged();
148 
149  //store banlist to disk immediately if user requested ban
150  if (ban_reason == BanReasonManuallyAdded) DumpBanlist();
151 }
152 
153 bool BanMan::Unban(const CNetAddr& net_addr)
154 {
155  CSubNet sub_net(net_addr);
156  return Unban(sub_net);
157 }
158 
159 bool BanMan::Unban(const CSubNet& sub_net)
160 {
161  {
162  LOCK(m_cs_banned);
163  if (m_banned.erase(sub_net) == 0) return false;
164  m_is_dirty = true;
165  }
166  if (m_client_interface) m_client_interface->BannedListChanged();
167  DumpBanlist(); //store banlist to disk immediately
168  return true;
169 }
170 
172 {
173  LOCK(m_cs_banned);
174  // Sweep the banlist so expired bans are not returned
175  SweepBanned();
176  banmap = m_banned; //create a thread safe copy
177 }
178 
179 void BanMan::SetBanned(const banmap_t& banmap)
180 {
181  LOCK(m_cs_banned);
182  m_banned = banmap;
183  m_is_dirty = true;
184 }
185 
187 {
188  int64_t now = GetTime();
189  bool notify_ui = false;
190  {
191  LOCK(m_cs_banned);
192  banmap_t::iterator it = m_banned.begin();
193  while (it != m_banned.end()) {
194  CSubNet sub_net = (*it).first;
195  CBanEntry ban_entry = (*it).second;
196  if (now > ban_entry.nBanUntil) {
197  m_banned.erase(it++);
198  m_is_dirty = true;
199  notify_ui = true;
200  LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, sub_net.ToString());
201  } else
202  ++it;
203  }
204  }
205  // update UI
206  if (notify_ui && m_client_interface) {
207  m_client_interface->BannedListChanged();
208  }
209 }
210 
212 {
213  LOCK(m_cs_banned);
214  return m_is_dirty;
215 }
216 
218 {
219  LOCK(m_cs_banned); //reuse m_banned lock for the m_is_dirty flag
220  m_is_dirty = dirty;
221 }
BanReason
Definition: addrdb.h:19
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:54
void SetBanned(const banmap_t &banmap)
Definition: banman.cpp:179
CClientUIInterface * m_client_interface
Definition: banman.h:64
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:144
void SetBannedSetDirty(bool dirty=true)
set the "dirty" flag for the banlist
Definition: banman.cpp:217
Signals for UI communication.
Definition: ui_interface.h:34
~BanMan()
Definition: banman.cpp:37
void ClearBanned()
Definition: banman.cpp:60
std::map< CSubNet, CBanEntry > banmap_t
Definition: addrdb.h:82
bool IsBanned(CNetAddr net_addr)
Definition: banman.cpp:92
void SweepBanned()
clean unused entries (if bantime has expired)
Definition: banman.cpp:186
#define LOCK(cs)
Definition: sync.h:182
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:37
bool BannedSetIsDirty()
Definition: banman.cpp:211
static void LogPrint(const BCLog::LogFlags &category, const Args &... args)
Definition: logging.h:159
CBanDB m_ban_db
Definition: banman.h:65
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:124
void DumpBanlist()
Definition: banman.cpp:42
int64_t nBanUntil
Definition: addrdb.h:32
void GetBanned(banmap_t &banmap)
Definition: banman.cpp:171
void Ban(const CNetAddr &net_addr, const BanReason &ban_reason, int64_t ban_time_offset=0, bool since_unix_epoch=false)
Definition: banman.cpp:121
bool Match(const CNetAddr &addr) const
Definition: netaddress.cpp:758
const int64_t m_default_ban_time
Definition: banman.h:66
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:32
std::string ToString() const
Definition: netaddress.cpp:788
bool Unban(const CNetAddr &net_addr)
Definition: banman.cpp:153
uint8_t banReason
Definition: addrdb.h:33
int IsBannedLevel(CNetAddr net_addr)
Definition: banman.cpp:71
BanMan(fs::path ban_file, CClientUIInterface *client_interface, int64_t default_ban_time)
Definition: banman.cpp:15
CCriticalSection m_cs_banned
Definition: banman.h:61
Definition: addrdb.h:26
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:20
auto it
Definition: validation.cpp:366