12#ifndef OPENVPN_ADDR_IPV6_H
13#define OPENVPN_ADDR_IPV6_H
70 std::memcpy(&src, in6->s6_addr,
sizeof(
ipv6addr));
89 sockaddr_in6
ret = {};
90 ret.sin6_family = AF_INET6;
96 ret.sin6_len =
sizeof(sockaddr_in6);
101#ifndef OPENVPN_LEGACY_TITLE_ABSTRACTION
103 template <
typename TITLE>
106 openvpn_io::error_code ec;
107 openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec);
120 static Addr from_string(
const std::string &ipstr,
const char *title =
nullptr)
122 openvpn_io::error_code ec;
123 openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec);
133 const openvpn_io::ip::address_v6 a =
to_asio();
134 std::string
ret = a.to_string();
146 size_t len = s.length();
148 if (len > 0 && s[len - 1] ==
'L')
150 if (len >= 2 && s[0] ==
'0' && s[1] ==
'x')
155 if (len < 1 || len > 32)
156 throw ipv6_exception(
"parse hex error");
157 size_t di = (len - 1) >> 1;
158 for (
int i = (len & 1) ? -1 : 0; i < static_cast<int>(len); i += 2)
160 const size_t idx = base + i;
163 if (bh == -1 || bl == -1)
164 throw ipv6_exception(
"parse hex error");
165 ret.u.bytes[Endian::e16(di--)] =
static_cast<unsigned char>((bh << 4) + bl);
174 bool firstnonzero =
false;
175 for (
size_t i = 0; i < 16; ++i)
177 const unsigned char b =
u.
bytes[Endian::e16rev(i)];
178 if (b || firstnonzero || i == 15)
180 const char bh =
static_cast<decltype(bh)
>(b >> 4);
181 if (bh || firstnonzero)
194 ret.u.u64[Endian::e2(1)] = 0;
200 const unsigned long ret =
static_cast<unsigned long>(
u.
u64[Endian::e2(0)]);
201 const auto cmp = std::uint64_t(
ret);
202 if (
u.
u64[Endian::e2(1)] || cmp !=
u.
u64[Endian::e2(0)])
203 throw ipv6_exception(
"overflow in conversion from IPv6.Addr to unsigned long");
216 ret.
u.
u64[Endian::e2(0)] = std::uint64_t(ul);
217 ret.u.u64[Endian::e2(1)] = 0;
227 if (a.
u.
u64[Endian::e2(1)])
232 const long ret =
static_cast<long>(a.
u.
u64[Endian::e2(0)]);
233 const auto cmp = std::uint64_t(
ret);
234 if (a.
u.
u64[Endian::e2(1)] || cmp != a.
u.
u64[Endian::e2(0)])
235 throw ipv6_exception(
"overflow in conversion from IPv6.Addr to long");
236 return neg ? -(
ret + 1) :
ret;
241 throw ipv6_exception(
"arpa() not implemented");
250 ret.scope_id_ = asio_addr.scope_id();
261 std::memcpy(&src, bytestr,
sizeof(src));
273 std::memcpy(bytestr, &
ret,
sizeof(
ret));
277 const std::uint32_t v4addr)
283 std::memcpy(bytestr, &
ret,
sizeof(
ret));
289 std::memcpy(&a, bytestr,
sizeof(a));
290 return a.u32[0] == 0 && a.u32[1] == 0 && a.u32[2] == 0;
296 std::memcpy(&a, bytestr,
sizeof(a));
337 const Addr lb = *
this - 1;
338 for (
size_t i = 4; i-- > 0;)
340 const std::uint32_t v = lb.
u.
u32[Endian::e4(i)];
368 ret.
u.
u64[Endian::e2(0)] += delta;
369 ret.u.u64[Endian::e2(1)] += (delta >= 0)
370 ? (
ret.u.u64[Endian::e2(0)] <
u.
u64[Endian::e2(0)])
371 : -(
ret.u.u64[Endian::e2(0)] >
u.
u64[Endian::e2(0)]);
398 for (
unsigned int i = 0; i <
SIZE; ++i)
425 ret.u.u64[Endian::e2(1)],
434 ret.u.u64[Endian::e2(1)],
443 ret.u.u64[0] = ~u.u64[0];
444 ret.u.u64[1] = ~u.u64[1];
467 return compare(other, std::less<>{});
471 return compare(other, std::greater<>{});
475 return compare(other, std::less_equal<>{});
479 return compare(other, std::greater_equal<>{});
494 return u.
u64[0] == 0 &&
u.
u64[1] == 0;
499 return u.
u64[0] == ~std::uint64_t(0) &&
u.
u64[1] == ~std::uint64_t(0);
504 return u.
u64[Endian::e2(1)] == 0 &&
u.
u64[Endian::e2(0)] == 1;
509 return u.
u32[Endian::e4(1)] == 0xffff &&
u.
u32[Endian::e4(2)] == 0 &&
u.
u32[Endian::e4(3)] == 0;
514 return u.
u32[Endian::e2(0)];
517 bool bit(
unsigned int pos)
const
520 return (
u.
u64[Endian::e2(0)] & (std::uint64_t(1) << pos)) != 0;
521 return (
u.
u64[Endian::e2(1)] & (std::uint64_t(1) << (pos - 64))) != 0;
530 if (
u.
u32[Endian::e4(3)] != ~std::uint32_t(0))
532 if (!
u.
u32[Endian::e4(0)] && !
u.
u32[Endian::e4(1)] && !
u.
u32[Endian::e4(2)])
535 else if (
u.
u32[Endian::e4(2)] != ~std::uint32_t(0))
537 if (!
u.
u32[Endian::e4(0)] && !
u.
u32[Endian::e4(1)])
540 else if (
u.
u32[Endian::e4(1)] != ~std::uint32_t(0))
542 if (!
u.
u32[Endian::e4(0)])
552 return ret + (idx << 5);
554 throw ipv6_exception(
"malformed netmask");
575 throw ipv6_exception(
"extent overflow");
584 template <
typename HASH>
590#ifdef USE_OPENVPN_HASH
591 std::uint64_t hashval()
const
599#ifdef OPENVPN_IP_IMMUTABLE
605 u.
u64[0] = ~u.u64[0];
606 u.
u64[1] = ~u.u64[1];
617 u.
u64[0] = ~std::uint64_t(0);
618 u.
u64[1] = ~std::uint64_t(0);
629 if (++
u.
u64[Endian::e2(0)] == 0)
630 ++
u.
u64[Endian::e2(1)];
636 *
this = *
this + delta;
660 u.
u64[Endian::e2(1)],
668 u.
u64[Endian::e2(1)],
678 u.
u64[Endian::e2(0)] |= (std::uint64_t(1) << pos);
680 u.
u64[Endian::e2(0)] &= ~(std::uint64_t(1) << pos);
685 u.
u64[Endian::e2(1)] |= (std::uint64_t(1) << (pos - 64));
687 u.
u64[Endian::e2(1)] &= ~(std::uint64_t(1) << (pos - 64));
696 u.
u64[Endian::e2(0)] |= (std::uint64_t(1) << pos);
698 u.
u64[Endian::e2(1)] |= (std::uint64_t(1) << (pos - 64));
705 throw ipv6_exception(
"division by 0");
707 remainder = numerator;
709 Addr mask_high = denominator;
710 for (
unsigned int i = 0; i <
SIZE; ++i)
715 if (mask_high.
all_zeros() && remainder >= mask_low)
717 remainder -= mask_low;
741 const std::uint32_t mask = ~((1u << (31 - (pl & 31))) - 1);
745 u.
u32[Endian::e4(0)] = 0;
746 u.
u32[Endian::e4(1)] = 0;
747 u.
u32[Endian::e4(2)] = 0;
748 u.
u32[Endian::e4(3)] = mask;
751 u.
u32[Endian::e4(0)] = 0;
752 u.
u32[Endian::e4(1)] = 0;
753 u.
u32[Endian::e4(2)] = mask;
754 u.
u32[Endian::e4(3)] = ~0;
757 u.
u32[Endian::e4(0)] = 0;
758 u.
u32[Endian::e4(1)] = mask;
759 u.
u32[Endian::e4(2)] = ~0;
760 u.
u32[Endian::e4(3)] = ~0;
763 u.
u32[Endian::e4(0)] = mask;
764 u.
u32[Endian::e4(1)] = ~0;
765 u.
u32[Endian::e4(2)] = ~0;
766 u.
u32[Endian::e4(3)] = ~0;
778 throw ipv6_exception(
"bad prefix len");
783 dest->
u32[0] = htonl(src->
u32[Endian::e4rev(0)]);
784 dest->
u32[1] = htonl(src->
u32[Endian::e4rev(1)]);
785 dest->
u32[2] = htonl(src->
u32[Endian::e4rev(2)]);
786 dest->
u32[3] = htonl(src->
u32[Endian::e4rev(3)]);
791 dest->
u32[0] = ntohl(src->
u32[Endian::e4rev(0)]);
792 dest->
u32[1] = ntohl(src->
u32[Endian::e4rev(1)]);
793 dest->
u32[2] = ntohl(src->
u32[Endian::e4rev(2)]);
794 dest->
u32[3] = ntohl(src->
u32[Endian::e4rev(3)]);
805 if (low & (std::uint64_t(1) << 63u))
813 else if (shift == 128)
820 high = (high << shift) | (low >> (64u - shift));
823 else if (shift < 128)
832 throw ipv6_exception(
"l-shift too large");
843 low |= (std::uint64_t(1) << 63u);
851 low = (low >> shift) | (high << (64 - shift));
854 else if (shift <= 128)
861 throw ipv6_exception(
"r-shift too large");
866 const std::uint64_t dorigl = dest.
u64[Endian::e2(0)];
867 dest.
u64[Endian::e2(0)] += src.
u64[Endian::e2(0)];
868 dest.
u64[Endian::e2(1)] += src.
u64[Endian::e2(1)];
870 if (dest.
u64[Endian::e2(0)] < dorigl)
871 ++dest.
u64[Endian::e2(1)];
876 const std::uint64_t dorigl = dest.
u64[Endian::e2(0)];
877 dest.
u64[Endian::e2(0)] -= src.
u64[Endian::e2(0)];
878 dest.
u64[Endian::e2(1)] -= src.
u64[Endian::e2(1)]
879 + (dorigl < dest.
u64[Endian::e2(0)]);
883 template <
typename Comparator>
887 if (
u.
u64[Endian::e2(1)] == other.
u.
u64[Endian::e2(1)])
889 if (
u.
u64[Endian::e2(0)] != other.
u.
u64[Endian::e2(0)])
890 return comp(
u.
u64[Endian::e2(0)], other.
u.
u64[Endian::e2(0)]);
893 return comp(
u.
u64[Endian::e2(1)], other.
u.
u64[Endian::e2(1)]);
903#ifdef USE_OPENVPN_HASH
static int prefix_len_32(const std::uint32_t addr)
Addr & operator<<=(const unsigned int shift)
Addr netmask_from_this_as_extent() const
std::string to_hex() const
void set_clear_bit(unsigned int pos, bool value)
static Addr from_sockaddr(const sockaddr_in6 *sa)
static void sub(ipv6addr &dest, const ipv6addr &src)
bool operator!=(const Addr &other) const
Addr network_addr(const unsigned int prefix_len) const
Addr operator&(const Addr &other) const
unsigned int prefix_len() const
void set_bit(unsigned int pos, bool value)
bool operator==(const Addr &other) const
static std::string arpa()
Addr operator*(const Addr &d) const
Addr operator+(const Addr &other) const
static Addr from_byte_string(const unsigned char *bytestr)
static Addr from_long(long ul)
bool bit(unsigned int pos) const
static Addr from_in6_addr(const in6_addr *in6)
static Addr from_string(const std::string &ipstr)
static bool byte_string_is_v4(const unsigned char *bytestr)
Addr & operator-=(const long delta)
bool compare(const Addr &other, Comparator comp) const
Addr & operator>>=(const unsigned int shift)
void prefix_len_to_netmask(const unsigned int prefix_len)
bool is_mapped_address() const
static Addr from_addr(const Addr &addr)
static void shiftl128(std::uint64_t &low, std::uint64_t &high, unsigned int shift)
static constexpr int ip_version()
static Addr from_hex(const std::string &s)
Addr operator+(const long delta) const
static void host_to_network_order(ipv6addr *dest, const ipv6addr *src)
Addr operator%(const Addr &d) const
static Addr from_zero_complement()
Addr operator|(const Addr &other) const
Addr operator-(const long delta) const
Addr operator/(const Addr &d) const
static Addr netmask_from_prefix_len(const unsigned int prefix_len)
static void v4_to_byte_string(unsigned char *bytestr, const std::uint32_t v4addr)
void to_byte_string(unsigned char *bytestr) const
bool operator<=(const Addr &other) const
unsigned int host_len() const
static std::uint32_t v4_from_byte_string(const unsigned char *bytestr)
Addr & operator+=(const Addr &other)
bool operator>(const Addr &other) const
openvpn_io::ip::address_v6 to_asio() const
static constexpr bool defined()
static void shiftr128(std::uint64_t &low, std::uint64_t &high, unsigned int shift)
static Addr from_asio(const openvpn_io::ip::address_v6 &asio_addr)
static void div(const Addr &numerator, const Addr &denominator, Addr "ient, Addr &remainder)
std::uint32_t get_mapped_ipv4_address() const
Addr operator-(const Addr &other) const
static void network_to_host_order(ipv6addr *dest, const ipv6addr *src)
unsigned long to_ulong() const
Addr operator>>(const unsigned int shift) const
in6_addr to_in6_addr() const
void prefix_len_to_netmask_unchecked(const unsigned int prefix_len)
static void add(ipv6addr &dest, const ipv6addr &src)
std::string to_string() const
static Addr from_string(const std::string &ipstr, const TITLE &title)
Addr & operator+=(const long delta)
Addr & operator-=(const Addr &other)
static unsigned int size()
bool operator>=(const Addr &other) const
Addr operator<<(const unsigned int shift) const
bool operator<(const Addr &other) const
sockaddr_in6 to_sockaddr(const unsigned short port=0) const
Addr extent_from_netmask() const
static Addr from_ulong(unsigned long ul)
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_HASH_METHOD(T, meth)
std::string format_error(const std::string &ipstr, const TITLE &title, const char *ipver, const std::string &message)
std::string to_lower_copy(const std::string &str)
int parse_hex_char(const int c)
char render_hex_char(const int c, const bool caps=false)
#define OPENVPN_OSTREAM(TYPE, METH)
openvpn_io::ip::address_v6::bytes_type asio_bytes