1 // Copyright (c) 2009-2015 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "rpc/server.h"
6 
7 #include "chainparams.h"
8 #include "clientversion.h"
9 #include "main.h"
10 #include "net.h"
11 #include "netbase.h"
12 #include "protocol.h"
13 #include "sync.h"
14 #include "timedata.h"
15 #include "ui_interface.h"
16 #include "util.h"
17 #include "utilstrencodings.h"
18 #include "version.h"
19 
20 #include <boost/foreach.hpp>
21 
22 #include <univalue.h>
23 
24 using namespace std;
25 
getconnectioncount(const UniValue & params,bool fHelp)26 UniValue getconnectioncount(const UniValue& params, bool fHelp)
27 {
28     if (fHelp || params.size() != 0)
29         throw runtime_error(
30             "getconnectioncount\n"
31             "\nReturns the number of connections to other nodes.\n"
32             "\nResult:\n"
33             "n          (numeric) The connection count\n"
34             "\nExamples:\n"
35             + HelpExampleCli("getconnectioncount", "")
36             + HelpExampleRpc("getconnectioncount", "")
37         );
38 
39     LOCK2(cs_main, cs_vNodes);
40 
41     return (int)vNodes.size();
42 }
43 
ping(const UniValue & params,bool fHelp)44 UniValue ping(const UniValue& params, bool fHelp)
45 {
46     if (fHelp || params.size() != 0)
47         throw runtime_error(
48             "ping\n"
49             "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
50             "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
51             "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
52             "\nExamples:\n"
53             + HelpExampleCli("ping", "")
54             + HelpExampleRpc("ping", "")
55         );
56 
57     // Request that each node send a ping during next message processing pass
58     LOCK2(cs_main, cs_vNodes);
59 
60     BOOST_FOREACH(CNode* pNode, vNodes) {
61         pNode->fPingQueued = true;
62     }
63 
64     return NullUniValue;
65 }
66 
CopyNodeStats(std::vector<CNodeStats> & vstats)67 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
68 {
69     vstats.clear();
70 
71     LOCK(cs_vNodes);
72     vstats.reserve(vNodes.size());
73     BOOST_FOREACH(CNode* pnode, vNodes) {
74         CNodeStats stats;
75         pnode->copyStats(stats);
76         vstats.push_back(stats);
77     }
78 }
79 
getpeerinfo(const UniValue & params,bool fHelp)80 UniValue getpeerinfo(const UniValue& params, bool fHelp)
81 {
82     if (fHelp || params.size() != 0)
83         throw runtime_error(
84             "getpeerinfo\n"
85             "\nReturns data about each connected network node as a json array of objects.\n"
86             "\nResult:\n"
87             "[\n"
88             "  {\n"
89             "    \"id\": n,                   (numeric) Peer index\n"
90             "    \"addr\":\"host:port\",      (string) The ip address and port of the peer\n"
91             "    \"addrlocal\":\"ip:port\",   (string) local address\n"
92             "    \"services\":\"xxxxxxxxxxxxxxxx\",   (string) The services offered\n"
93             "    \"relaytxes\":true|false,    (boolean) Whether peer has asked us to relay transactions to it\n"
94             "    \"lastsend\": ttt,           (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
95             "    \"lastrecv\": ttt,           (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
96             "    \"bytessent\": n,            (numeric) The total bytes sent\n"
97             "    \"bytesrecv\": n,            (numeric) The total bytes received\n"
98             "    \"conntime\": ttt,           (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
99             "    \"timeoffset\": ttt,         (numeric) The time offset in seconds\n"
100             "    \"pingtime\": n,             (numeric) ping time (if available)\n"
101             "    \"minping\": n,              (numeric) minimum observed ping time (if any at all)\n"
102             "    \"pingwait\": n,             (numeric) ping wait (if non-zero)\n"
103             "    \"version\": v,              (numeric) The peer version, such as 7001\n"
104             "    \"subver\": \"/Satoshi:0.8.5/\",  (string) The string version\n"
105             "    \"inbound\": true|false,     (boolean) Inbound (true) or Outbound (false)\n"
106             "    \"startingheight\": n,       (numeric) The starting height (block) of the peer\n"
107             "    \"banscore\": n,             (numeric) The ban score\n"
108             "    \"synced_headers\": n,       (numeric) The last header we have in common with this peer\n"
109             "    \"synced_blocks\": n,        (numeric) The last block we have in common with this peer\n"
110             "    \"inflight\": [\n"
111             "       n,                        (numeric) The heights of blocks we're currently asking from this peer\n"
112             "       ...\n"
113             "    ]\n"
114             "    \"bytessent_per_msg\": {\n"
115             "       \"addr\": n,             (numeric) The total bytes sent aggregated by message type\n"
116             "       ...\n"
117             "    }\n"
118             "    \"bytesrecv_per_msg\": {\n"
119             "       \"addr\": n,             (numeric) The total bytes received aggregated by message type\n"
120             "       ...\n"
121             "    }\n"
122             "  }\n"
123             "  ,...\n"
124             "]\n"
125             "\nExamples:\n"
126             + HelpExampleCli("getpeerinfo", "")
127             + HelpExampleRpc("getpeerinfo", "")
128         );
129 
130     LOCK(cs_main);
131 
132     vector<CNodeStats> vstats;
133     CopyNodeStats(vstats);
134 
135     UniValue ret(UniValue::VARR);
136 
137     BOOST_FOREACH(const CNodeStats& stats, vstats) {
138         UniValue obj(UniValue::VOBJ);
139         CNodeStateStats statestats;
140         bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
141         obj.push_back(Pair("id", stats.nodeid));
142         obj.push_back(Pair("addr", stats.addrName));
143         if (!(stats.addrLocal.empty()))
144             obj.push_back(Pair("addrlocal", stats.addrLocal));
145         obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
146         obj.push_back(Pair("relaytxes", stats.fRelayTxes));
147         obj.push_back(Pair("lastsend", stats.nLastSend));
148         obj.push_back(Pair("lastrecv", stats.nLastRecv));
149         obj.push_back(Pair("bytessent", stats.nSendBytes));
150         obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
151         obj.push_back(Pair("conntime", stats.nTimeConnected));
152         obj.push_back(Pair("timeoffset", stats.nTimeOffset));
153         if (stats.dPingTime > 0.0)
154             obj.push_back(Pair("pingtime", stats.dPingTime));
155         if (stats.dPingMin < std::numeric_limits<int64_t>::max()/1e6)
156             obj.push_back(Pair("minping", stats.dPingMin));
157         if (stats.dPingWait > 0.0)
158             obj.push_back(Pair("pingwait", stats.dPingWait));
159         obj.push_back(Pair("version", stats.nVersion));
160         // Use the sanitized form of subver here, to avoid tricksy remote peers from
161         // corrupting or modifiying the JSON output by putting special characters in
162         // their ver message.
163         obj.push_back(Pair("subver", stats.cleanSubVer));
164         obj.push_back(Pair("inbound", stats.fInbound));
165         obj.push_back(Pair("startingheight", stats.nStartingHeight));
166         if (fStateStats) {
167             obj.push_back(Pair("banscore", statestats.nMisbehavior));
168             obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
169             obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
170             UniValue heights(UniValue::VARR);
171             BOOST_FOREACH(int height, statestats.vHeightInFlight) {
172                 heights.push_back(height);
173             }
174             obj.push_back(Pair("inflight", heights));
175         }
176         obj.push_back(Pair("whitelisted", stats.fWhitelisted));
177 
178         UniValue sendPerMsgCmd(UniValue::VOBJ);
179         BOOST_FOREACH(const mapMsgCmdSize::value_type &i, stats.mapSendBytesPerMsgCmd) {
180             if (i.second > 0)
181                 sendPerMsgCmd.push_back(Pair(i.first, i.second));
182         }
183         obj.push_back(Pair("bytessent_per_msg", sendPerMsgCmd));
184 
185         UniValue recvPerMsgCmd(UniValue::VOBJ);
186         BOOST_FOREACH(const mapMsgCmdSize::value_type &i, stats.mapRecvBytesPerMsgCmd) {
187             if (i.second > 0)
188                 recvPerMsgCmd.push_back(Pair(i.first, i.second));
189         }
190         obj.push_back(Pair("bytesrecv_per_msg", recvPerMsgCmd));
191 
192         ret.push_back(obj);
193     }
194 
195     return ret;
196 }
197 
addnode(const UniValue & params,bool fHelp)198 UniValue addnode(const UniValue& params, bool fHelp)
199 {
200     string strCommand;
201     if (params.size() == 2)
202         strCommand = params[1].get_str();
203     if (fHelp || params.size() != 2 ||
204         (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
205         throw runtime_error(
206             "addnode \"node\" \"add|remove|onetry\"\n"
207             "\nAttempts add or remove a node from the addnode list.\n"
208             "Or try a connection to a node once.\n"
209             "\nArguments:\n"
210             "1. \"node\"     (string, required) The node (see getpeerinfo for nodes)\n"
211             "2. \"command\"  (string, required) 'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once\n"
212             "\nExamples:\n"
213             + HelpExampleCli("addnode", "\"192.168.0.6:17333\" \"onetry\"")
214             + HelpExampleRpc("addnode", "\"192.168.0.6:17333\", \"onetry\"")
215         );
216 
217     string strNode = params[0].get_str();
218 
219     if (strCommand == "onetry")
220     {
221         CAddress addr;
222         OpenNetworkConnection(addr, false, NULL, strNode.c_str());
223         return NullUniValue;
224     }
225 
226     LOCK(cs_vAddedNodes);
227     vector<string>::iterator it = vAddedNodes.begin();
228     for(; it != vAddedNodes.end(); it++)
229         if (strNode == *it)
230             break;
231 
232     if (strCommand == "add")
233     {
234         if (it != vAddedNodes.end())
235             throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
236         vAddedNodes.push_back(strNode);
237     }
238     else if(strCommand == "remove")
239     {
240         if (it == vAddedNodes.end())
241             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
242         vAddedNodes.erase(it);
243     }
244 
245     return NullUniValue;
246 }
247 
disconnectnode(const UniValue & params,bool fHelp)248 UniValue disconnectnode(const UniValue& params, bool fHelp)
249 {
250     if (fHelp || params.size() != 1)
251         throw runtime_error(
252             "disconnectnode \"node\" \n"
253             "\nImmediately disconnects from the specified node.\n"
254             "\nArguments:\n"
255             "1. \"node\"     (string, required) The node (see getpeerinfo for nodes)\n"
256             "\nExamples:\n"
257             + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
258             + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
259         );
260 
261     CNode* pNode = FindNode(params[0].get_str());
262     if (pNode == NULL)
263         throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
264 
265     pNode->fDisconnect = true;
266 
267     return NullUniValue;
268 }
269 
getaddednodeinfo(const UniValue & params,bool fHelp)270 UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
271 {
272     if (fHelp || params.size() < 1 || params.size() > 2)
273         throw runtime_error(
274             "getaddednodeinfo dummy ( \"node\" )\n"
275             "\nReturns information about the given added node, or all added nodes\n"
276             "(note that onetry addnodes are not listed here)\n"
277             "\nArguments:\n"
278             "1. dummy      (boolean, required) Kept for historical purposes but ignored\n"
279             "2. \"node\"   (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
280             "\nResult:\n"
281             "[\n"
282             "  {\n"
283             "    \"addednode\" : \"192.168.0.201\",   (string) The node ip address or name (as provided to addnode)\n"
284             "    \"connected\" : true|false,          (boolean) If connected\n"
285             "    \"addresses\" : [                    (list of objects) Only when connected = true\n"
286             "       {\n"
287             "         \"address\" : \"192.168.0.201:8333\",  (string) The zetacoin server IP and port we're connected to\n"
288             "         \"connected\" : \"outbound\"           (string) connection, inbound or outbound\n"
289             "       }\n"
290             "     ]\n"
291             "  }\n"
292             "  ,...\n"
293             "]\n"
294             "\nExamples:\n"
295             + HelpExampleCli("getaddednodeinfo", "true")
296             + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
297             + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
298         );
299 
300     std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
301 
302     if (params.size() == 2) {
303         bool found = false;
304         for (const AddedNodeInfo& info : vInfo) {
305             if (info.strAddedNode == params[1].get_str()) {
306                 vInfo.assign(1, info);
307                 found = true;
308                 break;
309             }
310         }
311         if (!found) {
312             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
313         }
314     }
315 
316     UniValue ret(UniValue::VARR);
317 
318     for (const AddedNodeInfo& info : vInfo) {
319         UniValue obj(UniValue::VOBJ);
320         obj.push_back(Pair("addednode", info.strAddedNode));
321         obj.push_back(Pair("connected", info.fConnected));
322         UniValue addresses(UniValue::VARR);
323         if (info.fConnected) {
324             UniValue address(UniValue::VOBJ);
325             address.push_back(Pair("address", info.resolvedAddress.ToString()));
326             address.push_back(Pair("connected", info.fInbound ? "inbound" : "outbound"));
327             addresses.push_back(address);
328         }
329         obj.push_back(Pair("addresses", addresses));
330         ret.push_back(obj);
331     }
332 
333     return ret;
334 }
335 
getnettotals(const UniValue & params,bool fHelp)336 UniValue getnettotals(const UniValue& params, bool fHelp)
337 {
338     if (fHelp || params.size() > 0)
339         throw runtime_error(
340             "getnettotals\n"
341             "\nReturns information about network traffic, including bytes in, bytes out,\n"
342             "and current time.\n"
343             "\nResult:\n"
344             "{\n"
345             "  \"totalbytesrecv\": n,   (numeric) Total bytes received\n"
346             "  \"totalbytessent\": n,   (numeric) Total bytes sent\n"
347             "  \"timemillis\": t,       (numeric) Current UNIX time in milliseconds\n"
348             "  \"uploadtarget\":\n"
349             "  {\n"
350             "    \"timeframe\": n,                         (numeric) Length of the measuring timeframe in seconds\n"
351             "    \"target\": n,                            (numeric) Target in bytes\n"
352             "    \"target_reached\": true|false,           (boolean) True if target is reached\n"
353             "    \"serve_historical_blocks\": true|false,  (boolean) True if serving historical blocks\n"
354             "    \"bytes_left_in_cycle\": t,               (numeric) Bytes left in current time cycle\n"
355             "    \"time_left_in_cycle\": t                 (numeric) Seconds left in current time cycle\n"
356             "  }\n"
357             "}\n"
358             "\nExamples:\n"
359             + HelpExampleCli("getnettotals", "")
360             + HelpExampleRpc("getnettotals", "")
361        );
362 
363     UniValue obj(UniValue::VOBJ);
364     obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
365     obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
366     obj.push_back(Pair("timemillis", GetTimeMillis()));
367 
368     UniValue outboundLimit(UniValue::VOBJ);
369     outboundLimit.push_back(Pair("timeframe", CNode::GetMaxOutboundTimeframe()));
370     outboundLimit.push_back(Pair("target", CNode::GetMaxOutboundTarget()));
371     outboundLimit.push_back(Pair("target_reached", CNode::OutboundTargetReached(false)));
372     outboundLimit.push_back(Pair("serve_historical_blocks", !CNode::OutboundTargetReached(true)));
373     outboundLimit.push_back(Pair("bytes_left_in_cycle", CNode::GetOutboundTargetBytesLeft()));
374     outboundLimit.push_back(Pair("time_left_in_cycle", CNode::GetMaxOutboundTimeLeftInCycle()));
375     obj.push_back(Pair("uploadtarget", outboundLimit));
376     return obj;
377 }
378 
GetNetworksInfo()379 static UniValue GetNetworksInfo()
380 {
381     UniValue networks(UniValue::VARR);
382     for(int n=0; n<NET_MAX; ++n)
383     {
384         enum Network network = static_cast<enum Network>(n);
385         if(network == NET_UNROUTABLE)
386             continue;
387         proxyType proxy;
388         UniValue obj(UniValue::VOBJ);
389         GetProxy(network, proxy);
390         obj.push_back(Pair("name", GetNetworkName(network)));
391         obj.push_back(Pair("limited", IsLimited(network)));
392         obj.push_back(Pair("reachable", IsReachable(network)));
393         obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
394         obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
395         networks.push_back(obj);
396     }
397     return networks;
398 }
399 
getnetworkinfo(const UniValue & params,bool fHelp)400 UniValue getnetworkinfo(const UniValue& params, bool fHelp)
401 {
402     if (fHelp || params.size() != 0)
403         throw runtime_error(
404             "getnetworkinfo\n"
405             "Returns an object containing various state info regarding P2P networking.\n"
406             "\nResult:\n"
407             "{\n"
408             "  \"version\": xxxxx,                      (numeric) the server version\n"
409             "  \"subversion\": \"/Satoshi:x.x.x/\",     (string) the server subversion string\n"
410             "  \"protocolversion\": xxxxx,              (numeric) the protocol version\n"
411             "  \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
412             "  \"localrelay\": true|false,              (bool) true if transaction relay is requested from peers\n"
413             "  \"timeoffset\": xxxxx,                   (numeric) the time offset\n"
414             "  \"connections\": xxxxx,                  (numeric) the number of connections\n"
415             "  \"networks\": [                          (array) information per network\n"
416             "  {\n"
417             "    \"name\": \"xxx\",                     (string) network (ipv4, ipv6 or onion)\n"
418             "    \"limited\": true|false,               (boolean) is the network limited using -onlynet?\n"
419             "    \"reachable\": true|false,             (boolean) is the network reachable?\n"
420             "    \"proxy\": \"host:port\"               (string) the proxy that is used for this network, or empty if none\n"
421             "  }\n"
422             "  ,...\n"
423             "  ],\n"
424             "  \"relayfee\": x.xxxxxxxx,                (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
425             "  \"localaddresses\": [                    (array) list of local addresses\n"
426             "  {\n"
427             "    \"address\": \"xxxx\",                 (string) network address\n"
428             "    \"port\": xxx,                         (numeric) network port\n"
429             "    \"score\": xxx                         (numeric) relative score\n"
430             "  }\n"
431             "  ,...\n"
432             "  ]\n"
433             "  \"warnings\": \"...\"                    (string) any network warnings (such as alert messages) \n"
434             "}\n"
435             "\nExamples:\n"
436             + HelpExampleCli("getnetworkinfo", "")
437             + HelpExampleRpc("getnetworkinfo", "")
438         );
439 
440     LOCK(cs_main);
441 
442     UniValue obj(UniValue::VOBJ);
443     obj.push_back(Pair("version",       CLIENT_VERSION));
444     obj.push_back(Pair("subversion",    strSubVersion));
445     obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
446     obj.push_back(Pair("localservices",       strprintf("%016x", nLocalServices)));
447     obj.push_back(Pair("localrelay",     fRelayTxes));
448     obj.push_back(Pair("timeoffset",    GetTimeOffset()));
449     obj.push_back(Pair("connections",   (int)vNodes.size()));
450     obj.push_back(Pair("networks",      GetNetworksInfo()));
451     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
452     UniValue localAddresses(UniValue::VARR);
453     {
454         LOCK(cs_mapLocalHost);
455         BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
456         {
457             UniValue rec(UniValue::VOBJ);
458             rec.push_back(Pair("address", item.first.ToString()));
459             rec.push_back(Pair("port", item.second.nPort));
460             rec.push_back(Pair("score", item.second.nScore));
461             localAddresses.push_back(rec);
462         }
463     }
464     obj.push_back(Pair("localaddresses", localAddresses));
465     obj.push_back(Pair("warnings",       GetWarnings("statusbar")));
466     return obj;
467 }
468 
setban(const UniValue & params,bool fHelp)469 UniValue setban(const UniValue& params, bool fHelp)
470 {
471     string strCommand;
472     if (params.size() >= 2)
473         strCommand = params[1].get_str();
474     if (fHelp || params.size() < 2 ||
475         (strCommand != "add" && strCommand != "remove"))
476         throw runtime_error(
477                             "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n"
478                             "\nAttempts add or remove a IP/Subnet from the banned list.\n"
479                             "\nArguments:\n"
480                             "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n"
481                             "2. \"command\"      (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n"
482                             "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"
483                             "4. \"absolute\"     (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
484                             "\nExamples:\n"
485                             + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
486                             + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
487                             + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
488                             );
489 
490     CSubNet subNet;
491     CNetAddr netAddr;
492     bool isSubnet = false;
493 
494     if (params[0].get_str().find("/") != string::npos)
495         isSubnet = true;
496 
497     if (!isSubnet)
498         netAddr = CNetAddr(params[0].get_str());
499     else
500         subNet = CSubNet(params[0].get_str());
501 
502     if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
503         throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
504 
505     if (strCommand == "add")
506     {
507         if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
508             throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
509 
510         int64_t banTime = 0; //use standard bantime if not specified
511         if (params.size() >= 3 && !params[2].isNull())
512             banTime = params[2].get_int64();
513 
514         bool absolute = false;
515         if (params.size() == 4 && params[3].isTrue())
516             absolute = true;
517 
518         isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
519     }
520     else if(strCommand == "remove")
521     {
522         if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
523             throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
524     }
525     return NullUniValue;
526 }
527 
listbanned(const UniValue & params,bool fHelp)528 UniValue listbanned(const UniValue& params, bool fHelp)
529 {
530     if (fHelp || params.size() != 0)
531         throw runtime_error(
532                             "listbanned\n"
533                             "\nList all banned IPs/Subnets.\n"
534                             "\nExamples:\n"
535                             + HelpExampleCli("listbanned", "")
536                             + HelpExampleRpc("listbanned", "")
537                             );
538 
539     banmap_t banMap;
540     CNode::GetBanned(banMap);
541 
542     UniValue bannedAddresses(UniValue::VARR);
543     for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
544     {
545         CBanEntry banEntry = (*it).second;
546         UniValue rec(UniValue::VOBJ);
547         rec.push_back(Pair("address", (*it).first.ToString()));
548         rec.push_back(Pair("banned_until", banEntry.nBanUntil));
549         rec.push_back(Pair("ban_created", banEntry.nCreateTime));
550         rec.push_back(Pair("ban_reason", banEntry.banReasonToString()));
551 
552         bannedAddresses.push_back(rec);
553     }
554 
555     return bannedAddresses;
556 }
557 
clearbanned(const UniValue & params,bool fHelp)558 UniValue clearbanned(const UniValue& params, bool fHelp)
559 {
560     if (fHelp || params.size() != 0)
561         throw runtime_error(
562                             "clearbanned\n"
563                             "\nClear all banned IPs.\n"
564                             "\nExamples:\n"
565                             + HelpExampleCli("clearbanned", "")
566                             + HelpExampleRpc("clearbanned", "")
567                             );
568 
569     CNode::ClearBanned();
570 
571     return NullUniValue;
572 }
573 
574 static const CRPCCommand commands[] =
575 { //  category              name                      actor (function)         okSafeMode
576   //  --------------------- ------------------------  -----------------------  ----------
577     { "network",            "getconnectioncount",     &getconnectioncount,     true  },
578     { "network",            "ping",                   &ping,                   true  },
579     { "network",            "getpeerinfo",            &getpeerinfo,            true  },
580     { "network",            "addnode",                &addnode,                true  },
581     { "network",            "disconnectnode",         &disconnectnode,         true  },
582     { "network",            "getaddednodeinfo",       &getaddednodeinfo,       true  },
583     { "network",            "getnettotals",           &getnettotals,           true  },
584     { "network",            "getnetworkinfo",         &getnetworkinfo,         true  },
585     { "network",            "setban",                 &setban,                 true  },
586     { "network",            "listbanned",             &listbanned,             true  },
587     { "network",            "clearbanned",            &clearbanned,            true  },
588 };
589 
RegisterNetRPCCommands(CRPCTable & tableRPC)590 void RegisterNetRPCCommands(CRPCTable &tableRPC)
591 {
592     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
593         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
594 }
595