Line data Source code
1 : // Copyright (c) 2009-2015 The Bitcoin developers
2 : // Copyright (c) 2014-2015 The Dash developers
3 : // Copyright (c) 2015-2022 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : #include "rpc/server.h"
8 :
9 : #include "clientversion.h"
10 : #include "net.h"
11 : #include "netbase.h"
12 : #include "net_processing.h"
13 : #include "optional.h"
14 : #include "protocol.h"
15 : #include "sync.h"
16 : #include "timedata.h"
17 : #include "guiinterface.h"
18 : #include "util/system.h"
19 : #include "version.h"
20 : #include "validation.h"
21 : #include "warnings.h"
22 :
23 : #include <univalue.h>
24 :
25 :
26 3 : UniValue getconnectioncount(const JSONRPCRequest& request)
27 : {
28 3 : if (request.fHelp || request.params.size() != 0)
29 0 : throw std::runtime_error(
30 : "getconnectioncount\n"
31 : "\nReturns the number of connections to other nodes.\n"
32 :
33 : "\nbResult:\n"
34 : "n (numeric) The connection count\n"
35 :
36 0 : "\nExamples:\n" +
37 0 : HelpExampleCli("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", ""));
38 :
39 3 : if(!g_connman)
40 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
41 :
42 3 : return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
43 : }
44 :
45 1 : UniValue ping(const JSONRPCRequest& request)
46 : {
47 1 : if (request.fHelp || request.params.size() != 0)
48 0 : throw std::runtime_error(
49 : "ping\n"
50 : "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
51 : "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
52 : "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
53 :
54 0 : "\nExamples:\n" +
55 0 : HelpExampleCli("ping", "") + HelpExampleRpc("ping", ""));
56 :
57 1 : if(!g_connman)
58 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
59 :
60 : // Request that each node send a ping during next message processing pass
61 1 : g_connman->ForEachNode([](CNode* pnode) {
62 2 : pnode->fPingQueued = true;
63 2 : });
64 1 : return NullUniValue;
65 : }
66 :
67 16992 : UniValue getpeerinfo(const JSONRPCRequest& request)
68 : {
69 16992 : if (request.fHelp || request.params.size() != 0)
70 0 : throw std::runtime_error(
71 : "getpeerinfo\n"
72 : "\nReturns data about each connected network node as a json array of objects.\n"
73 :
74 : "\nbResult:\n"
75 : "[\n"
76 : " {\n"
77 : " \"id\": n, (numeric) Peer index\n"
78 : " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
79 : " \"addrlocal\":\"ip:port\", (string) local address\n"
80 : " \"mapped_as\":\"mapped_as\", (string) The AS in the BGP route to the peer used for diversifying\n"
81 : "peer selection (only available if the asmap config flag is set)\n"
82 : " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
83 : " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
84 : " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
85 : " \"bytessent\": n, (numeric) The total bytes sent\n"
86 : " \"bytesrecv\": n, (numeric) The total bytes received\n"
87 : " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
88 : " \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
89 : " \"pingtime\": n, (numeric) ping time\n"
90 : " \"pingwait\": n, (numeric) ping wait\n"
91 : " \"version\": v, (numeric) The peer version, such as 7001\n"
92 : " \"subver\": \"/Pivx Core:x.x.x.x/\", (string) The string version\n"
93 : " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
94 : " \"addnode\": true|false, (boolean) Whether connection was due to addnode and is using an addnode slot\n"
95 : " \"masternode\": true|false, (boolean) Whether the connection is only for masternode quorums related messages\n"
96 : " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
97 : " \"banscore\": n, (numeric) The ban score\n"
98 : " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
99 : " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
100 : " \"inflight\": [\n"
101 : " n, (numeric) The heights of blocks we're currently asking from this peer\n"
102 : " ...\n"
103 : " ]\n"
104 : " \"addr_processed\": n, (numeric) The total number of addresses processed, excluding those dropped due to rate limiting\n"
105 : " \"addr_rate_limited\": n, (numeric) The total number of addresses dropped due to rate limiting\n"
106 : " \"bytessent_per_msg\": {\n"
107 : " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n"
108 : " ...\n"
109 : " }\n"
110 : " \"bytesrecv_per_msg\": {\n"
111 : " \"addr\": n, (numeric) The total bytes received aggregated by message type\n"
112 : " ...\n"
113 : " }\n"
114 : " \"masternode_iqr_conn\": true|false, (boolean) Whether the connection is an intra-quorum relay connection or not\n"
115 : " \"verif_mn_proreg_tx_hash\": \"hex\", (string) The MN provider register tx hash (if the connection is verified)\n"
116 : " \"verif_mn_operator_pubkey_hash\": \"hex\", (string) The MN operator pubkey hash (if the connection is verified)\n"
117 : " }\n"
118 : " ,...\n"
119 : "]\n"
120 :
121 0 : "\nExamples:\n" +
122 0 : HelpExampleCli("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", ""));
123 :
124 16992 : if(!g_connman)
125 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
126 :
127 16992 : std::vector<CNodeStats> vstats;
128 16992 : g_connman->GetNodeStats(vstats);
129 :
130 16992 : UniValue ret(UniValue::VARR);
131 :
132 78365 : for (const CNodeStats& stats : vstats) {
133 61373 : UniValue obj(UniValue::VOBJ);
134 122746 : CNodeStateStats statestats;
135 61373 : bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
136 61373 : obj.pushKV("id", stats.nodeid);
137 122746 : obj.pushKV("addr", stats.addrName);
138 61373 : if (!(stats.addrLocal.empty()))
139 172 : obj.pushKV("addrlocal", stats.addrLocal);
140 61373 : if (stats.m_mapped_as != 0) {
141 0 : obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
142 : }
143 122746 : obj.pushKV("services", strprintf("%016x", stats.nServices));
144 61373 : obj.pushKV("lastsend", stats.nLastSend);
145 61373 : obj.pushKV("lastrecv", stats.nLastRecv);
146 61373 : obj.pushKV("bytessent", stats.nSendBytes);
147 61373 : obj.pushKV("bytesrecv", stats.nRecvBytes);
148 61373 : obj.pushKV("conntime", stats.nTimeConnected);
149 61373 : obj.pushKV("timeoffset", stats.nTimeOffset);
150 61373 : obj.pushKV("pingtime", stats.dPingTime);
151 61373 : if (stats.dPingWait > 0.0)
152 1620 : obj.pushKV("pingwait", stats.dPingWait);
153 61373 : obj.pushKV("version", stats.nVersion);
154 : // Use the sanitized form of subver here, to avoid tricksy remote peers from
155 : // corrupting or modifying the JSON output by putting special characters in
156 : // their ver message.
157 61373 : obj.pushKV("subver", stats.cleanSubVer);
158 61373 : obj.pushKV("inbound", stats.fInbound);
159 61373 : obj.pushKV("addnode", stats.fAddnode);
160 61373 : obj.pushKV("masternode", stats.m_masternode_connection);
161 61373 : obj.pushKV("startingheight", stats.nStartingHeight);
162 61373 : if (fStateStats) {
163 61373 : obj.pushKV("banscore", statestats.nMisbehavior);
164 61373 : obj.pushKV("synced_headers", statestats.nSyncHeight);
165 61373 : obj.pushKV("synced_blocks", statestats.nCommonHeight);
166 61373 : UniValue heights(UniValue::VARR);
167 61373 : for (int height : statestats.vHeightInFlight) {
168 0 : heights.push_back(height);
169 : }
170 61373 : obj.pushKV("inflight", heights);
171 61373 : obj.pushKV("addr_processed", statestats.m_addr_processed);
172 122746 : obj.pushKV("addr_rate_limited", statestats.m_addr_rate_limited);
173 : }
174 61373 : obj.pushKV("whitelisted", stats.fWhitelisted);
175 :
176 122746 : UniValue sendPerMsgCmd(UniValue::VOBJ);
177 920689 : for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) {
178 859316 : if (i.second > 0)
179 859316 : sendPerMsgCmd.pushKV(i.first, i.second);
180 : }
181 61373 : obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
182 :
183 122746 : UniValue recvPerMsgCmd(UniValue::VOBJ);
184 3621010 : for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) {
185 3559630 : if (i.second > 0)
186 855932 : recvPerMsgCmd.pushKV(i.first, i.second);
187 : }
188 61373 : obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
189 :
190 : // DMN data
191 61373 : if (stats.m_masternode_connection) {
192 2600 : obj.pushKV("masternode_iqr_conn", stats.m_masternode_iqr_connection);
193 5200 : obj.pushKV("verif_mn_proreg_tx_hash", stats.verifiedProRegTxHash.GetHex());
194 7800 : obj.pushKV("verif_mn_operator_pubkey_hash", stats.verifiedPubKeyHash.GetHex());
195 : }
196 :
197 61373 : ret.push_back(obj);
198 : }
199 :
200 16992 : return ret;
201 : }
202 :
203 604 : UniValue addnode(const JSONRPCRequest& request)
204 : {
205 1208 : std::string strCommand;
206 604 : if (request.params.size() == 2)
207 604 : strCommand = request.params[1].get_str();
208 604 : if (request.fHelp || request.params.size() != 2 ||
209 605 : (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
210 0 : throw std::runtime_error(
211 : "addnode \"node\" \"add|remove|onetry\"\n"
212 : "\nAttempts add or remove a node from the addnode list.\n"
213 : "Or try a connection to a node once.\n"
214 :
215 : "\nArguments:\n"
216 : "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
217 : "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"
218 :
219 0 : "\nExamples:\n" +
220 0 : HelpExampleCli("addnode", "\"192.168.0.6:51472\" \"onetry\"") + HelpExampleRpc("addnode", "\"192.168.0.6:51472\", \"onetry\""));
221 :
222 604 : if(!g_connman)
223 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
224 :
225 1208 : std::string strNode = request.params[0].get_str();
226 :
227 604 : if (strCommand == "onetry") {
228 1206 : CAddress addr;
229 603 : g_connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str());
230 603 : return NullUniValue;
231 : }
232 :
233 1 : if (strCommand == "add") {
234 1 : if(!g_connman->AddNode(strNode))
235 0 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
236 0 : } else if (strCommand == "remove") {
237 0 : if(!g_connman->RemoveAddedNode(strNode))
238 0 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
239 : }
240 :
241 1 : return NullUniValue;
242 : }
243 :
244 25 : UniValue disconnectnode(const JSONRPCRequest& request)
245 : {
246 25 : if (request.fHelp || request.params.size() != 1)
247 0 : throw std::runtime_error(
248 : "disconnectnode \"node\" \n"
249 : "\nImmediately disconnects from the specified node.\n"
250 :
251 : "\nArguments:\n"
252 : "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
253 :
254 : "\nExamples:\n"
255 0 : + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
256 0 : + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
257 0 : );
258 :
259 25 : if(!g_connman)
260 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
261 :
262 25 : bool ret = g_connman->DisconnectNode(request.params[0].get_str());
263 25 : if (!ret)
264 2 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
265 :
266 24 : return NullUniValue;
267 : }
268 :
269 3 : UniValue getaddednodeinfo(const JSONRPCRequest& request)
270 : {
271 3 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
272 0 : throw std::runtime_error(
273 : "getaddednodeinfo dummy ( \"node\" )\n"
274 : "\nReturns information about the given added node, or all added nodes\n"
275 : "(note that onetry addnodes are not listed here)\n"
276 :
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 :
281 : "\nResult:\n"
282 : "[\n"
283 : " {\n"
284 : " \"addednode\" : \"192.168.0.201\", (string) The node ip address or name (as provided to addnode)\n"
285 : " \"connected\" : true|false, (boolean) If connected\n"
286 : " \"addresses\" : [ (list of objects) Only when connected = true\n"
287 : " {\n"
288 : " \"address\" : \"192.168.0.201:51472\", (string) The pivx server IP and port we're connected to\n"
289 : " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
290 : " }\n"
291 : " ]\n"
292 : " }\n"
293 : " ,...\n"
294 : "]\n"
295 :
296 0 : "\nExamples:\n" +
297 0 : HelpExampleCli("getaddednodeinfo", "true") + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\""));
298 :
299 3 : if(!g_connman)
300 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
301 :
302 4 : std::vector<AddedNodeInfo> vInfo = g_connman->GetAddedNodeInfo();
303 :
304 3 : if (request.params.size() == 2) {
305 2 : bool found = false;
306 3 : for (const AddedNodeInfo& info : vInfo) {
307 2 : if (info.strAddedNode == request.params[1].get_str()) {
308 1 : vInfo.assign(1, info);
309 : found = true;
310 : break;
311 : }
312 : }
313 1 : if (!found) {
314 2 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
315 : }
316 : }
317 :
318 2 : UniValue ret(UniValue::VARR);
319 :
320 3 : for (const AddedNodeInfo& info : vInfo) {
321 2 : UniValue obj(UniValue::VOBJ);
322 1 : obj.pushKV("addednode", info.strAddedNode);
323 1 : obj.pushKV("connected", info.fConnected);
324 2 : UniValue addresses(UniValue::VARR);
325 1 : if (info.fConnected) {
326 0 : UniValue address(UniValue::VOBJ);
327 0 : address.pushKV("address", info.resolvedAddress.ToString());
328 0 : address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
329 0 : addresses.push_back(address);
330 : }
331 1 : obj.pushKV("addresses", addresses);
332 1 : ret.push_back(obj);
333 : }
334 :
335 2 : return ret;
336 : }
337 :
338 5 : UniValue getnettotals(const JSONRPCRequest& request)
339 : {
340 5 : if (request.fHelp || request.params.size() > 0)
341 0 : throw std::runtime_error(
342 : "getnettotals\n"
343 : "\nReturns information about network traffic, including bytes in, bytes out,\n"
344 : "and current time.\n"
345 :
346 : "\nResult:\n"
347 : "{\n"
348 : " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
349 : " \"totalbytessent\": n, (numeric) Total bytes sent\n"
350 : " \"timemillis\": t (numeric) Total cpu time\n"
351 : "}\n"
352 :
353 0 : "\nExamples:\n" +
354 0 : HelpExampleCli("getnettotals", "") + HelpExampleRpc("getnettotals", ""));
355 :
356 5 : if(!g_connman)
357 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
358 :
359 5 : UniValue obj(UniValue::VOBJ);
360 5 : obj.pushKV("totalbytesrecv", g_connman->GetTotalBytesRecv());
361 5 : obj.pushKV("totalbytessent", g_connman->GetTotalBytesSent());
362 5 : obj.pushKV("timemillis", GetTimeMillis());
363 5 : return obj;
364 : }
365 :
366 1222 : static UniValue GetNetworksInfo()
367 : {
368 1222 : UniValue networks(UniValue::VARR);
369 9776 : for (int n = 0; n < NET_MAX; ++n) {
370 8554 : enum Network network = static_cast<enum Network>(n);
371 8554 : if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue;
372 7332 : proxyType proxy;
373 7332 : UniValue obj(UniValue::VOBJ);
374 3666 : GetProxy(network, proxy);
375 7332 : obj.pushKV("name", GetNetworkName(network));
376 3666 : obj.pushKV("limited", !IsReachable(network));
377 3666 : obj.pushKV("reachable", IsReachable(network));
378 10968 : obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
379 3666 : obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
380 3666 : networks.push_back(obj);
381 : }
382 1222 : return networks;
383 : }
384 :
385 1222 : UniValue getnetworkinfo(const JSONRPCRequest& request)
386 : {
387 1222 : if (request.fHelp || request.params.size() != 0)
388 0 : throw std::runtime_error(
389 : "getnetworkinfo\n"
390 : "\nReturns an object containing various state info regarding P2P networking.\n"
391 :
392 : "\nResult:\n"
393 : "{\n"
394 : " \"version\": xxxxx, (numeric) the server version\n"
395 : " \"subversion\": \"/Pivx Core:x.x.x.x/\", (string) the server subversion string\n"
396 : " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
397 : " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
398 : " \"timeoffset\": xxxxx, (numeric) the time offset\n"
399 : " \"connections\": xxxxx, (numeric) the number of connections\n"
400 : " \"networkactive\": true|false, (boolean) the network activity status\n"
401 : " \"networks\": [ (array) information per network\n"
402 : " {\n"
403 : " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
404 : " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
405 : " \"reachable\": true|false, (boolean) is the network reachable?\n"
406 : " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
407 : " }\n"
408 : " ,...\n"
409 : " ],\n"
410 0 : " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
411 0 : " \"incrementalfee\": x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n"
412 : " \"localaddresses\": [ (array) list of local addresses\n"
413 : " {\n"
414 : " \"address\": \"xxxx\", (string) network address\n"
415 : " \"port\": xxx, (numeric) network port\n"
416 : " \"score\": xxx (numeric) relative score\n"
417 : " }\n"
418 : " ,...\n"
419 : " ]\n"
420 : " \"warnings\": \"...\" (string) any network and blockchain warnings\n"
421 : "}\n"
422 :
423 0 : "\nExamples:\n" +
424 0 : HelpExampleCli("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", ""));
425 :
426 1222 : LOCK(cs_main);
427 1222 : UniValue obj(UniValue::VOBJ);
428 1222 : obj.pushKV("version", CLIENT_VERSION);
429 1222 : obj.pushKV("subversion", strSubVersion);
430 1222 : obj.pushKV("protocolversion", PROTOCOL_VERSION);
431 1222 : if (g_connman)
432 3666 : obj.pushKV("localservices", strprintf("%016x", g_connman->GetLocalServices()));
433 1222 : obj.pushKV("timeoffset", GetTimeOffset());
434 1222 : if (g_connman) {
435 1222 : obj.pushKV("networkactive", g_connman->GetNetworkActive());
436 2444 : obj.pushKV("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
437 : }
438 2444 : obj.pushKV("networks", GetNetworksInfo());
439 2444 : obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
440 2444 : UniValue localAddresses(UniValue::VARR);
441 1222 : {
442 1222 : LOCK(cs_mapLocalHost);
443 1222 : for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost) {
444 0 : UniValue rec(UniValue::VOBJ);
445 0 : rec.pushKV("address", item.first.ToString());
446 0 : rec.pushKV("port", item.second.nPort);
447 0 : rec.pushKV("score", item.second.nScore);
448 0 : localAddresses.push_back(rec);
449 : }
450 : }
451 1222 : obj.pushKV("localaddresses", localAddresses);
452 3666 : obj.pushKV("warnings", GetWarnings("statusbar"));
453 2444 : return obj;
454 : }
455 :
456 23 : UniValue setban(const JSONRPCRequest& request)
457 : {
458 23 : std::string strCommand;
459 23 : if (request.params.size() >= 2)
460 22 : strCommand = request.params[1].get_str();
461 23 : if (request.fHelp || request.params.size() < 2 ||
462 26 : (strCommand != "add" && strCommand != "remove"))
463 1 : throw std::runtime_error(
464 : "setban \"subnet\" \"add|remove\" ( bantime absolute )\n"
465 : "\nAttempts add or remove a IP/Subnet from the banned list.\n"
466 :
467 : "\nArguments:\n"
468 : "1. \"subnet\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n"
469 : "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n"
470 : "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"
471 : "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
472 :
473 : "\nExamples:\n"
474 3 : + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
475 5 : + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
476 5 : + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400"));
477 :
478 22 : if (!g_connman)
479 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
480 :
481 44 : CSubNet subNet;
482 44 : CNetAddr netAddr;
483 22 : bool isSubnet = false;
484 :
485 22 : if (request.params[0].get_str().find('/') != std::string::npos)
486 12 : isSubnet = true;
487 :
488 22 : if (!isSubnet) {
489 20 : CNetAddr resolved;
490 10 : LookupHost(request.params[0].get_str(), resolved, false);
491 10 : netAddr = resolved;
492 : } else
493 12 : LookupSubNet(request.params[0].get_str(), subNet);
494 :
495 22 : if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
496 4 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
497 :
498 20 : if (strCommand == "add")
499 : {
500 38 : if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr))
501 6 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
502 :
503 13 : int64_t banTime = 0; //use standard bantime if not specified
504 13 : if (request.params.size() >= 3 && !request.params[2].isNull())
505 4 : banTime = request.params[2].get_int64();
506 :
507 13 : bool absolute = false;
508 13 : if (request.params.size() == 4)
509 1 : absolute = request.params[3].get_bool();
510 :
511 13 : isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
512 : }
513 4 : else if(strCommand == "remove")
514 : {
515 4 : if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) ))
516 2 : throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
517 : }
518 32 : return NullUniValue;
519 : }
520 :
521 19 : UniValue listbanned(const JSONRPCRequest& request)
522 : {
523 19 : if (request.fHelp || request.params.size() != 0)
524 0 : throw std::runtime_error(
525 : "listbanned\n"
526 : "\nList all banned IPs/Subnets.\n"
527 :
528 : "\nResult:\n"
529 : "[\n"
530 : " {\n"
531 : " \"address\": \"xxx\", (string) Network address of banned client.\n"
532 : " \"banned_until\": nnn, (numeric) Timestamp when the ban is lifted.\n"
533 : " \"ban_created\": nnn, (numeric) Timestamp when the ban was created.\n"
534 : " \"ban_reason\": \"xxx\" (string) Reason for banning.\n"
535 : " }\n"
536 : " ,...\n"
537 : "]\n"
538 :
539 : "\nExamples:\n"
540 0 : + HelpExampleCli("listbanned", "")
541 0 : + HelpExampleRpc("listbanned", ""));
542 :
543 19 : if (!g_connman)
544 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
545 :
546 19 : banmap_t banMap;
547 19 : g_connman->GetBanned(banMap);
548 :
549 19 : UniValue bannedAddresses(UniValue::VARR);
550 39 : for (const auto& entry : banMap)
551 : {
552 20 : const CBanEntry& banEntry = entry.second;
553 40 : UniValue rec(UniValue::VOBJ);
554 40 : rec.pushKV("address", entry.first.ToString());
555 20 : rec.pushKV("banned_until", banEntry.nBanUntil);
556 20 : rec.pushKV("ban_created", banEntry.nCreateTime);
557 40 : rec.pushKV("ban_reason", banEntry.banReasonToString());
558 :
559 20 : bannedAddresses.push_back(rec);
560 : }
561 :
562 19 : return bannedAddresses;
563 : }
564 :
565 8 : UniValue clearbanned(const JSONRPCRequest& request)
566 : {
567 8 : if (request.fHelp || request.params.size() != 0)
568 0 : throw std::runtime_error(
569 : "clearbanned\n"
570 : "\nClear all banned IPs.\n"
571 :
572 : "\nExamples:\n"
573 0 : + HelpExampleCli("clearbanned", "")
574 0 : + HelpExampleRpc("clearbanned", ""));
575 :
576 8 : if (!g_connman)
577 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
578 :
579 8 : g_connman->ClearBanned();
580 :
581 8 : return NullUniValue;
582 : }
583 :
584 8 : static UniValue getnodeaddresses(const JSONRPCRequest& request)
585 : {
586 8 : if (request.fHelp || request.params.size() > 2) {
587 0 : throw std::runtime_error(
588 : "getnodeaddresses ( count \"network\" )\n"
589 : "\nReturn known addresses which can potentially be used to find new nodes in the network\n"
590 :
591 : "\nArguments:\n"
592 : "1. count (numeric, optional) The maximum number of addresses to return. Specify 0 to return all known addresses.\n"
593 : "2. \"network\" (string, optional) Return only addresses of the specified network. Can be one of: ipv4, ipv6, onion."
594 :
595 : "\nResult:\n"
596 : "[\n"
597 : " {\n"
598 : " \"time\": ttt, (numeric) Timestamp in seconds since epoch (Jan 1 1970 GMT) when the node was last seen\n"
599 : " \"services\": n, (numeric) The services offered by the node\n"
600 : " \"address\": \"host\", (string) The address of the node\n"
601 : " \"port\": n, (numeric) The port number of the node\n"
602 : " \"network\": \"xxxx\" (string) The network (ipv4, ipv6, onion) the node connected through\n"
603 : " }\n"
604 : " ,...\n"
605 : "]\n"
606 :
607 : "\nExamples:\n"
608 0 : + HelpExampleCli("getnodeaddresses", "8")
609 0 : + HelpExampleCli("getnodeaddresses", "4 \"ipv4\"")
610 0 : + HelpExampleRpc("getnodeaddresses", "8")
611 0 : + HelpExampleRpc("getnodeaddresses", "4 \"ipv4\"")
612 0 : );
613 : }
614 8 : if (!g_connman) {
615 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
616 : }
617 :
618 8 : const int count{request.params[0].isNull() ? 1 : request.params[0].get_int()};
619 8 : if (count < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
620 :
621 12 : const Optional<Network> network{request.params[1].isNull() ? nullopt : Optional<Network>{ParseNetwork(request.params[1].get_str())}};
622 7 : if (network == NET_UNROUTABLE) {
623 2 : throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Network not recognized: %s", request.params[1].get_str()));
624 : }
625 :
626 : // returns a shuffled list of CAddress
627 6 : const std::vector<CAddress> vAddr{g_connman->GetAddresses(count, /* max_pct */ 0, network)};
628 6 : UniValue ret(UniValue::VARR);
629 :
630 8858 : for (const CAddress& addr : vAddr) {
631 17704 : UniValue obj(UniValue::VOBJ);
632 8852 : obj.pushKV("time", (int)addr.nTime);
633 8852 : obj.pushKV("services", (uint64_t)addr.nServices);
634 17704 : obj.pushKV("address", addr.ToStringIP());
635 8852 : obj.pushKV("port", addr.GetPort());
636 17704 : obj.pushKV("network", GetNetworkName(addr.GetNetClass()));
637 8852 : ret.push_back(obj);
638 : }
639 6 : return ret;
640 : }
641 :
642 10001 : static UniValue addpeeraddress(const JSONRPCRequest& request)
643 : {
644 10001 : if (request.fHelp || request.params.size() != 2) {
645 0 : throw std::runtime_error(
646 : "addpeeraddress \"address\" port\n"
647 : "\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n"
648 :
649 : "\nArguments\n"
650 : "1. \"address\" (string, required) The IP address of the peer\n"
651 : "2. port (numeric, required) The port of the peer\n"
652 :
653 : "\nResult:\n"
654 : "{\n"
655 : " \"success\": true|false (boolean) Whether the peer address was successfully added to the address manager\n"
656 : "}\n"
657 :
658 : "\nExamples:\n"
659 0 : + HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 51472")
660 0 : + HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 51472"));
661 : }
662 10001 : if (!g_connman) {
663 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
664 : }
665 :
666 10001 : UniValue obj(UniValue::VOBJ);
667 :
668 20002 : std::string addr_string = request.params[0].get_str();
669 10001 : uint16_t port = request.params[1].get_int();
670 :
671 20002 : CNetAddr net_addr;
672 10001 : if (!LookupHost(addr_string, net_addr, false)) {
673 0 : obj.pushKV("success", false);
674 0 : return obj;
675 : }
676 30003 : CAddress address = CAddress({net_addr, port}, ServiceFlags(NODE_NETWORK));
677 10001 : address.nTime = GetAdjustedTime();
678 : // The source address is set equal to the address. This is equivalent to the peer
679 : // announcing itself.
680 20002 : if (!g_connman->AddNewAddresses({address}, address)) {
681 512 : obj.pushKV("success", false);
682 512 : return obj;
683 : }
684 :
685 9489 : obj.pushKV("success", true);
686 9489 : return obj;
687 : }
688 :
689 19 : UniValue setnetworkactive(const JSONRPCRequest& request)
690 : {
691 19 : if (request.fHelp || request.params.size() != 1) {
692 0 : throw std::runtime_error(
693 : "setnetworkactive \"true|false\"\n"
694 : "Disable/enable all p2p network activity.\n"
695 :
696 : "\nResult:\n"
697 : "status (boolean) The final network activity status\n"
698 0 : "\nExamples:\n" +
699 0 : HelpExampleCli("setnetworkactive", "true") + HelpExampleRpc("setnetworkactive", "true"));
700 : }
701 19 : if (!g_connman) {
702 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
703 : }
704 19 : g_connman->SetNetworkActive(request.params[0].get_bool());
705 19 : return g_connman->GetNetworkActive();
706 : }
707 :
708 : // clang-format off
709 : static const CRPCCommand commands[] =
710 : { // category name actor (function) okSafe argNames
711 : // --------------------- ------------------------ ----------------------- ------ --------
712 : { "network", "addnode", &addnode, true, {"node","command"} },
713 : { "network", "clearbanned", &clearbanned, true, {} },
714 : { "network", "disconnectnode", &disconnectnode, true, {"node"} },
715 : { "network", "getaddednodeinfo", &getaddednodeinfo, true, {"dummy","node"} },
716 : { "network", "getconnectioncount", &getconnectioncount, true, {} },
717 : { "network", "getnettotals", &getnettotals, true, {} },
718 : { "network", "getnetworkinfo", &getnetworkinfo, true, {} },
719 : { "network", "getnodeaddresses", &getnodeaddresses, true, {"count"} },
720 : { "network", "getpeerinfo", &getpeerinfo, true, {} },
721 : { "network", "listbanned", &listbanned, true, {} },
722 : { "network", "ping", &ping, true, {} },
723 : { "network", "setban", &setban, true, {"subnet", "command", "bantime", "absolute"} },
724 : { "network", "setnetworkactive", &setnetworkactive, true, {"active"} },
725 :
726 : /** Not shown in help */
727 : { "hidden", "addpeeraddress", &addpeeraddress, true, {"address", "port"} },
728 : };
729 : // clang-format on
730 :
731 494 : void RegisterNetRPCCommands(CRPCTable &tableRPC)
732 : {
733 7410 : for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
734 6916 : tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
735 494 : }
|