diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 152 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.h | 5 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 61 | ||||
-rw-r--r-- | src/rpc/daemon_handler.cpp | 5 | ||||
-rw-r--r-- | src/rpc/rpc_args.cpp | 37 | ||||
-rw-r--r-- | src/rpc/rpc_args.h | 6 |
7 files changed, 234 insertions, 34 deletions
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index cffe8e1eb..06577d37e 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -47,7 +47,7 @@ set(rpc_base_headers rpc_args.h) set(rpc_headers - rpc_handler.cpp) + rpc_handler.h) set(daemon_rpc_server_headers) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d80219f1c..9aaaa026d 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -142,6 +142,7 @@ namespace cryptonote { m_restricted = restricted; m_net_server.set_threads_prefix("RPC"); + m_net_server.set_connection_filter(&m_p2p); auto rpc_config = cryptonote::rpc_args::process(vm, true); if (!rpc_config) @@ -161,7 +162,9 @@ namespace cryptonote auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); }; return epee::http_server_impl_base<core_rpc_server, connection_context>::init( - rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options) + rng, std::move(port), std::move(rpc_config->bind_ip), + std::move(rpc_config->bind_ipv6_address), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4), + std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options) ); } //------------------------------------------------------------------------------------------------------------------------------ @@ -173,6 +176,24 @@ namespace cryptonote } return true; } + //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::add_host_fail(const connection_context *ctx) + { + if(!ctx || !ctx->m_remote_address.is_blockable()) + return false; + + CRITICAL_REGION_LOCAL(m_host_fails_score_lock); + uint64_t fails = ++m_host_fails_score[ctx->m_remote_address.host_str()]; + MDEBUG("Host " << ctx->m_remote_address.host_str() << " fail score=" << fails); + if(fails > RPC_IP_FAILS_BEFORE_BLOCK) + { + auto it = m_host_fails_score.find(ctx->m_remote_address.host_str()); + CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error"); + it->second = RPC_IP_FAILS_BEFORE_BLOCK/2; + m_p2p.block_host(ctx->m_remote_address); + } + return true; + } #define CHECK_CORE_READY() do { if(!check_core_ready()){res.status = CORE_RPC_STATUS_BUSY;return true;} } while(0) //------------------------------------------------------------------------------------------------------------------------------ @@ -300,6 +321,7 @@ namespace cryptonote if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, !req.no_miner_tx, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) { res.status = "Failed"; + add_host_fail(ctx); return false; } @@ -423,6 +445,7 @@ namespace cryptonote if(!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, res.m_block_ids, res.start_height, res.current_height, false)) { res.status = "Failed"; + add_host_fail(ctx); return false; } @@ -603,7 +626,8 @@ namespace cryptonote return true; } const cryptonote::blobdata pruned = ss.str(); - sorted_txs.push_back(std::make_tuple(h, pruned, get_transaction_prunable_hash(tx), std::string(i->tx_blob, pruned.size()))); + const crypto::hash prunable_hash = tx.version == 1 ? crypto::null_hash : get_transaction_prunable_hash(tx); + sorted_txs.push_back(std::make_tuple(h, pruned, prunable_hash, std::string(i->tx_blob, pruned.size()))); missed_txs.erase(std::find(missed_txs.begin(), missed_txs.end(), h)); pool_tx_hashes.insert(h); const std::string hash_string = epee::string_tools::pod_to_hex(h); @@ -862,6 +886,8 @@ namespace cryptonote add_reason(reason, "fee too low"); if ((res.not_rct = tvc.m_not_rct)) add_reason(reason, "tx is not ringct"); + if ((res.too_few_outputs = tvc.m_too_few_outputs)) + add_reason(reason, "too few outputs"); const std::string punctuation = reason.empty() ? "" : ": "; if (tvc.m_verifivation_failed) { @@ -1026,6 +1052,11 @@ namespace cryptonote if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id()) res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(), entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); + else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id()) + { + res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(), + entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); + } else res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port); } @@ -1036,6 +1067,9 @@ namespace cryptonote if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id()) res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(), entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); + else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id()) + res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(), + entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); else res.gray_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port); } @@ -1044,6 +1078,45 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_get_public_nodes(const COMMAND_RPC_GET_PUBLIC_NODES::request& req, COMMAND_RPC_GET_PUBLIC_NODES::response& res, const connection_context *ctx) + { + PERF_TIMER(on_get_public_nodes); + + COMMAND_RPC_GET_PEER_LIST::response peer_list_res; + const bool success = on_get_peer_list(COMMAND_RPC_GET_PEER_LIST::request(), peer_list_res, ctx); + res.status = peer_list_res.status; + if (!success) + { + return false; + } + if (res.status != CORE_RPC_STATUS_OK) + { + return true; + } + + const auto collect = [](const std::vector<peer> &peer_list, std::vector<public_node> &public_nodes) + { + for (const auto &entry : peer_list) + { + if (entry.rpc_port != 0) + { + public_nodes.emplace_back(entry); + } + } + }; + + if (req.white) + { + collect(peer_list_res.white_list, res.white); + } + if (req.gray) + { + collect(peer_list_res.gray_list, res.gray); + } + + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_set_log_hash_rate(const COMMAND_RPC_SET_LOG_HASH_RATE::request& req, COMMAND_RPC_SET_LOG_HASH_RATE::response& res, const connection_context *ctx) { PERF_TIMER(on_set_log_hash_rate); @@ -1600,38 +1673,55 @@ namespace cryptonote if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH>(invoke_http_mode::JON_RPC, "getblockheaderbyhash", req, res, r)) return r; - crypto::hash block_hash; - bool hash_parsed = parse_hash256(req.hash, block_hash); - if(!hash_parsed) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; - error_resp.message = "Failed to parse hex representation of block hash. Hex = " + req.hash + '.'; - return false; - } - block blk; - bool orphan = false; - bool have_block = m_core.get_block_by_hash(block_hash, blk, &orphan); - if (!have_block) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.'; - return false; - } - if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen)) + auto get = [this](const std::string &hash, bool fill_pow_hash, block_header_response &block_header, bool restricted, epee::json_rpc::error& error_resp) -> bool { + crypto::hash block_hash; + bool hash_parsed = parse_hash256(hash, block_hash); + if(!hash_parsed) + { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Failed to parse hex representation of block hash. Hex = " + hash + '.'; + return false; + } + block blk; + bool orphan = false; + bool have_block = m_core.get_block_by_hash(block_hash, blk, &orphan); + if (!have_block) + { + error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; + error_resp.message = "Internal error: can't get block by hash. Hash = " + hash + '.'; + return false; + } + if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen)) + { + error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; + error_resp.message = "Internal error: coinbase transaction in the block has the wrong type"; + return false; + } + uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height; + bool response_filled = fill_block_header_response(blk, orphan, block_height, block_hash, block_header, fill_pow_hash && !restricted); + if (!response_filled) + { + error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; + error_resp.message = "Internal error: can't produce valid response."; + return false; + } + return true; + }; + + const bool restricted = m_restricted && ctx; + if (!req.hash.empty()) { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: coinbase transaction in the block has the wrong type"; - return false; + if (!get(req.hash, req.fill_pow_hash, res.block_header, restricted, error_resp)) + return false; } - uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height; - const bool restricted = m_restricted && ctx; - bool response_filled = fill_block_header_response(blk, orphan, block_height, block_hash, res.block_header, req.fill_pow_hash && !restricted); - if (!response_filled) + res.block_headers.reserve(req.hashes.size()); + for (const std::string &hash: req.hashes) { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't produce valid response."; - return false; + res.block_headers.push_back({}); + if (!get(hash, req.fill_pow_hash, res.block_headers.back(), restricted, error_resp)) + return false; } + res.status = CORE_RPC_STATUS_OK; return true; } @@ -2061,7 +2151,7 @@ namespace cryptonote PERF_TIMER(on_get_alternate_chains); try { - std::list<std::pair<Blockchain::block_extended_info, std::vector<crypto::hash>>> chains = m_core.get_blockchain_storage().get_alternative_chains(); + std::vector<std::pair<Blockchain::block_extended_info, std::vector<crypto::hash>>> chains = m_core.get_blockchain_storage().get_alternative_chains(); for (const auto &i: chains) { difficulty_type wdiff = i.first.cumulative_difficulty; diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 663975617..e91d4c953 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -108,6 +108,7 @@ namespace cryptonote MAP_URI_AUTO_JON2_IF("/mining_status", on_mining_status, COMMAND_RPC_MINING_STATUS, !m_restricted) MAP_URI_AUTO_JON2_IF("/save_bc", on_save_bc, COMMAND_RPC_SAVE_BC, !m_restricted) MAP_URI_AUTO_JON2_IF("/get_peer_list", on_get_peer_list, COMMAND_RPC_GET_PEER_LIST, !m_restricted) + MAP_URI_AUTO_JON2_IF("/get_public_nodes", on_get_public_nodes, COMMAND_RPC_GET_PUBLIC_NODES, !m_restricted) MAP_URI_AUTO_JON2_IF("/set_log_hash_rate", on_set_log_hash_rate, COMMAND_RPC_SET_LOG_HASH_RATE, !m_restricted) MAP_URI_AUTO_JON2_IF("/set_log_level", on_set_log_level, COMMAND_RPC_SET_LOG_LEVEL, !m_restricted) MAP_URI_AUTO_JON2_IF("/set_log_categories", on_set_log_categories, COMMAND_RPC_SET_LOG_CATEGORIES, !m_restricted) @@ -186,6 +187,7 @@ namespace cryptonote bool on_get_net_stats(const COMMAND_RPC_GET_NET_STATS::request& req, COMMAND_RPC_GET_NET_STATS::response& res, const connection_context *ctx = NULL); bool on_save_bc(const COMMAND_RPC_SAVE_BC::request& req, COMMAND_RPC_SAVE_BC::response& res, const connection_context *ctx = NULL); bool on_get_peer_list(const COMMAND_RPC_GET_PEER_LIST::request& req, COMMAND_RPC_GET_PEER_LIST::response& res, const connection_context *ctx = NULL); + bool on_get_public_nodes(const COMMAND_RPC_GET_PUBLIC_NODES::request& req, COMMAND_RPC_GET_PUBLIC_NODES::response& res, const connection_context *ctx = NULL); bool on_set_log_hash_rate(const COMMAND_RPC_SET_LOG_HASH_RATE::request& req, COMMAND_RPC_SET_LOG_HASH_RATE::response& res, const connection_context *ctx = NULL); bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request& req, COMMAND_RPC_SET_LOG_LEVEL::response& res, const connection_context *ctx = NULL); bool on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request& req, COMMAND_RPC_SET_LOG_CATEGORIES::response& res, const connection_context *ctx = NULL); @@ -236,6 +238,7 @@ namespace cryptonote private: bool check_core_busy(); bool check_core_ready(); + bool add_host_fail(const connection_context *ctx); //utils uint64_t get_block_reward(const block& blk); @@ -256,6 +259,8 @@ private: bool m_was_bootstrap_ever_used; network_type m_nettype; bool m_restricted; + epee::critical_section m_host_fails_score_lock; + std::map<std::string, uint64_t> m_host_fails_score; }; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 571a71207..7ae0c77b2 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -87,7 +87,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 2 -#define CORE_RPC_VERSION_MINOR 7 +#define CORE_RPC_VERSION_MINOR 8 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -612,6 +612,7 @@ namespace cryptonote bool overspend; bool fee_too_low; bool not_rct; + bool too_few_outputs; bool sanity_check_failed; bool untrusted; @@ -627,6 +628,7 @@ namespace cryptonote KV_SERIALIZE(overspend) KV_SERIALIZE(fee_too_low) KV_SERIALIZE(not_rct) + KV_SERIALIZE(too_few_outputs) KV_SERIALIZE(sanity_check_failed) KV_SERIALIZE(untrusted) END_KV_SERIALIZE_MAP() @@ -1094,10 +1096,12 @@ namespace cryptonote struct request_t { std::string hash; + std::vector<std::string> hashes; bool fill_pow_hash; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(hash) + KV_SERIALIZE(hashes) KV_SERIALIZE_OPT(fill_pow_hash, false); END_KV_SERIALIZE_MAP() }; @@ -1107,10 +1111,12 @@ namespace cryptonote { std::string status; block_header_response block_header; + std::vector<block_header_response> block_headers; bool untrusted; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(block_header) + KV_SERIALIZE(block_headers) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) END_KV_SERIALIZE_MAP() @@ -1200,6 +1206,9 @@ namespace cryptonote peer(uint64_t id, const std::string &host, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port) : id(id), host(host), ip(0), port(0), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed) {} + peer(uint64_t id, const std::string &host, uint16_t port, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port) + : id(id), host(host), ip(0), port(port), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed) + {} peer(uint64_t id, uint32_t ip, uint16_t port, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port) : id(id), host(epee::string_tools::get_ip_string_from_int32(ip)), ip(ip), port(port), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed) {} @@ -1239,6 +1248,54 @@ namespace cryptonote typedef epee::misc_utils::struct_init<response_t> response; }; + struct public_node + { + std::string host; + uint64_t last_seen; + uint16_t rpc_port; + + public_node() = delete; + + public_node(const peer &peer) + : host(peer.host), last_seen(peer.last_seen), rpc_port(peer.rpc_port) + {} + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(host) + KV_SERIALIZE(last_seen) + KV_SERIALIZE(rpc_port) + END_KV_SERIALIZE_MAP() + }; + + struct COMMAND_RPC_GET_PUBLIC_NODES + { + struct request_t + { + bool gray; + bool white; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(gray, false) + KV_SERIALIZE_OPT(white, true) + END_KV_SERIALIZE_MAP() + }; + typedef epee::misc_utils::struct_init<request_t> request; + + struct response_t + { + std::string status; + std::vector<public_node> gray; + std::vector<public_node> white; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(status) + KV_SERIALIZE(gray) + KV_SERIALIZE(white) + END_KV_SERIALIZE_MAP() + }; + typedef epee::misc_utils::struct_init<response_t> response; + }; + struct COMMAND_RPC_SET_LOG_HASH_RATE { struct request_t @@ -2095,7 +2152,7 @@ namespace cryptonote struct response_t { std::string status; - std::list<chain_info> chains; + std::vector<chain_info> chains; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 612b2cab6..890380dc8 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -343,6 +343,11 @@ namespace rpc if (!res.error_details.empty()) res.error_details += " and "; res.error_details = "tx is not ringct"; } + if (tvc.m_too_few_outputs) + { + if (!res.error_details.empty()) res.error_details += " and "; + res.error_details = "too few outputs"; + } if (res.error_details.empty()) { res.error_details = "an unknown issue was found with the transaction"; diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index 4479bd1f1..68b33cb8c 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -90,6 +90,9 @@ namespace cryptonote rpc_args::descriptors::descriptors() : rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"}) + , rpc_bind_ipv6_address({"rpc-bind-ipv6-address", rpc_args::tr("Specify IPv6 address to bind RPC server"), "::1"}) + , rpc_use_ipv6({"rpc-use-ipv6", rpc_args::tr("Allow IPv6 for RPC"), false}) + , rpc_require_ipv4({"rpc-require-ipv4", rpc_args::tr("Require successful IPv4 bind for RPC"), true}) , rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true}) , confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")}) , rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""}) @@ -108,6 +111,9 @@ namespace cryptonote { const descriptors arg{}; command_line::add_arg(desc, arg.rpc_bind_ip); + command_line::add_arg(desc, arg.rpc_bind_ipv6_address); + command_line::add_arg(desc, arg.rpc_use_ipv6); + command_line::add_arg(desc, arg.rpc_require_ipv4); command_line::add_arg(desc, arg.rpc_login); command_line::add_arg(desc, arg.confirm_external_bind); command_line::add_arg(desc, arg.rpc_access_control_origins); @@ -127,6 +133,9 @@ namespace cryptonote rpc_args config{}; config.bind_ip = command_line::get_arg(vm, arg.rpc_bind_ip); + config.bind_ipv6_address = command_line::get_arg(vm, arg.rpc_bind_ipv6_address); + config.use_ipv6 = command_line::get_arg(vm, arg.rpc_use_ipv6); + config.require_ipv4 = command_line::get_arg(vm, arg.rpc_require_ipv4); if (!config.bind_ip.empty()) { // always parse IP here for error consistency @@ -148,6 +157,34 @@ namespace cryptonote return boost::none; } } + if (!config.bind_ipv6_address.empty()) + { + // allow square braces, but remove them here if present + if (config.bind_ipv6_address.find('[') != std::string::npos) + { + config.bind_ipv6_address = config.bind_ipv6_address.substr(1, config.bind_ipv6_address.size() - 2); + } + + + // always parse IP here for error consistency + boost::system::error_code ec{}; + const auto parsed_ip = boost::asio::ip::address::from_string(config.bind_ipv6_address, ec); + if (ec) + { + LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_bind_ipv6_address.name); + return boost::none; + } + + if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg.confirm_external_bind)) + { + LOG_ERROR( + "--" << arg.rpc_bind_ipv6_address.name << + tr(" permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --") << + arg.confirm_external_bind.name + ); + return boost::none; + } + } const char *env_rpc_login = nullptr; const bool has_rpc_arg = command_line::has_arg(vm, arg.rpc_login); diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h index 619f02b42..cd154a4d0 100644 --- a/src/rpc/rpc_args.h +++ b/src/rpc/rpc_args.h @@ -52,6 +52,9 @@ namespace cryptonote descriptors& operator=(descriptors&&) = delete; const command_line::arg_descriptor<std::string> rpc_bind_ip; + const command_line::arg_descriptor<std::string> rpc_bind_ipv6_address; + const command_line::arg_descriptor<bool> rpc_use_ipv6; + const command_line::arg_descriptor<bool> rpc_require_ipv4; const command_line::arg_descriptor<std::string> rpc_login; const command_line::arg_descriptor<bool> confirm_external_bind; const command_line::arg_descriptor<std::string> rpc_access_control_origins; @@ -76,6 +79,9 @@ namespace cryptonote static boost::optional<epee::net_utils::ssl_options_t> process_ssl(const boost::program_options::variables_map& vm, const bool any_cert_option = false); std::string bind_ip; + std::string bind_ipv6_address; + bool use_ipv6; + bool require_ipv4; std::vector<std::string> access_control_origins; boost::optional<tools::login> login; // currently `boost::none` if unspecified by user epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled; |