Skip to content

Commit 409bccf

Browse files
committed
use CBanEntry as object container for banned nodes
- added a reason enum for a ban - added creation time for a ban Using CBanEntry as container will keep banlist.dat extenable.
1 parent dfa174c commit 409bccf

File tree

5 files changed

+106
-37
lines changed

5 files changed

+106
-37
lines changed

src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4959,7 +4959,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
49594959
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
49604960
else
49614961
{
4962-
CNode::Ban(pto->addr);
4962+
CNode::Ban(pto->addr, BanReasonNodeMisbehaving);
49634963
}
49644964
}
49654965
state.fShouldBan = false;

src/net.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ void CNode::PushVersion()
443443

444444

445445

446-
std::map<CSubNet, int64_t> CNode::setBanned;
446+
banmap_t CNode::setBanned;
447447
CCriticalSection CNode::cs_setBanned;
448448
bool CNode::setBannedIsDirty;
449449

@@ -459,12 +459,12 @@ bool CNode::IsBanned(CNetAddr ip)
459459
bool fResult = false;
460460
{
461461
LOCK(cs_setBanned);
462-
for (std::map<CSubNet, int64_t>::iterator it = setBanned.begin(); it != setBanned.end(); it++)
462+
for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
463463
{
464464
CSubNet subNet = (*it).first;
465-
int64_t t = (*it).second;
465+
CBanEntry banEntry = (*it).second;
466466

467-
if(subNet.Match(ip) && GetTime() < t)
467+
if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil)
468468
fResult = true;
469469
}
470470
}
@@ -476,30 +476,36 @@ bool CNode::IsBanned(CSubNet subnet)
476476
bool fResult = false;
477477
{
478478
LOCK(cs_setBanned);
479-
std::map<CSubNet, int64_t>::iterator i = setBanned.find(subnet);
479+
banmap_t::iterator i = setBanned.find(subnet);
480480
if (i != setBanned.end())
481481
{
482-
int64_t t = (*i).second;
483-
if (GetTime() < t)
482+
CBanEntry banEntry = (*i).second;
483+
if (GetTime() < banEntry.nBanUntil)
484484
fResult = true;
485485
}
486486
}
487487
return fResult;
488488
}
489489

490-
void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset, bool sinceUnixEpoch) {
490+
void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
491491
CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128"));
492-
Ban(subNet, bantimeoffset, sinceUnixEpoch);
492+
Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
493493
}
494494

495-
void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset, bool sinceUnixEpoch) {
496-
int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
497-
if (bantimeoffset > 0)
498-
banTime = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
495+
void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
496+
CBanEntry banEntry(GetTime());
497+
banEntry.banReason = banReason;
498+
if (bantimeoffset <= 0)
499+
{
500+
bantimeoffset = GetArg("-bantime", 60*60*24); // Default 24-hour ban
501+
sinceUnixEpoch = false;
502+
}
503+
banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
504+
499505

500506
LOCK(cs_setBanned);
501-
if (setBanned[subNet] < banTime)
502-
setBanned[subNet] = banTime;
507+
if (setBanned[subNet].nBanUntil < banEntry.nBanUntil)
508+
setBanned[subNet] = banEntry;
503509

504510
setBannedIsDirty = true;
505511
}
@@ -519,13 +525,13 @@ bool CNode::Unban(const CSubNet &subNet) {
519525
return false;
520526
}
521527

522-
void CNode::GetBanned(std::map<CSubNet, int64_t> &banMap)
528+
void CNode::GetBanned(banmap_t &banMap)
523529
{
524530
LOCK(cs_setBanned);
525531
banMap = setBanned; //create a thread safe copy
526532
}
527533

