aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.cpp2
-rw-r--r--src/net.cpp53
-rw-r--r--src/net.h72
-rw-r--r--src/rpcnet.cpp12
-rw-r--r--src/test/rpc_tests.cpp4
5 files changed, 106 insertions, 37 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 6c4cfe75aa..a000a81fd9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4959,7 +4959,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
else
{
- CNode::Ban(pto->addr);
+ CNode::Ban(pto->addr, BanReasonNodeMisbehaving);
}
}
state.fShouldBan = false;
diff --git a/src/net.cpp b/src/net.cpp
index 03db1f06a4..ade34f5754 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -443,7 +443,7 @@ void CNode::PushVersion()
-std::map<CSubNet, int64_t> CNode::setBanned;
+banmap_t CNode::setBanned;
CCriticalSection CNode::cs_setBanned;
bool CNode::setBannedIsDirty;
@@ -459,12 +459,12 @@ bool CNode::IsBanned(CNetAddr ip)
bool fResult = false;
{
LOCK(cs_setBanned);
- for (std::map<CSubNet, int64_t>::iterator it = setBanned.begin(); it != setBanned.end(); it++)
+ for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
{
CSubNet subNet = (*it).first;
- int64_t t = (*it).second;
+ CBanEntry banEntry = (*it).second;
- if(subNet.Match(ip) && GetTime() < t)
+ if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil)
fResult = true;
}
}
@@ -476,30 +476,36 @@ bool CNode::IsBanned(CSubNet subnet)
bool fResult = false;
{
LOCK(cs_setBanned);
- std::map<CSubNet, int64_t>::iterator i = setBanned.find(subnet);
+ banmap_t::iterator i = setBanned.find(subnet);
if (i != setBanned.end())
{
- int64_t t = (*i).second;
- if (GetTime() < t)
+ CBanEntry banEntry = (*i).second;
+ if (GetTime() < banEntry.nBanUntil)
fResult = true;
}
}
return fResult;
}
-void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset, bool sinceUnixEpoch) {
+void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128"));
- Ban(subNet, bantimeoffset, sinceUnixEpoch);
+ Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
}
-void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset, bool sinceUnixEpoch) {
- int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
- if (bantimeoffset > 0)
- banTime = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
+void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
+ CBanEntry banEntry(GetTime());
+ banEntry.banReason = banReason;
+ if (bantimeoffset <= 0)
+ {
+ bantimeoffset = GetArg("-bantime", 60*60*24); // Default 24-hour ban
+ sinceUnixEpoch = false;
+ }
+ banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
+
LOCK(cs_setBanned);
- if (setBanned[subNet] < banTime)
- setBanned[subNet] = banTime;
+ if (setBanned[subNet].nBanUntil < banEntry.nBanUntil)
+ setBanned[subNet] = banEntry;
setBannedIsDirty = true;
}
@@ -519,13 +525,13 @@ bool CNode::Unban(const CSubNet &subNet) {
return false;
}
-void CNode::GetBanned(std::map<CSubNet, int64_t> &banMap)
+void CNode::GetBanned(banmap_t &banMap)
{
LOCK(cs_setBanned);
banMap = setBanned; //create a thread safe copy
}
-void CNode::SetBanned(const std::map<CSubNet, int64_t> &banMap)
+void CNode::SetBanned(const banmap_t &banMap)
{
LOCK(cs_setBanned);
setBanned = banMap;
@@ -537,10 +543,11 @@ void CNode::SweepBanned()
int64_t now = GetTime();
LOCK(cs_setBanned);
- std::map<CSubNet, int64_t>::iterator it = setBanned.begin();
+ banmap_t::iterator it = setBanned.begin();
while(it != setBanned.end())
{
- if(now > (*it).second)
+ CBanEntry banEntry = (*it).second;
+ if(now > banEntry.nBanUntil)
{
setBanned.erase(it++);
setBannedIsDirty = true;
@@ -1708,7 +1715,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
//try to read stored banlist
CBanDB bandb;
- std::map<CSubNet, int64_t> banmap;
+ banmap_t banmap;
if (!bandb.Read(banmap))
LogPrintf("Invalid or missing banlist.dat; recreating\n");
@@ -2183,7 +2190,7 @@ CBanDB::CBanDB()
pathBanlist = GetDataDir() / "banlist.dat";
}
-bool CBanDB::Write(const std::map<CSubNet, int64_t>& banSet)
+bool CBanDB::Write(const banmap_t& banSet)
{
// Generate random temporary filename
unsigned short randv = 0;
@@ -2221,7 +2228,7 @@ bool CBanDB::Write(const std::map<CSubNet, int64_t>& banSet)
return true;
}
-bool CBanDB::Read(std::map<CSubNet, int64_t>& banSet)
+bool CBanDB::Read(banmap_t& banSet)
{
// open input file, and associate with CAutoFile
FILE *file = fopen(pathBanlist.string().c_str(), "rb");
@@ -2282,7 +2289,7 @@ void DumpBanlist()
CNode::SweepBanned(); //clean unused entires (if bantime has expired)
CBanDB bandb;
- std::map<CSubNet, int64_t> banmap;
+ banmap_t banmap;
CNode::GetBanned(banmap);
bandb.Write(banmap);
diff --git a/src/net.h b/src/net.h
index 42c859e460..f15b85474f 100644
--- a/src/net.h
+++ b/src/net.h
@@ -228,8 +228,66 @@ public:
};
+typedef enum BanReason
+{
+ BanReasonUnknown = 0,
+ BanReasonNodeMisbehaving = 1,
+ BanReasonManuallyAdded = 2
+} BanReason;
+
+class CBanEntry
+{
+public:
+ static const int CURRENT_VERSION=1;
+ int nVersion;
+ int64_t nCreateTime;
+ int64_t nBanUntil;
+ uint8_t banReason;
+
+ CBanEntry()
+ {
+ SetNull();
+ }
+
+ CBanEntry(int64_t nCreateTimeIn)
+ {
+ SetNull();
+ nCreateTime = nCreateTimeIn;
+ }
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(nCreateTime);
+ READWRITE(nBanUntil);
+ READWRITE(banReason);
+ }
+
+ void SetNull()
+ {
+ nVersion = CBanEntry::CURRENT_VERSION;
+ nCreateTime = 0;
+ nBanUntil = 0;
+ banReason = BanReasonUnknown;
+ }
+
+ std::string banReasonToString()
+ {
+ switch (banReason) {
+ case BanReasonNodeMisbehaving:
+ return "node misbehabing";
+ case BanReasonManuallyAdded:
+ return "manually added";
+ default:
+ return "unknown";
+ }
+ }
+};
+typedef std::map<CSubNet, CBanEntry> banmap_t;
/** Information about a peer */
class CNode
@@ -285,7 +343,7 @@ protected:
// Denial-of-service detection/prevention
// Key is IP address, value is banned-until-time
- static std::map<CSubNet, int64_t> setBanned;
+ static banmap_t setBanned;
static CCriticalSection cs_setBanned;
static bool setBannedIsDirty;
@@ -609,12 +667,12 @@ public:
static void ClearBanned(); // needed for unit testing
static bool IsBanned(CNetAddr ip);
static bool IsBanned(CSubNet subnet);
- static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
- static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
+ static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
+ static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
static bool Unban(const CNetAddr &ip);
static bool Unban(const CSubNet &ip);
- static void GetBanned(std::map<CSubNet, int64_t> &banmap);
- static void SetBanned(const std::map<CSubNet, int64_t> &banmap);
+ static void GetBanned(banmap_t &banmap);
+ static void SetBanned(const banmap_t &banmap);
//!check is the banlist has unwritten changes
static bool BannedSetIsDirty();
@@ -660,8 +718,8 @@ private:
boost::filesystem::path pathBanlist;
public:
CBanDB();
- bool Write(const std::map<CSubNet, int64_t>& banSet);
- bool Read(std::map<CSubNet, int64_t>& banSet);
+ bool Write(const banmap_t& banSet);
+ bool Read(banmap_t& banSet);
};
void DumpBanlist();
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 0c3745a7da..dd631905fd 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -515,7 +515,7 @@ UniValue setban(const UniValue& params, bool fHelp)
if (params.size() == 4 && params[3].isTrue())
absolute = true;
- isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute);
+ isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
//disconnect possible nodes
while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
@@ -542,15 +542,19 @@ UniValue listbanned(const UniValue& params, bool fHelp)
+ HelpExampleRpc("listbanned", "")
);
- std::map<CSubNet, int64_t> banMap;
+ banmap_t banMap;
CNode::GetBanned(banMap);
UniValue bannedAddresses(UniValue::VARR);
- for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++)
+ for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
{
+ CBanEntry banEntry = (*it).second;
UniValue rec(UniValue::VOBJ);
rec.push_back(Pair("address", (*it).first.ToString()));
- rec.push_back(Pair("banned_untill", (*it).second));
+ rec.push_back(Pair("banned_until", banEntry.nBanUntil));
+ rec.push_back(Pair("ban_created", banEntry.nCreateTime));
+ rec.push_back(Pair("ban_reason", banEntry.banReasonToString()));
+
bannedAddresses.push_back(rec);
}
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index c38df0ecf3..9e99ff6286 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
ar = r.get_array();
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
- UniValue banned_until = find_value(o1, "banned_untill");
+ UniValue banned_until = find_value(o1, "banned_until");
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check
@@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
ar = r.get_array();
o1 = ar[0].get_obj();
adr = find_value(o1, "address");
- banned_until = find_value(o1, "banned_untill");
+ banned_until = find_value(o1, "banned_until");
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
int64_t now = GetTime();
BOOST_CHECK(banned_until.get_int64() > now);