Bitcoin ABC 0.32.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 if (m_ban_db.Read(m_banned, m_is_dirty)) {
25 // sweep out unused entries
27
28 LogPrint(BCLog::NET, "Loaded %d banned node addresses/subnets %dms\n",
29 m_banned.size(), GetTimeMillis() - n_start);
30 } else {
31 LogPrintf("Recreating the banlist database\n");
32 m_banned = {};
33 m_is_dirty = true;
34 }
35
37}
38
41}
42
44 // clean unused entries (if bantime has expired)
46
47 if (!BannedSetIsDirty()) {
48 return;
49 }
50
51 int64_t n_start = GetTimeMillis();
52
53 banmap_t banmap;
54 GetBanned(banmap);
55 if (m_ban_db.Write(banmap)) {
56 SetBannedSetDirty(false);
57 }
58
60 "Flushed %d banned node addresses/subnets to disk %dms\n",
61 banmap.size(), GetTimeMillis() - n_start);
62}
63
65 {
67 m_discouraged.reset();
68 m_banned.clear();
69 m_is_dirty = true;
70 }
71 // store banlist to disk
74 m_client_interface->BannedListChanged();
75 }
76}
77
78bool BanMan::IsDiscouraged(const CNetAddr &net_addr) {
80 return m_discouraged.contains(net_addr.GetAddrBytes());
81}
82
83bool BanMan::IsBanned(const CNetAddr &net_addr) {
84 auto current_time = GetTime();
86 for (const auto &it : m_banned) {
87 CSubNet sub_net = it.first;
88 CBanEntry ban_entry = it.second;
89
90 if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
91 return true;
92 }
93 }
94 return false;
95}
96
97bool BanMan::IsBanned(const CSubNet &sub_net) {
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
110void BanMan::Ban(const CNetAddr &net_addr, int64_t ban_time_offset,
111 bool since_unix_epoch) {
112 CSubNet sub_net(net_addr);
113 Ban(sub_net, ban_time_offset, since_unix_epoch);
114}
115
116void BanMan::Discourage(const CNetAddr &net_addr) {
118 m_discouraged.insert(net_addr.GetAddrBytes());
119}
120
121void BanMan::Ban(const CSubNet &sub_net, int64_t ban_time_offset,
122 bool since_unix_epoch) {
123 CBanEntry ban_entry(GetTime());
124
125 int64_t normalized_ban_time_offset = ban_time_offset;
126 bool normalized_since_unix_epoch = since_unix_epoch;
127 if (ban_time_offset <= 0) {
128 normalized_ban_time_offset = m_default_ban_time;
129 normalized_since_unix_epoch = false;
130 }
131 ban_entry.nBanUntil = (normalized_since_unix_epoch ? 0 : GetTime()) +
132 normalized_ban_time_offset;
133
134 {
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 }
143 if (m_client_interface) {
144 m_client_interface->BannedListChanged();
145 }
146
147 // store banlist to disk immediately
148 DumpBanlist();
149}
150
151bool BanMan::Unban(const CNetAddr &net_addr) {
152 CSubNet sub_net(net_addr);
153 return Unban(sub_net);
154}
155
156bool BanMan::Unban(const CSubNet &sub_net) {
157 {
159 if (m_banned.erase(sub_net) == 0) {
160 return false;
161 }
162 m_is_dirty = true;
163 }
164 if (m_client_interface) {
165 m_client_interface->BannedListChanged();
166 }
167
168 // store banlist to disk immediately
169 DumpBanlist();
170 return true;
171}
172
175 // Sweep the banlist so expired bans are not returned
176 SweepBanned();
177 // create a thread safe copy
178 banmap = m_banned;
179}
180
182 int64_t now = GetTime();
183 bool notify_ui = false;
184 {
186 banmap_t::iterator it = m_banned.begin();
187 while (it != m_banned.end()) {
188 CSubNet sub_net = (*it).first;
189 CBanEntry ban_entry = (*it).second;
190 if (!sub_net.IsValid() || now > ban_entry.nBanUntil) {
191 m_banned.erase(it++);
192 m_is_dirty = true;
193 notify_ui = true;
194 LogPrint(BCLog::NET, "Removed banned node address/subnet: %s\n",
195 sub_net.ToString());
196 } else {
197 ++it;
198 }
199 }
200 }
201 // update UI
202 if (notify_ui && m_client_interface) {
203 m_client_interface->BannedListChanged();
204 }
205}
206
209 return m_is_dirty;
210}
211
213 // reuse m_banned lock for the m_is_dirty flag
215 m_is_dirty = dirty;
216}
void Discourage(const CNetAddr &net_addr)
Definition: banman.cpp:116
void Ban(const CNetAddr &net_addr, int64_t ban_time_offset=0, bool since_unix_epoch=false)
Definition: banman.cpp:110
const int64_t m_default_ban_time
Definition: banman.h:97
void GetBanned(banmap_t &banmap)
Definition: banman.cpp:173
void ClearBanned()
Definition: banman.cpp:64
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
Definition: banman.cpp:83
RecursiveMutex m_cs_banned
Definition: banman.h:92
bool BannedSetIsDirty()
Definition: banman.cpp:207
CClientUIInterface * m_client_interface
Definition: banman.h:95
bool Unban(const CNetAddr &net_addr)
Definition: banman.cpp:151
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:212
~BanMan()
Definition: banman.cpp:39
void SweepBanned()
clean unused entries (if bantime has expired)
Definition: banman.cpp:181
void DumpBanlist()
Definition: banman.cpp:43
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
Definition: banman.cpp:78
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:203
bool Read(banmap_t &banSet, bool &dirty)
Read the banlist from disk.
Definition: addrdb.cpp:216
Definition: addrdb.h:31
int64_t nBanUntil
Definition: addrdb.h:36
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:86
Signals for UI communication.
Definition: ui_interface.h:25
Network address.
Definition: netaddress.h:121
std::vector< uint8_t > GetAddrBytes() const
Definition: netaddress.cpp:858
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:452
#define LogPrintf(...)
Definition: logging.h:424
@ NET
Definition: logging.h:69
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:105
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68