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
15BanMan::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
33}
34
36{
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
69bool BanMan::IsDiscouraged(const CNetAddr& net_addr)
70{
72 return m_discouraged.contains(net_addr.GetAddrBytes());
73}
74
75bool 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
90bool 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
104void 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
110void BanMan::Discourage(const CNetAddr& net_addr)
111{
113 m_discouraged.insert(net_addr.GetAddrBytes());
114}
115
116void 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 {
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
142bool BanMan::Unban(const CNetAddr& net_addr)
143{
144 CSubNet sub_net(net_addr);
145 return Unban(sub_net);
146}
147
148bool BanMan::Unban(const CSubNet& sub_net)
149{
150 {
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{
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 {
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{
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}
BanMan(fs::path ban_file, CClientUIInterface *client_interface, int64_t default_ban_time)
Definition: banman.cpp:15
void Discourage(const CNetAddr &net_addr)
Definition: banman.cpp:110
void Ban(const CNetAddr &net_addr, int64_t ban_time_offset=0, bool since_unix_epoch=false)
Definition: banman.cpp:104
const int64_t m_default_ban_time
Definition: banman.h:94
void GetBanned(banmap_t &banmap)
Definition: banman.cpp:160
void ClearBanned()
Definition: banman.cpp:58
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
Definition: banman.cpp:75
RecursiveMutex m_cs_banned
Definition: banman.h:89
bool BannedSetIsDirty()
Definition: banman.cpp:193
CClientUIInterface * m_client_interface
Definition: banman.h:92
bool Unban(const CNetAddr &net_addr)
Definition: banman.cpp:142
CBanDB m_ban_db
Definition: banman.h:93
void SetBannedSetDirty(bool dirty=true)
set the "dirty" flag for the banlist
Definition: banman.cpp:199
~BanMan()
Definition: banman.cpp:35
void SweepBanned()
clean unused entries (if bantime has expired)
Definition: banman.cpp:168
void DumpBanlist()
Definition: banman.cpp:40
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
Definition: banman.cpp:69
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:130
bool Read(banmap_t &banSet)
Read the banlist from disk.
Definition: addrdb.cpp:143
Definition: net_types.h:15
int64_t nBanUntil
Definition: net_types.h:20
Signals for UI communication.
Definition: ui_interface.h:25
Network address.
Definition: netaddress.h:119
std::vector< unsigned char > GetAddrBytes() const
Definition: netaddress.cpp:826
std::string ToString() const
bool IsValid() const
bool Match(const CNetAddr &addr) const
Path class wrapper to prepare application code for transition from boost::filesystem library to std::...
Definition: fs.h:34
#define LogPrint(category,...)
Definition: logging.h:191
#define LogPrintf(...)
Definition: logging.h:187
@ NET
Definition: logging.h:38
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:41
#define LOCK(cs)
Definition: sync.h:226
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:117
int64_t GetTime()
DEPRECATED Use either GetTimeSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:26
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:63