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