528-
void CNode::SetBanned(const std::map<CSubNet, int64_t> &banMap)
534+
void CNode::SetBanned(const banmap_t &banMap)
529535
{
530536
LOCK(cs_setBanned);
531537
setBanned = banMap;
@@ -537,10 +543,11 @@ void CNode::SweepBanned()
537543
int64_t now = GetTime();
538544

539545
LOCK(cs_setBanned);
540-
std::map<CSubNet, int64_t>::iterator it = setBanned.begin();
546+
banmap_t::iterator it = setBanned.begin();
541547
while(it != setBanned.end())
542548
{
543-
if(now > (*it).second)
549+
CBanEntry banEntry = (*it).second;
550+
if(now > banEntry.nBanUntil)
544551
{
545552
setBanned.erase(it++);
546553
setBannedIsDirty = true;
@@ -1708,7 +1715,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
17081715

17091716
//try to read stored banlist
17101717
CBanDB bandb;
1711-
std::map<CSubNet, int64_t> banmap;
1718+
banmap_t banmap;
17121719
if (!bandb.Read(banmap))
17131720
LogPrintf("Invalid or missing banlist.dat; recreating\n");
17141721

@@ -2183,7 +2190,7 @@ CBanDB::CBanDB()
21832190
pathBanlist = GetDataDir() / "banlist.dat";
21842191
}
21852192

2186-
bool CBanDB::Write(const std::map<CSubNet, int64_t>& banSet)
2193+
bool CBanDB::Write(const banmap_t& banSet)
21872194
{
21882195
// Generate random temporary filename
21892196
unsigned short randv = 0;
@@ -2221,7 +2228,7 @@ bool CBanDB::Write(const std::map<CSubNet, int64_t>& banSet)
22212228
return true;
22222229
}
22232230

2224-
bool CBanDB::Read(std::map<CSubNet, int64_t>& banSet)
2231+
bool CBanDB::Read(banmap_t& banSet)
22252232
{
22262233
// open input file, and associate with CAutoFile
22272234
FILE *file = fopen(pathBanlist.string().c_str(), "rb");
@@ -2282,7 +2289,7 @@ void DumpBanlist()
22822289
CNode::SweepBanned(); //clean unused entires (if bantime has expired)
22832290

22842291
CBanDB bandb;
2285-
std::map<CSubNet, int64_t> banmap;
2292+
banmap_t banmap;
22862293
CNode::GetBanned(banmap);
22872294
bandb.Write(banmap);
22882295

src/net.h

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,66 @@ class CNetMessage {
228228
};
229229

230230

231+
typedef enum BanReason
232+
{
233+
BanReasonUnknown = 0,
234+
BanReasonNodeMisbehaving = 1,
235+
BanReasonManuallyAdded = 2
236+
} BanReason;
237+
238+
class CBanEntry
239+
{
240+
public:
241+
static const int CURRENT_VERSION=1;
242+
int nVersion;
243+
int64_t nCreateTime;
244+
int64_t nBanUntil;
245+
uint8_t banReason;
246+
247+
CBanEntry()
248+
{
249+
SetNull();
250+
}
251+
252+
CBanEntry(int64_t nCreateTimeIn)
253+
{
254+
SetNull();
255+
nCreateTime = nCreateTimeIn;
256+
}
231257

258+
ADD_SERIALIZE_METHODS;
259+
260+
template <typename Stream, typename Operation>
261+
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
262+
READWRITE(this->nVersion);
263+
nVersion = this->nVersion;
264+
READWRITE(nCreateTime);
265+
READWRITE(nBanUntil);
266+
READWRITE(banReason);
267+
}
268+
269+
void SetNull()
270+
{
271+
nVersion = CBanEntry::CURRENT_VERSION;
272+
nCreateTime = 0;
273+
nBanUntil = 0;
274+
banReason = BanReasonUnknown;
275+
}
276+
277+
std::string banReasonToString()
278+
{
279+
switch (banReason) {
280+
case BanReasonNodeMisbehaving:
281+
return "node misbehabing";
282+
case BanReasonManuallyAdded:
283+
return "manually added";
284+
default:
285+
return "unknown";
286+
}
287+
}
288+
};
232289

290+
typedef std::map<CSubNet, CBanEntry> banmap_t;
233291

234292
/** Information about a peer */
235293
class CNode
@@ -285,7 +343,7 @@ class CNode
285343

286344
// Denial-of-service detection/prevention
287345
// Key is IP address, value is banned-until-time
288-
static std::map<CSubNet, int64_t> setBanned;
346+
static banmap_t setBanned;
289347
static CCriticalSection cs_setBanned;
290348
static bool setBannedIsDirty;
291349

@@ -609,12 +667,12 @@ class CNode
609667
static void ClearBanned(); // needed for unit testing
610668
static bool IsBanned(CNetAddr ip);
611669
static bool IsBanned(CSubNet subnet);
612-
static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
613-
static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
670+
static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
671+
static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
614672
static bool Unban(const CNetAddr &ip);
615673
static bool Unban(const CSubNet &ip);
616-
static void GetBanned(std::map<CSubNet, int64_t> &banmap);
617-
static void SetBanned(const std::map<CSubNet, int64_t> &banmap);
674+
static void GetBanned(banmap_t &banmap);
675+
static void SetBanned(const banmap_t &banmap);
618676

619677
//!check is the banlist has unwritten changes
620678
static bool BannedSetIsDirty();
@@ -660,8 +718,8 @@ class CBanDB
660718
boost::filesystem::path pathBanlist;
661719
public:
662720
CBanDB();
663-
bool Write(const std::map<CSubNet, int64_t>& banSet);
664-
bool Read(std::map<CSubNet, int64_t>& banSet);
721+
bool Write(const banmap_t& banSet);
722+
bool Read(banmap_t& banSet);
665723
};
666724

667725
void DumpBanlist();

src/rpcnet.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ UniValue setban(const UniValue& params, bool fHelp)
515515
if (params.size() == 4 && params[3].isTrue())
516516
absolute = true;
517517

518-
isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute);
518+
isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
519519

520520
//disconnect possible nodes
521521
while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
@@ -542,15 +542,19 @@ UniValue listbanned(const UniValue& params, bool fHelp)
542542
+ HelpExampleRpc("listbanned", "")
543543
);
544544

545-
std::map<CSubNet, int64_t> banMap;
545+
banmap_t banMap;
546546
CNode::GetBanned(banMap);
547547

548548
UniValue bannedAddresses(UniValue::VARR);
549-
for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++)
549+
for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
550550
{
551+
CBanEntry banEntry = (*it).second;
551552
UniValue rec(UniValue::VOBJ);
552553
rec.push_back(Pair("address", (*it).first.ToString()));
553-
rec.push_back(Pair("banned_untill", (*it).second));
554+
rec.push_back(Pair("banned_until", banEntry.nBanUntil));
555+
rec.push_back(Pair("ban_created", banEntry.nCreateTime));
556+
rec.push_back(Pair("ban_reason", banEntry.banReasonToString()));
557+
554558
bannedAddresses.push_back(rec);
555559
}
556560

src/test/rpc_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
199199
ar = r.get_array();
200200
o1 = ar[0].get_obj();
201201
adr = find_value(o1, "address");
202-
UniValue banned_until = find_value(o1, "banned_untill");
202+
UniValue banned_until = find_value(o1, "banned_until");
203203
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
204204
BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check
205205

@@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
210210
ar = r.get_array();
211211
o1 = ar[0].get_obj();
212212
adr = find_value(o1, "address");
213-
banned_until = find_value(o1, "banned_untill");
213+
banned_until = find_value(o1, "banned_until");
214214
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
215215
int64_t now = GetTime();
216216
BOOST_CHECK(banned_until.get_int64() > now);

0 commit comments

Comments
 (0)