12#ifndef OPENVPN_ADDR_IPV6_H
13#define OPENVPN_ADDR_IPV6_H
43 static constexpr unsigned int SIZE = 128;
67 std::memcpy(&src, in6->s6_addr,
sizeof(
ipv6addr));
86 sockaddr_in6
ret = {};
87 ret.sin6_family = AF_INET6;
93 ret.sin6_len =
sizeof(sockaddr_in6);
98#ifndef OPENVPN_LEGACY_TITLE_ABSTRACTION
100 template <
typename TITLE>
103 openvpn_io::error_code ec;
104 const openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec);
117 static Addr from_string(
const std::string &ipstr,
const char *title =
nullptr)
119 openvpn_io::error_code ec;
120 openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec);
130 const openvpn_io::ip::address_v6 a =
to_asio();
131 const std::string
ret = a.to_string();
143 size_t len = s.length();
145 if (len > 0 && s[len - 1] ==
'L')
147 if (len >= 2 && s[0] ==
'0' && s[1] ==
'x')
152 if (len < 1 || len > 32)
153 throw ipv6_exception(
"parse hex error");
154 size_t di = (len - 1) >> 1;
155 for (
int i = (len & 1) ? -1 : 0; i < static_cast<int>(len); i += 2)
157 const size_t idx = base + i;
160 if (bh == -1 || bl == -1)
161 throw ipv6_exception(
"parse hex error");
162 ret.u.bytes[Endian::e16(di--)] =
static_cast<unsigned char>((bh << 4) + bl);
171 bool firstnonzero =
false;
172 for (
size_t i = 0; i < 16; ++i)
174 const unsigned char b =
u.
bytes[Endian::e16rev(i)];
175 if (b || firstnonzero || i == 15)
177 const char bh =
static_cast<decltype(bh)
>(b >> 4);
178 if (bh || firstnonzero)
191 ret.u.u64[Endian::e2(1)] = 0;
197 const unsigned long ret =
static_cast<unsigned long>(
u.
u64[Endian::e2(0)]);
198 const auto cmp = std::uint64_t(
ret);
199 if (
u.
u64[Endian::e2(1)] || cmp !=
u.
u64[Endian::e2(0)])
200 throw ipv6_exception(
"overflow in conversion from IPv6.Addr to unsigned long");
213 ret.
u.
u64[Endian::e2(0)] = std::uint64_t(ul);
214 ret.u.u64[Endian::e2(1)] = 0;
224 if (a.
u.
u64[Endian::e2(1)])
229 const long ret =
static_cast<long>(a.
u.
u64[Endian::e2(0)]);
230 const auto cmp = std::uint64_t(
ret);
231 if (a.
u.
u64[Endian::e2(1)] || cmp != a.
u.
u64[Endian::e2(0)])
232 throw ipv6_exception(
"overflow in conversion from IPv6.Addr to long");
233 return neg ? -(
ret + 1) :
ret;
238 throw ipv6_exception(
"arpa() not implemented");
247 ret.scope_id_ = asio_addr.scope_id();
258 std::memcpy(&src, bytestr,
sizeof(src));
270 std::memcpy(bytestr, &
ret,
sizeof(
ret));
274 const std::uint32_t v4addr)
280 std::memcpy(bytestr, &
ret,
sizeof(
ret));
286 std::memcpy(&a, bytestr,
sizeof(a));
287 return a.u32[0] == 0 && a.u32[1] == 0 && a.u32[2] == 0;
293 std::memcpy(&a, bytestr,
sizeof(a));
334 const Addr lb = *
this - 1;
335 for (
size_t i = 4; i-- > 0;)
337 const std::uint32_t v = lb.
u.
u32[Endian::e4(i)];
365 ret.
u.
u64[Endian::e2(0)] += delta;
366 ret.u.u64[Endian::e2(1)] += (delta >= 0)
367 ? (
ret.u.u64[Endian::e2(0)] <
u.
u64[Endian::e2(0)])
368 : -(
ret.u.u64[Endian::e2(0)] >
u.
u64[Endian::e2(0)]);
395 for (
unsigned int i = 0; i <
SIZE; ++i)
422 ret.u.u64[Endian::e2(1)],
431 ret.u.u64[Endian::e2(1)],
440 ret.u.u64[0] = ~u.u64[0];
441 ret.u.u64[1] = ~u.u64[1];
464 return compare(other, std::less<>{});
468 return compare(other, std::greater<>{});
472 return compare(other, std::less_equal<>{});
476 return compare(other, std::greater_equal<>{});
491 return u.
u64[0] == 0 &&
u.
u64[1] == 0;
496 return u.
u64[0] == ~std::uint64_t(0) &&
u.
u64[1] == ~std::uint64_t(0);
501 return u.
u64[Endian::e2(1)] == 0 &&
u.
u64[Endian::e2(0)] == 1;
506 return u.
u32[Endian::e4(1)] == 0xffff &&
u.
u32[Endian::e4(2)] == 0 &&
u.
u32[Endian::e4(3)] == 0;
511 return u.
u32[Endian::e2(0)];
514 bool bit(
unsigned int pos)
const
517 return (
u.
u64[Endian::e2(0)] & (std::uint64_t(1) << pos)) != 0;
518 return (
u.
u64[Endian::e2(1)] & (std::uint64_t(1) << (pos - 64))) != 0;
527 if (
u.
u32[Endian::e4(3)] != ~std::uint32_t(0))
529 if (!
u.
u32[Endian::e4(0)] && !
u.
u32[Endian::e4(1)] && !
u.
u32[Endian::e4(2)])
532 else if (
u.
u32[Endian::e4(2)] != ~std::uint32_t(0))
534 if (!
u.
u32[Endian::e4(0)] && !
u.
u32[Endian::e4(1)])
537 else if (
u.
u32[Endian::e4(1)] != ~std::uint32_t(0))
539 if (!
u.
u32[Endian::e4(0)])
549 return ret + (idx << 5);
551 throw ipv6_exception(
"malformed netmask");
572 throw ipv6_exception(
"extent overflow");
581 template <
typename HASH>
587#ifdef USE_OPENVPN_HASH
588 std::uint64_t hashval()
const
596#ifdef OPENVPN_IP_IMMUTABLE
602 u.
u64[0] = ~u.u64[0];
603 u.
u64[1] = ~u.u64[1];
614 u.
u64[0] = ~std::uint64_t(0);
615 u.
u64[1] = ~std::uint64_t(0);
626 if (++
u.
u64[Endian::e2(0)] == 0)
627 ++
u.
u64[Endian::e2(1)];
633 *
this = *
this + delta;
657 u.
u64[Endian::e2(1)],
665 u.
u64[Endian::e2(1)],
675 u.
u64[Endian::e2(0)] |= (std::uint64_t(1) << pos);
677 u.
u64[Endian::e2(0)] &= ~(std::uint64_t(1) << pos);
682 u.
u64[Endian::e2(1)] |= (std::uint64_t(1) << (pos - 64));
684 u.
u64[Endian::e2(1)] &= ~(std::uint64_t(1) << (pos - 64));
693 u.
u64[Endian::e2(0)] |= (std::uint64_t(1) << pos);
695 u.
u64[Endian::e2(1)] |= (std::uint64_t(1) << (pos - 64));
702 throw ipv6_exception(
"division by 0");
704 remainder = numerator;
706 Addr mask_high = denominator;
707 for (
unsigned int i = 0; i <
SIZE; ++i)
712 if (mask_high.
all_zeros() && remainder >= mask_low)
714 remainder -= mask_low;
738 const std::uint32_t mask = ~((1U << (31 - (pl & 31))) - 1);
742 u.
u32[Endian::e4(0)] = 0;
743 u.
u32[Endian::e4(1)] = 0;
744 u.
u32[Endian::e4(2)] = 0;
745 u.
u32[Endian::e4(3)] = mask;
748 u.
u32[Endian::e4(0)] = 0;
749 u.
u32[Endian::e4(1)] = 0;
750 u.
u32[Endian::e4(2)] = mask;
751 u.
u32[Endian::e4(3)] = ~0;
754 u.
u32[Endian::e4(0)] = 0;
755 u.
u32[Endian::e4(1)] = mask;
756 u.
u32[Endian::e4(2)] = ~0;
757 u.
u32[Endian::e4(3)] = ~0;
760 u.
u32[Endian::e4(0)] = mask;
761 u.
u32[Endian::e4(1)] = ~0;
762 u.
u32[Endian::e4(2)] = ~0;
763 u.
u32[Endian::e4(3)] = ~0;
775 throw ipv6_exception(
"bad prefix len");
780 dest->
u32[0] = htonl(src->
u32[Endian::e4rev(0)]);
781 dest->
u32[1] = htonl(src->
u32[Endian::e4rev(1)]);
782 dest->
u32[2] = htonl(src->
u32[Endian::e4rev(2)]);
783 dest->
u32[3] = htonl(src->
u32[Endian::e4rev(3)]);
788 dest->
u32[0] = ntohl(src->
u32[Endian::e4rev(0)]);
789 dest->
u32[1] = ntohl(src->
u32[Endian::e4rev(1)]);
790 dest->
u32[2] = ntohl(src->
u32[Endian::e4rev(2)]);
791 dest->
u32[3] = ntohl(src->
u32[Endian::e4rev(3)]);
802 if (low & (std::uint64_t(1) << 63U))
810 else if (shift == 128)
817 high = (high << shift) | (low >> (64U - shift));
820 else if (shift < 128)
829 throw ipv6_exception(
"l-shift too large");
840 low |= (std::uint64_t(1) << 63U);
848 low = (low >> shift) | (high << (64 - shift));
851 else if (shift <= 128)
858 throw ipv6_exception(
"r-shift too large");
863 const std::uint64_t dorigl = dest.
u64[Endian::e2(0)];
864 dest.
u64[Endian::e2(0)] += src.
u64[Endian::e2(0)];
865 dest.
u64[Endian::e2(1)] += src.
u64[Endian::e2(1)];
867 if (dest.
u64[Endian::e2(0)] < dorigl)
868 ++dest.
u64[Endian::e2(1)];
873 const std::uint64_t dorigl = dest.
u64[Endian::e2(0)];
874 dest.
u64[Endian::e2(0)] -= src.
u64[Endian::e2(0)];
875 dest.
u64[Endian::e2(1)] -= src.
u64[Endian::e2(1)]
876 + (dorigl < dest.
u64[Endian::e2(0)]);
880 template <
typename Comparator>
884 if (
u.
u64[Endian::e2(1)] == other.
u.
u64[Endian::e2(1)])
886 if (
u.
u64[Endian::e2(0)] != other.
u.
u64[Endian::e2(0)])
887 return comp(
u.
u64[Endian::e2(0)], other.
u.
u64[Endian::e2(0)]);
890 return comp(
u.
u64[Endian::e2(1)], other.
u.
u64[Endian::e2(1)]);
900#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)
static constexpr unsigned int SIZE
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