aboutsummaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/error.h3
-rw-r--r--src/net/parse.cpp82
-rw-r--r--src/net/parse.h15
3 files changed, 90 insertions, 10 deletions
diff --git a/src/net/error.h b/src/net/error.h
index c8338f7e2..7c852dd20 100644
--- a/src/net/error.h
+++ b/src/net/error.h
@@ -42,7 +42,8 @@ namespace net
invalid_i2p_address,
invalid_port, //!< Outside of 0-65535 range
invalid_tor_address,//!< Invalid base32 or length
- unsupported_address //!< Type not supported by `get_network_address`
+ unsupported_address,//!< Type not supported by `get_network_address`
+ invalid_mask, //!< Outside of 0-32 range
};
//! \return `std::error_category` for `net` namespace.
diff --git a/src/net/parse.cpp b/src/net/parse.cpp
index eaaadb67e..ce580afe7 100644
--- a/src/net/parse.cpp
+++ b/src/net/parse.cpp
@@ -34,28 +34,92 @@
namespace net
{
+ void get_network_address_host_and_port(const std::string& address, std::string& host, std::string& port)
+ {
+ // require ipv6 address format "[addr:addr:addr:...:addr]:port"
+ if (address.find(']') != std::string::npos)
+ {
+ host = address.substr(1, address.rfind(']') - 1);
+ if ((host.size() + 2) < address.size())
+ {
+ port = address.substr(address.rfind(':') + 1);
+ }
+ }
+ else
+ {
+ host = address.substr(0, address.rfind(':'));
+ if (host.size() < address.size())
+ {
+ port = address.substr(host.size() + 1);
+ }
+ }
+ }
+
expect<epee::net_utils::network_address>
get_network_address(const boost::string_ref address, const std::uint16_t default_port)
{
- const boost::string_ref host = address.substr(0, address.rfind(':'));
+ std::string host_str = "";
+ std::string port_str = "";
- if (host.empty())
+ bool ipv6 = false;
+
+ get_network_address_host_and_port(std::string(address), host_str, port_str);
+
+ boost::string_ref host_str_ref(host_str);
+ boost::string_ref port_str_ref(port_str);
+
+ if (host_str.empty())
return make_error_code(net::error::invalid_host);
- if (host.ends_with(".onion"))
+ if (host_str_ref.ends_with(".onion"))
return tor_address::make(address, default_port);
- if (host.ends_with(".i2p"))
+ if (host_str_ref.ends_with(".i2p"))
return i2p_address::make(address, default_port);
+ boost::system::error_code ec;
+ boost::asio::ip::address_v6 v6 = boost::asio::ip::address_v6::from_string(host_str, ec);
+ ipv6 = !ec;
+
std::uint16_t port = default_port;
- if (host.size() < address.size())
+ if (port_str.size())
{
- if (!epee::string_tools::get_xtype_from_string(port, std::string{address.substr(host.size() + 1)}))
+ if (!epee::string_tools::get_xtype_from_string(port, port_str))
return make_error_code(net::error::invalid_port);
}
- std::uint32_t ip = 0;
- if (epee::string_tools::get_ip_int32_from_string(ip, std::string{host}))
- return {epee::net_utils::ipv4_network_address{ip, port}};
+ if (ipv6)
+ {
+ return {epee::net_utils::ipv6_network_address{v6, port}};
+ }
+ else
+ {
+ std::uint32_t ip = 0;
+ if (epee::string_tools::get_ip_int32_from_string(ip, host_str))
+ return {epee::net_utils::ipv4_network_address{ip, port}};
+ }
+
return make_error_code(net::error::unsupported_address);
}
+
+ expect<epee::net_utils::ipv4_network_subnet>
+ get_ipv4_subnet_address(const boost::string_ref address, bool allow_implicit_32)
+ {
+ uint32_t mask = 32;
+ const boost::string_ref::size_type slash = address.find_first_of('/');
+ if (slash != boost::string_ref::npos)
+ {
+ if (!epee::string_tools::get_xtype_from_string(mask, std::string{address.substr(slash + 1)}))
+ return make_error_code(net::error::invalid_mask);
+ if (mask > 32)
+ return make_error_code(net::error::invalid_mask);
+ }
+ else if (!allow_implicit_32)
+ return make_error_code(net::error::invalid_mask);
+
+ std::uint32_t ip = 0;
+ boost::string_ref S(address.data(), slash != boost::string_ref::npos ? slash : address.size());
+ if (!epee::string_tools::get_ip_int32_from_string(ip, std::string(S)))
+ return make_error_code(net::error::invalid_host);
+
+ return {epee::net_utils::ipv4_network_subnet{ip, (uint8_t)mask}};
+ }
}
diff --git a/src/net/parse.h b/src/net/parse.h
index 5804c4128..0d8fda711 100644
--- a/src/net/parse.h
+++ b/src/net/parse.h
@@ -36,6 +36,8 @@
namespace net
{
+ void get_network_address_host_and_port(const std::string& address, std::string& host, std::string& port);
+
/*!
Identifies onion, i2p and IPv4 addresses and returns them as a generic
`network_address`. If the type is unsupported, it might be a hostname,
@@ -50,5 +52,18 @@ namespace net
*/
expect<epee::net_utils::network_address>
get_network_address(boost::string_ref address, std::uint16_t default_port);
+
+ /*!
+ Identifies an IPv4 subnet in CIDR notatioa and returns it as a generic
+ `network_address`. If the type is unsupported, it might be a hostname,
+ and `error() == net::error::kUnsupportedAddress` is returned.
+
+ \param address An ipv4 address.
+ \param allow_implicit_32 whether to accept "raw" IPv4 addresses, with CIDR notation
+
+ \return A tor or IPv4 address, else error.
+ */
+ expect<epee::net_utils::ipv4_network_subnet>
+ get_ipv4_subnet_address(boost::string_ref address, bool allow_implicit_32 = false);
}