7#include <botan/ipv4_address.h>
9#include <botan/internal/fmt.h>
10#include <botan/internal/loadstor.h>
11#include <botan/internal/parsing.h>
21std::optional<uint32_t> string_to_ipv4(std::string_view str) {
24 if(str.size() < 3 + 4 * 1 || str.size() > 3 + 4 * 3) {
35 size_t cur_digits = 0;
37 for(
const char c : str) {
50 ip = (ip << 8) | accum;
52 }
else if(c >=
'0' && c <=
'9') {
53 const auto d =
static_cast<uint8_t
>(c -
'0');
56 if(cur_digits > 0 && accum == 0) {
59 accum = (accum * 10) + d;
82 ip = (ip << 8) | accum;
91 if(
auto ipv4 = string_to_ipv4(str)) {
100 BOTAN_ARG_CHECK(bits <= 32,
"IPv4 netmask prefix length must be at most 32");
108 std::array<uint8_t, 4> out{};
119 for(
size_t i = 0; i != 4; ++i) {
123 str += std::to_string(addr[i]);
132 const uint32_t inv = ~m_ip;
133 if((inv & (inv + 1)) != 0) {
136 return std::countl_one(m_ip);
147 std::array<uint8_t, 8> addr_and_mask{};
167 const auto slash = str.find(
'/');
168 if(slash == std::string_view::npos) {
173 if(!addr.has_value()) {
178 const auto plen_str = str.substr(slash + 1);
180 const auto plen =
parse_sz(plen_str,
true);
182 if(!plen.has_value() || plen.value() > 32) {
202 return fmt(
"{}/{}", m_address.to_string(),
static_cast<size_t>(m_prefix_length));
206 std::vector<uint8_t> out;
209 store_be(m_address.address(), out.data());
213 store_be(m_address.address(), out.data());
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ARG_CHECK(expr, msg)
static std::optional< IPv4Address > from_string(std::string_view str)
std::optional< size_t > prefix_length() const
std::string to_string() const
Dotted-decimal form, e.g. "10.0.0.1".
std::array< uint8_t, 4 > to_bytes() const
The address as four bytes, network-byte-order.
static IPv4Address netmask(size_t bits)
static std::optional< IPv4Subnet > from_address_and_mask(std::span< const uint8_t, 8 > addr_and_mask)
std::vector< uint8_t > serialize() const
bool contains(const IPv4Address &ip) const
True iff ip falls within this subnet.
bool is_host() const
True iff prefix_length() == 32.
IPv4Subnet(IPv4Address address, size_t prefix_length)
size_t prefix_length() const
Prefix length in [0, 32].
static std::optional< IPv4Subnet > from_string(std::string_view str)
std::string to_string() const
CIDR-style "10.0.0.0/8".
const IPv4Address & address() const
The network address (host bits already zeroed).
std::string fmt(std::string_view format, const T &... args)
std::optional< size_t > parse_sz(std::string_view input, bool require_canonical)
constexpr auto store_be(ParamTs &&... params)
constexpr auto load_be(ParamTs &&... params)