From fcc8920f36fc306c5c1ead6ab41c81e9c55495c8 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 12 Jun 2015 18:31:47 +0200 Subject: [PATCH] setban: rewrite to UniValue, allow absolute bantime --- src/net.cpp | 8 ++++---- src/net.h | 4 ++-- src/rpcclient.cpp | 1 + src/rpcnet.cpp | 27 ++++++++++++++++----------- src/rpcserver.h | 6 +++--- src/test/rpc_tests.cpp | 25 ++++++++++++++++++++----- 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 53d073c062c..1805c8af76c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -490,15 +490,15 @@ bool CNode::IsBanned(CSubNet subnet) return fResult; } -void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset) { +void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset, bool sinceUnixEpoch) { CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); - Ban(subNet, bantimeoffset); + Ban(subNet, bantimeoffset, sinceUnixEpoch); } -void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset) { +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 = GetTime()+bantimeoffset; + banTime = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; LOCK(cs_setBanned); if (setBanned[subNet] < banTime) diff --git a/src/net.h b/src/net.h index 77a0bd02921..95bb79e1ac4 100644 --- a/src/net.h +++ b/src/net.h @@ -615,8 +615,8 @@ class CNode 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); - static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0); + 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 bool Unban(const CNetAddr &ip); static bool Unban(const CSubNet &ip); static void GetBanned(std::map &banmap); diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index c40fbeedda1..1d0073a081e 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -93,6 +93,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 1 }, { "prioritisetransaction", 2 }, { "setban", 2 }, + { "setban", 3 }, { "zcrawjoinsplit", 1 }, { "zcrawjoinsplit", 2 }, { "zcrawjoinsplit", 3 }, diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 08e01689051..19d6c61ca9a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -467,7 +467,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) return obj; } -Value setban(const Array& params, bool fHelp) +UniValue setban(const UniValue& params, bool fHelp) { string strCommand; if (params.size() >= 2) @@ -475,12 +475,13 @@ Value setban(const Array& params, bool fHelp) if (fHelp || params.size() < 2 || (strCommand != "add" && strCommand != "remove")) throw runtime_error( - "setban \"ip(/netmask)\" \"add|remove\" (bantime)\n" + "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n" "\nAttempts add or remove a IP/Subnet from the banned list.\n" "\nArguments:\n" "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n" "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n" - "1. \"bantime\" (numeric, optional) time in seconds how long the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") @@ -508,10 +509,14 @@ Value setban(const Array& params, bool fHelp) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); int64_t banTime = 0; //use standard bantime if not specified - if (params.size() == 3 && !params[2].is_null()) + if (params.size() >= 3 && !params[2].isNull()) banTime = params[2].get_int64(); - isSubnet ? CNode::Ban(subNet, banTime) : CNode::Ban(netAddr, banTime); + bool absolute = false; + if (params.size() == 4 && params[3].isTrue()) + absolute = true; + + isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute); //disconnect possible nodes while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) @@ -523,10 +528,10 @@ Value setban(const Array& params, bool fHelp) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Unban failed"); } - return Value::null; + return NullUniValue; } -Value listbanned(const Array& params, bool fHelp) +UniValue listbanned(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -540,10 +545,10 @@ Value listbanned(const Array& params, bool fHelp) std::map banMap; CNode::GetBanned(banMap); - Array bannedAddresses; + UniValue bannedAddresses(UniValue::VARR); for (std::map::iterator it = banMap.begin(); it != banMap.end(); it++) { - Object rec; + UniValue rec(UniValue::VOBJ); rec.push_back(Pair("address", (*it).first.ToString())); rec.push_back(Pair("banned_untill", (*it).second)); bannedAddresses.push_back(rec); @@ -552,7 +557,7 @@ Value listbanned(const Array& params, bool fHelp) return bannedAddresses; } -Value clearbanned(const Array& params, bool fHelp) +UniValue clearbanned(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -565,5 +570,5 @@ Value clearbanned(const Array& params, bool fHelp) CNode::ClearBanned(); - return Value::null; + return NullUniValue; } diff --git a/src/rpcserver.h b/src/rpcserver.h index 18e5bbbaa5e..9a090d0def3 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -161,9 +161,9 @@ extern UniValue addnode(const UniValue& params, bool fHelp); extern UniValue disconnectnode(const UniValue& params, bool fHelp); extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); extern UniValue getnettotals(const UniValue& params, bool fHelp); -extern UniValue setban(const json_spirit::Array& params, bool fHelp); -extern UniValue listbanned(const json_spirit::Array& params, bool fHelp); -extern UniValue clearbanned(const json_spirit::Array& params, bool fHelp); +extern UniValue setban(const UniValue& params, bool fHelp); +extern UniValue listbanned(const UniValue& params, bool fHelp); +extern UniValue clearbanned(const UniValue& params, bool fHelp); extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp extern UniValue importprivkey(const UniValue& params, bool fHelp); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index f26ced30d90..1e9fd684741 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -231,25 +231,40 @@ BOOST_AUTO_TEST_CASE(rpc_ban) { BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); - Value r; + UniValue r; BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0 add"))); BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.0:8334")), runtime_error); //portnumber for setban not allowed BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); - Array ar = r.get_array(); - Object o1 = ar[0].get_obj(); - Value adr = find_value(o1, "address"); + UniValue ar = r.get_array(); + UniValue o1 = ar[0].get_obj(); + UniValue adr = find_value(o1, "address"); BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.255"); BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));; BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); BOOST_CHECK_EQUAL(ar.size(), 0); - BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 1607731200 true"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + UniValue banned_until = find_value(o1, "banned_untill"); + 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 + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 200"))); BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); + banned_until = find_value(o1, "banned_untill"); 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); + BOOST_CHECK(banned_until.get_int64()-now <= 200); // must throw an exception because 127.0.0.1 is in already banned suubnet range BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.1 add")), runtime_error);