diff options
Diffstat (limited to 'src/rpc/net.cpp')
-rw-r--r-- | src/rpc/net.cpp | 301 |
1 files changed, 181 insertions, 120 deletions
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 846d90cd0a..e8cdce623c 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1,23 +1,26 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <rpc/server.h> +#include <banman.h> #include <chainparams.h> #include <clientversion.h> #include <core_io.h> -#include <validation.h> #include <net.h> #include <net_processing.h> #include <netbase.h> #include <policy/policy.h> +#include <policy/settings.h> #include <rpc/protocol.h> +#include <rpc/util.h> #include <sync.h> #include <timedata.h> #include <ui_interface.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> +#include <util/system.h> +#include <validation.h> #include <version.h> #include <warnings.h> @@ -27,14 +30,17 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( - "getconnectioncount\n" - "\nReturns the number of connections to other nodes.\n" - "\nResult:\n" + RPCHelpMan{"getconnectioncount", + "\nReturns the number of connections to other nodes.\n", + {}, + RPCResult{ "n (numeric) The connection count\n" - "\nExamples:\n" - + HelpExampleCli("getconnectioncount", "") + }, + RPCExamples{ + HelpExampleCli("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", "") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -46,14 +52,17 @@ static UniValue ping(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( - "ping\n" - "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" - "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" - "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n" - "\nExamples:\n" - + HelpExampleCli("ping", "") + RPCHelpMan{"ping", + "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" + "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" + "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n", + {}, + RPCResults{}, + RPCExamples{ + HelpExampleCli("ping", "") + HelpExampleRpc("ping", "") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -69,9 +78,10 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( - "getpeerinfo\n" - "\nReturns data about each connected network node as a json array of objects.\n" - "\nResult:\n" + RPCHelpMan{"getpeerinfo", + "\nReturns data about each connected network node as a json array of objects.\n", + {}, + RPCResult{ "[\n" " {\n" " \"id\": n, (numeric) Peer index\n" @@ -104,20 +114,26 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) " \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n" " \"minfeefilter\": n, (numeric) The minimum fee rate for transactions this peer accepts\n" " \"bytessent_per_msg\": {\n" - " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n" + " \"msg\": n, (numeric) The total bytes sent aggregated by message type\n" + " When a message type is not listed in this json object, the bytes sent are 0.\n" + " Only known message types can appear as keys in the object.\n" " ...\n" " },\n" " \"bytesrecv_per_msg\": {\n" - " \"addr\": n, (numeric) The total bytes received aggregated by message type\n" + " \"msg\": n, (numeric) The total bytes received aggregated by message type\n" + " When a message type is not listed in this json object, the bytes received are 0.\n" + " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n" " ...\n" " }\n" " }\n" " ,...\n" "]\n" - "\nExamples:\n" - + HelpExampleCli("getpeerinfo", "") + }, + RPCExamples{ + HelpExampleCli("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", "") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -173,14 +189,14 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter)); UniValue sendPerMsgCmd(UniValue::VOBJ); - for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) { + for (const auto& i : stats.mapSendBytesPerMsgCmd) { if (i.second > 0) sendPerMsgCmd.pushKV(i.first, i.second); } obj.pushKV("bytessent_per_msg", sendPerMsgCmd); UniValue recvPerMsgCmd(UniValue::VOBJ); - for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) { + for (const auto& i : stats.mapRecvBytesPerMsgCmd) { if (i.second > 0) recvPerMsgCmd.pushKV(i.first, i.second); } @@ -200,18 +216,21 @@ static UniValue addnode(const JSONRPCRequest& request) if (request.fHelp || request.params.size() != 2 || (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) throw std::runtime_error( - "addnode \"node\" \"add|remove|onetry\"\n" - "\nAttempts to add or remove a node from the addnode list.\n" - "Or try a connection to a node once.\n" - "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n" - "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n" - "\nArguments:\n" - "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" - "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" - "\nExamples:\n" - + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") + RPCHelpMan{"addnode", + "\nAttempts to add or remove a node from the addnode list.\n" + "Or try a connection to a node once.\n" + "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n" + "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n", + { + {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"}, + {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'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"}, + }, + RPCResults{}, + RPCExamples{ + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -243,19 +262,22 @@ static UniValue disconnectnode(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3) throw std::runtime_error( - "disconnectnode \"[address]\" [nodeid]\n" - "\nImmediately disconnects from the specified peer node.\n" - "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" - "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n" - "\nArguments:\n" - "1. \"address\" (string, optional) The IP address/port of the node\n" - "2. \"nodeid\" (number, optional) The node ID (see getpeerinfo for node IDs)\n" - "\nExamples:\n" - + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"") + RPCHelpMan{"disconnectnode", + "\nImmediately disconnects from the specified peer node.\n" + "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" + "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n", + { + {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"}, + {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"}, + }, + RPCResults{}, + RPCExamples{ + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleCli("disconnectnode", "\"\" 1") + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleRpc("disconnectnode", "\"\", 1") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -286,12 +308,13 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( - "getaddednodeinfo ( \"node\" )\n" - "\nReturns information about the given added node, or all added nodes\n" - "(note that onetry addnodes are not listed here)\n" - "\nArguments:\n" - "1. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" - "\nResult:\n" + RPCHelpMan{"getaddednodeinfo", + "\nReturns information about the given added node, or all added nodes\n" + "(note that onetry addnodes are not listed here)\n", + { + {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."}, + }, + RPCResult{ "[\n" " {\n" " \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n" @@ -305,10 +328,12 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) " }\n" " ,...\n" "]\n" - "\nExamples:\n" - + HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + }, + RPCExamples{ + HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -353,10 +378,11 @@ static UniValue getnettotals(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 0) throw std::runtime_error( - "getnettotals\n" - "\nReturns information about network traffic, including bytes in, bytes out,\n" - "and current time.\n" - "\nResult:\n" + RPCHelpMan{"getnettotals", + "\nReturns information about network traffic, including bytes in, bytes out,\n" + "and current time.\n", + {}, + RPCResult{ "{\n" " \"totalbytesrecv\": n, (numeric) Total bytes received\n" " \"totalbytessent\": n, (numeric) Total bytes sent\n" @@ -371,10 +397,12 @@ static UniValue getnettotals(const JSONRPCRequest& request) " \"time_left_in_cycle\": t (numeric) Seconds left in current time cycle\n" " }\n" "}\n" - "\nExamples:\n" - + HelpExampleCli("getnettotals", "") + }, + RPCExamples{ + HelpExampleCli("getnettotals", "") + HelpExampleRpc("getnettotals", "") - ); + }, + }.ToString()); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -406,7 +434,7 @@ static UniValue GetNetworksInfo() UniValue obj(UniValue::VOBJ); GetProxy(network, proxy); obj.pushKV("name", GetNetworkName(network)); - obj.pushKV("limited", IsLimited(network)); + obj.pushKV("limited", !IsReachable(network)); obj.pushKV("reachable", IsReachable(network)); obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string()); obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials); @@ -419,9 +447,10 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( - "getnetworkinfo\n" - "Returns an object containing various state info regarding P2P networking.\n" - "\nResult:\n" + RPCHelpMan{"getnetworkinfo", + "Returns an object containing various state info regarding P2P networking.\n", + {}, + RPCResult{ "{\n" " \"version\": xxxxx, (numeric) the server version\n" " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n" @@ -453,10 +482,12 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) " ]\n" " \"warnings\": \"...\" (string) any network and blockchain warnings\n" "}\n" - "\nExamples:\n" - + HelpExampleCli("getnetworkinfo", "") + }, + RPCExamples{ + HelpExampleCli("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", "") - ); + }, + }.ToString()); LOCK(cs_main); UniValue obj(UniValue::VOBJ); @@ -493,26 +524,30 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) static UniValue setban(const JSONRPCRequest& request) { + const RPCHelpMan help{"setban", + "\nAttempts to add or remove an IP/Subnet from the banned list.\n", + { + {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"}, + {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list"}, + {"bantime", RPCArg::Type::NUM, /* default */ "0", "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)"}, + {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)"}, + }, + RPCResults{}, + RPCExamples{ + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") + }, + }; std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); - if (request.fHelp || request.params.size() < 2 || - (strCommand != "add" && strCommand != "remove")) - throw std::runtime_error( - "setban \"subnet\" \"add|remove\" (bantime) (absolute)\n" - "\nAttempts to add or remove an IP/Subnet from the banned list.\n" - "\nArguments:\n" - "1. \"subnet\" (string, required) The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)\n" - "2. \"command\" (string, required) 'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list\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 an 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\"") - + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") - ); - if(!g_connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) { + throw std::runtime_error(help.ToString()); + } + if (!g_banman) { + throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); + } CSubNet subNet; CNetAddr netAddr; @@ -534,8 +569,9 @@ static UniValue setban(const JSONRPCRequest& request) if (strCommand == "add") { - if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr)) + if (isSubnet ? g_banman->IsBanned(subNet) : g_banman->IsBanned(netAddr)) { throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); + } int64_t banTime = 0; //use standard bantime if not specified if (!request.params[2].isNull()) @@ -545,12 +581,23 @@ static UniValue setban(const JSONRPCRequest& request) if (request.params[3].isTrue()) absolute = true; - isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); + if (isSubnet) { + g_banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute); + if (g_connman) { + g_connman->DisconnectNode(subNet); + } + } else { + g_banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); + if (g_connman) { + g_connman->DisconnectNode(netAddr); + } + } } else if(strCommand == "remove") { - if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) )) + if (!( isSubnet ? g_banman->Unban(subNet) : g_banman->Unban(netAddr) )) { throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned."); + } } return NullUniValue; } @@ -559,18 +606,22 @@ static UniValue listbanned(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( - "listbanned\n" - "\nList all banned IPs/Subnets.\n" - "\nExamples:\n" - + HelpExampleCli("listbanned", "") + RPCHelpMan{"listbanned", + "\nList all banned IPs/Subnets.\n", + {}, + RPCResults{}, + RPCExamples{ + HelpExampleCli("listbanned", "") + HelpExampleRpc("listbanned", "") - ); + }, + }.ToString()); - if(!g_connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + if(!g_banman) { + throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); + } banmap_t banMap; - g_connman->GetBanned(banMap); + g_banman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); for (const auto& entry : banMap) @@ -592,16 +643,20 @@ static UniValue clearbanned(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( - "clearbanned\n" - "\nClear all banned IPs.\n" - "\nExamples:\n" - + HelpExampleCli("clearbanned", "") + RPCHelpMan{"clearbanned", + "\nClear all banned IPs.\n", + {}, + RPCResults{}, + RPCExamples{ + HelpExampleCli("clearbanned", "") + HelpExampleRpc("clearbanned", "") - ); - if(!g_connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + }, + }.ToString()); + if (!g_banman) { + throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); + } - g_connman->ClearBanned(); + g_banman->ClearBanned(); return NullUniValue; } @@ -610,10 +665,14 @@ static UniValue setnetworkactive(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) { throw std::runtime_error( - "setnetworkactive true|false\n" - "\nDisable/enable all p2p network activity.\n" - "\nArguments:\n" - "1. \"state\" (boolean, required) true to enable networking, false to disable\n" + RPCHelpMan{"setnetworkactive", + "\nDisable/enable all p2p network activity.\n", + { + {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"}, + }, + RPCResults{}, + RPCExamples{""}, + }.ToString() ); } @@ -630,12 +689,12 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) { throw std::runtime_error( - "getnodeaddresses ( count )\n" - "\nReturn known addresses which can potentially be used to find new nodes in the network\n" - "\nArguments:\n" - "1. \"count\" (numeric, optional) How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + - " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses. (default = 1)\n" - "\nResult:\n" + RPCHelpMan{"getnodeaddresses", + "\nReturn known addresses which can potentially be used to find new nodes in the network\n", + { + {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."}, + }, + RPCResult{ "[\n" " {\n" " \"time\": ttt, (numeric) Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen\n" @@ -645,10 +704,12 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request) " }\n" " ,....\n" "]\n" - "\nExamples:\n" - + HelpExampleCli("getnodeaddresses", "8") + }, + RPCExamples{ + HelpExampleCli("getnodeaddresses", "8") + HelpExampleRpc("getnodeaddresses", "8") - ); + }, + }.ToString()); } if (!g_connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); |