7#include <botan/ipv6_address.h>
9#include <botan/ipv4_address.h>
10#include <botan/internal/fmt.h>
11#include <botan/internal/loadstor.h>
12#include <botan/internal/parsing.h>
18 for(
size_t i = 0; i != 16; ++i) {
34 BOTAN_ARG_CHECK(bits <= 128,
"IPv6 netmask prefix length must be at most 128");
36 const size_t full_bytes = bits / 8;
37 const size_t leftover = bits % 8;
39 std::array<uint8_t, 16> m{};
40 for(
size_t i = 0; i != full_bytes; ++i) {
45 m[full_bytes] =
static_cast<uint8_t
>(0xFF << (8 - leftover));
56 std::array<uint8_t, 16> masked{};
57 for(
size_t i = 0; i != 16; ++i) {
58 masked[i] = m_ip[i] & other.m_ip[i];
66 for(
size_t i = 0; i != 16; ++i) {
67 const size_t hw = (m_ip[i] == 0xFF) ? 8 : std::countl_one(m_ip[i]);
87 if(ip0 == 0x00000000 && ip1 == 0x00000000 && (ip2 == 0x00000000 || ip2 == 0x0000FFFF)) {
102 const auto addr =
IPv6Address(addr_and_mask.first<16>());
103 const auto mask =
IPv6Address(addr_and_mask.last<16>());
105 if(
const auto plen = mask.prefix_length()) {
114 const auto slash = str.find(
'/');
115 if(slash == std::string_view::npos) {
120 if(!addr.has_value()) {
125 const auto plen_str = str.substr(slash + 1);
126 if(plen_str.empty() || plen_str.size() > 3) {
130 for(
const char c : plen_str) {
131 if(c <
'0' || c >
'9') {
134 plen = plen * 10 +
static_cast<size_t>(c -
'0');
148 return fmt(
"{}/{}", m_address.to_string(),
static_cast<size_t>(m_prefix_length));
152 const auto addr = m_address.address();
154 return std::vector<uint8_t>(addr.begin(), addr.end());
157 std::vector<uint8_t> out;
159 out.insert(out.end(), addr.begin(), addr.end());
160 out.insert(out.end(), mask.begin(), mask.end());
#define BOTAN_ARG_CHECK(expr, msg)
std::optional< IPv4Address > as_ipv4() const
IPv6Address(std::span< const uint8_t, 16 > ip)
std::string to_string() const
static IPv6Address netmask(size_t bits)
static std::optional< IPv6Address > from_string(std::string_view str)
IPv6Address operator&(const IPv6Address &other) const
std::optional< size_t > prefix_length() const
std::span< const uint8_t, 16 > address() const
bool contains(const IPv6Address &ip) const
True iff ip falls within this subnet.
size_t prefix_length() const
Prefix length in [0, 128].
std::string to_string() const
CIDR-style "2001:db8::/32".
static std::optional< IPv6Subnet > from_address_and_mask(std::span< const uint8_t, 32 > addr_and_mask)
const IPv6Address & address() const
The network address (host bits already zeroed).
static std::optional< IPv6Subnet > from_string(std::string_view str)
IPv6Subnet(IPv6Address address, size_t prefix_length)
bool is_host() const
True iff prefix_length() == 128.
std::vector< uint8_t > serialize() const
std::string fmt(std::string_view format, const T &... args)
std::optional< std::array< uint8_t, 16 > > string_to_ipv6(std::string_view str)
constexpr auto load_be(ParamTs &&... params)
std::string ipv6_to_string(std::span< const uint8_t, 16 > a)