OpenVPN 3 Core Library
Loading...
Searching...
No Matches
ipv6.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#ifndef OPENVPN_ADDR_IPV6_H
13#define OPENVPN_ADDR_IPV6_H
14
15#include <cstring> // for std::memcpy, std::memset
16#include <cstdint> // for std::uint32_t
17
18#include <openvpn/io/io.hpp>
19
25#include <openvpn/addr/ipv4.hpp>
27
28namespace openvpn::IP {
29class Addr;
30}
31
32// Fundamental classes for representing an IPv6 IP address.
33
34namespace openvpn::IPv6 {
35
36OPENVPN_EXCEPTION(ipv6_exception);
37
38class Addr // NOTE: must be union-legal, so default constructor does not initialize
39{
40 friend class IP::Addr;
41
42 public:
43 static constexpr unsigned int SIZE = 128;
44
45 static constexpr int ip_version()
46 {
47 return 6;
48 }
49
50 static constexpr bool defined()
51 {
52 return true;
53 }
54
55 static Addr from_addr(const Addr &addr)
56 {
57 return addr;
58 }
59
60 static Addr from_in6_addr(const in6_addr *in6)
61 {
62 Addr ret;
63 /* Alignment of in6_addr is only 4 while our ipv6 addr requires an
64 * alignment of 8 due to its uint64 members, so use memcpy to copy it
65 */
66 ipv6addr src;
67 std::memcpy(&src, in6->s6_addr, sizeof(ipv6addr));
68 network_to_host_order(&ret.u, &src);
69 return ret;
70 }
71
72 in6_addr to_in6_addr() const
73 {
74 in6_addr ret;
75 host_to_network_order(reinterpret_cast<ipv6addr *>(&ret), &u);
76 return ret;
77 }
78
79 static Addr from_sockaddr(const sockaddr_in6 *sa)
80 {
81 return from_in6_addr(&sa->sin6_addr);
82 }
83
84 sockaddr_in6 to_sockaddr(const unsigned short port = 0) const
85 {
86 sockaddr_in6 ret = {};
87 ret.sin6_family = AF_INET6;
88 ret.sin6_port = htons(port);
89 host_to_network_order(reinterpret_cast<ipv6addr *>(&ret.sin6_addr.s6_addr), &u);
90 ret.sin6_scope_id = scope_id_;
91#ifdef SIN6_LEN
92 /* This is defined on both macOS and FreeBSD that have the sin6_len member */
93 ret.sin6_len = sizeof(sockaddr_in6);
94#endif
95 return ret;
96 }
97
98#ifndef OPENVPN_LEGACY_TITLE_ABSTRACTION
99
100 template <typename TITLE>
101 static Addr from_string(const std::string &ipstr, const TITLE &title)
102 {
103 openvpn_io::error_code ec;
104 const openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec);
105 if (ec)
106 throw ipv6_exception(IP::internal::format_error(ipstr, title, "v6", ec));
107 return from_asio(a);
108 }
109
110 static Addr from_string(const std::string &ipstr)
111 {
112 return from_string(ipstr, nullptr);
113 }
114
115#else
116
117 static Addr from_string(const std::string &ipstr, const char *title = nullptr)
118 {
119 openvpn_io::error_code ec;
120 openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec);
121 if (ec)
122 throw ipv6_exception(IP::internal::format_error(ipstr, title, "v6", ec));
123 return from_asio(a);
124 }
125
126#endif
127
128 std::string to_string() const
129 {
130 const openvpn_io::ip::address_v6 a = to_asio();
131 const std::string ret = a.to_string();
132#ifdef UNIT_TEST
134#else
135 return ret;
136#endif
137 }
138
139 static Addr from_hex(const std::string &s)
140 {
141 Addr ret;
142 ret.zero();
143 size_t len = s.length();
144 size_t base = 0;
145 if (len > 0 && s[len - 1] == 'L')
146 len -= 1;
147 if (len >= 2 && s[0] == '0' && s[1] == 'x')
148 {
149 base = 2;
150 len -= 2;
151 }
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)
156 {
157 const size_t idx = base + i;
158 const int bh = (i >= 0) ? parse_hex_char(s[idx]) : 0;
159 const int bl = parse_hex_char(s[idx + 1]);
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);
163 }
164 return ret;
165 }
166
167 std::string to_hex() const
168 {
169 std::string ret;
170 ret.reserve(32);
171 bool firstnonzero = false;
172 for (size_t i = 0; i < 16; ++i)
173 {
174 const unsigned char b = u.bytes[Endian::e16rev(i)];
175 if (b || firstnonzero || i == 15)
176 {
177 const char bh = static_cast<decltype(bh)>(b >> 4);
178 if (bh || firstnonzero)
179 ret += render_hex_char(bh);
180 ret += render_hex_char(b & 0x0F);
181 firstnonzero = true;
182 }
183 }
184 return ret;
185 }
186
187 static Addr from_ulong(unsigned long ul)
188 {
189 Addr ret;
190 ret.u.u64[Endian::e2(0)] = ul;
191 ret.u.u64[Endian::e2(1)] = 0;
192 return ret;
193 }
194
195 unsigned long to_ulong() const
196 {
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");
201 return ret;
202 }
203
204 static Addr from_long(long ul)
205 {
206 bool neg = false;
207 Addr ret;
208 if (ul < 0)
209 {
210 ul = -(ul + 1);
211 neg = true;
212 }
213 ret.u.u64[Endian::e2(0)] = std::uint64_t(ul);
214 ret.u.u64[Endian::e2(1)] = 0;
215 if (neg)
216 ret.negate();
217 return ret;
218 }
219
220 long to_long() const
221 {
222 bool neg = false;
223 Addr a = *this;
224 if (a.u.u64[Endian::e2(1)])
225 {
226 a.negate();
227 neg = true;
228 }
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;
234 }
235
236 static std::string arpa()
237 {
238 throw ipv6_exception("arpa() not implemented");
239 }
240
241 static Addr from_asio(const openvpn_io::ip::address_v6 &asio_addr)
242 {
243 Addr ret;
244 ipv6addr addr{};
245 addr.asio_bytes = asio_addr.to_bytes();
246 network_to_host_order(&ret.u, &addr);
247 ret.scope_id_ = asio_addr.scope_id();
248 return ret;
249 }
250
251 static Addr from_byte_string(const unsigned char *bytestr)
252 {
253 /* bytestr might not be correctly aligned to an 8 byte boundary
254 * that ipv6addr requires, so use a temporary object that is
255 * properly aligned */
256 Addr ret;
257 ipv6addr src{};
258 std::memcpy(&src, bytestr, sizeof(src));
259 network_to_host_order(&ret.u, &src);
260 return ret;
261 }
262
263 void to_byte_string(unsigned char *bytestr) const
264 {
265 /* bytestr might not be correctly aligned to an 8 byte boundary
266 * that ipv6addr requires, so use a temporary object that is
267 * properly aligned */
268 ipv6addr ret{};
270 std::memcpy(bytestr, &ret, sizeof(ret));
271 }
272
273 static void v4_to_byte_string(unsigned char *bytestr,
274 const std::uint32_t v4addr)
275 {
276 ipv6addr ret{};
277 ret.u32[0] = ret.u32[1] = ret.u32[2] = 0;
278 ret.u32[3] = v4addr;
279
280 std::memcpy(bytestr, &ret, sizeof(ret));
281 }
282
283 static bool byte_string_is_v4(const unsigned char *bytestr)
284 {
285 ipv6addr a{};
286 std::memcpy(&a, bytestr, sizeof(a));
287 return a.u32[0] == 0 && a.u32[1] == 0 && a.u32[2] == 0;
288 }
289
290 static std::uint32_t v4_from_byte_string(const unsigned char *bytestr)
291 {
292 ipv6addr a{};
293 std::memcpy(&a, bytestr, sizeof(a));
294 return a.u32[3];
295 }
296
297 openvpn_io::ip::address_v6 to_asio() const
298 {
299 ipv6addr addr;
300 host_to_network_order(&addr, &u);
301 return openvpn_io::ip::address_v6(addr.asio_bytes, scope_id_);
302 }
303
305 {
306 Addr ret;
307 ret.zero();
308 return ret;
309 }
310
311 static Addr from_one()
312 {
313 Addr ret;
314 ret.one();
315 return ret;
316 }
317
319 {
320 Addr ret;
322 return ret;
323 }
324
325 static Addr netmask_from_prefix_len(const unsigned int prefix_len)
326 {
327 Addr ret;
329 return ret;
330 }
331
333 {
334 const Addr lb = *this - 1;
335 for (size_t i = 4; i-- > 0;)
336 {
337 const std::uint32_t v = lb.u.u32[Endian::e4(i)];
338 if (v)
339 return netmask_from_prefix_len(SIZE - ((static_cast<unsigned int>(i) << 5) + find_last_set(v)));
340 }
341 return from_zero_complement();
342 }
343
344 Addr operator&(const Addr &other) const
345 {
346 Addr ret;
348 ret.u.u64[0] = u.u64[0] & other.u.u64[0];
349 ret.u.u64[1] = u.u64[1] & other.u.u64[1];
350 return ret;
351 }
352
353 Addr operator|(const Addr &other) const
354 {
355 Addr ret;
357 ret.u.u64[0] = u.u64[0] | other.u.u64[0];
358 ret.u.u64[1] = u.u64[1] | other.u.u64[1];
359 return ret;
360 }
361
362 Addr operator+(const long delta) const
363 {
364 Addr ret = *this;
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)]);
369 return ret;
370 }
371
372 Addr operator+(const Addr &other) const
373 {
374 Addr ret = *this;
375 add(ret.u, other.u);
376 return ret;
377 }
378
379 Addr operator-(const long delta) const
380 {
381 return operator+(-delta);
382 }
383
384 Addr operator-(const Addr &other) const
385 {
386 Addr ret = *this;
387 sub(ret.u, other.u);
388 return ret;
389 }
390
391 Addr operator*(const Addr &d) const
392 {
393 Addr m = d;
394 Addr ret = from_zero();
395 for (unsigned int i = 0; i < SIZE; ++i)
396 {
397 if (bit(i))
398 ret += m;
399 m <<= 1;
400 }
401 return ret;
402 }
403
404 Addr operator/(const Addr &d) const
405 {
406 Addr q, r;
407 div(*this, d, q, r);
408 return q;
409 }
410
411 Addr operator%(const Addr &d) const
412 {
413 Addr q, r;
414 div(*this, d, q, r);
415 return r;
416 }
417
418 Addr operator<<(const unsigned int shift) const
419 {
420 Addr ret = *this;
421 shiftl128(ret.u.u64[Endian::e2(0)],
422 ret.u.u64[Endian::e2(1)],
423 shift);
424 return ret;
425 }
426
427 Addr operator>>(const unsigned int shift) const
428 {
429 Addr ret = *this;
430 shiftr128(ret.u.u64[Endian::e2(0)],
431 ret.u.u64[Endian::e2(1)],
432 shift);
433 return ret;
434 }
435
437 {
438 Addr ret;
440 ret.u.u64[0] = ~u.u64[0];
441 ret.u.u64[1] = ~u.u64[1];
442 return ret;
443 }
444
445 // return the network that contains the current address
446 Addr network_addr(const unsigned int prefix_len) const
447 {
448 return *this & netmask_from_prefix_len(prefix_len);
449 }
450
451 bool operator==(const Addr &other) const
452 {
453 return u.u64[0] == other.u.u64[0] && u.u64[1] == other.u.u64[1] && scope_id_ == other.scope_id_;
454 }
455
456 bool operator!=(const Addr &other) const
457 {
458 return !operator==(other);
459 }
460
461
462 bool operator<(const Addr &other) const
463 {
464 return compare(other, std::less<>{});
465 }
466 bool operator>(const Addr &other) const
467 {
468 return compare(other, std::greater<>{});
469 }
470 bool operator<=(const Addr &other) const
471 {
472 return compare(other, std::less_equal<>{});
473 }
474 bool operator>=(const Addr &other) const
475 {
476 return compare(other, std::greater_equal<>{});
477 }
478
479 bool unspecified() const
480 {
481 return all_zeros();
482 }
483
484 bool specified() const
485 {
486 return !unspecified();
487 }
488
489 bool all_zeros() const
490 {
491 return u.u64[0] == 0 && u.u64[1] == 0;
492 }
493
494 bool all_ones() const
495 {
496 return u.u64[0] == ~std::uint64_t(0) && u.u64[1] == ~std::uint64_t(0);
497 }
498
499 bool is_loopback() const // ::1
500 {
501 return u.u64[Endian::e2(1)] == 0 && u.u64[Endian::e2(0)] == 1;
502 }
503
504 bool is_mapped_address() const
505 {
506 return u.u32[Endian::e4(1)] == 0xffff && u.u32[Endian::e4(2)] == 0 && u.u32[Endian::e4(3)] == 0;
507 }
508
509 std::uint32_t get_mapped_ipv4_address() const
510 {
511 return u.u32[Endian::e2(0)];
512 }
513
514 bool bit(unsigned int pos) const
515 {
516 if (pos < 64)
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;
519 }
520
521 // number of network bits in netmask,
522 // throws exception if addr is not a netmask
523 unsigned int prefix_len() const
524 {
525 int idx = -1;
526
527 if (u.u32[Endian::e4(3)] != ~std::uint32_t(0))
528 {
529 if (!u.u32[Endian::e4(0)] && !u.u32[Endian::e4(1)] && !u.u32[Endian::e4(2)])
530 idx = 0;
531 }
532 else if (u.u32[Endian::e4(2)] != ~std::uint32_t(0))
533 {
534 if (!u.u32[Endian::e4(0)] && !u.u32[Endian::e4(1)])
535 idx = 1;
536 }
537 else if (u.u32[Endian::e4(1)] != ~std::uint32_t(0))
538 {
539 if (!u.u32[Endian::e4(0)])
540 idx = 2;
541 }
542 else
543 idx = 3;
544
545 if (idx >= 0)
546 {
547 const int ret = IPv4::Addr::prefix_len_32(u.u32[Endian::e4rev(idx)]);
548 if (ret >= 0)
549 return ret + (idx << 5);
550 }
551 throw ipv6_exception("malformed netmask");
552 }
553
554 // number of host bits in netmask
555 unsigned int host_len() const
556 {
557 return SIZE - prefix_len();
558 }
559
560 // return the number of host addresses contained within netmask
562 {
563 const unsigned int hl = host_len();
564 if (hl < SIZE)
565 {
566 Addr a;
567 a.one();
568 return a << hl;
569 }
570 if (hl == SIZE)
571 return from_zero();
572 throw ipv6_exception("extent overflow");
573 }
574
575 // address size in bits
576 static unsigned int size()
577 {
578 return SIZE;
579 }
580
581 template <typename HASH>
582 void hash(HASH &h) const
583 {
584 h(u.bytes, sizeof(u.bytes));
585 }
586
587#ifdef USE_OPENVPN_HASH
588 std::uint64_t hashval() const
589 {
590 Hash64 h;
591 hash(h);
592 return h.value();
593 }
594#endif
595
596#ifdef OPENVPN_IP_IMMUTABLE
597 private:
598#endif
599
600 void negate()
601 {
602 u.u64[0] = ~u.u64[0];
603 u.u64[1] = ~u.u64[1];
604 }
605
606 void zero()
607 {
608 u.u64[0] = 0;
609 u.u64[1] = 0;
610 }
611
613 {
614 u.u64[0] = ~std::uint64_t(0);
615 u.u64[1] = ~std::uint64_t(0);
616 }
617
618 void one()
619 {
620 u.u64[0] = 1;
621 u.u64[1] = 0;
622 }
623
625 {
626 if (++u.u64[Endian::e2(0)] == 0)
627 ++u.u64[Endian::e2(1)];
628 return *this;
629 }
630
631 Addr &operator+=(const long delta)
632 {
633 *this = *this + delta;
634 return *this;
635 }
636
637 Addr &operator-=(const long delta)
638 {
639 return operator+=(-delta);
640 }
641
642 Addr &operator+=(const Addr &other)
643 {
644 add(u, other.u);
645 return *this;
646 }
647
648 Addr &operator-=(const Addr &other)
649 {
650 sub(u, other.u);
651 return *this;
652 }
653
654 Addr &operator<<=(const unsigned int shift)
655 {
656 shiftl128(u.u64[Endian::e2(0)],
657 u.u64[Endian::e2(1)],
658 shift);
659 return *this;
660 }
661
662 Addr &operator>>=(const unsigned int shift)
663 {
664 shiftr128(u.u64[Endian::e2(0)],
665 u.u64[Endian::e2(1)],
666 shift);
667 return *this;
668 }
669
670 void set_clear_bit(unsigned int pos, bool value)
671 {
672 if (pos < 64)
673 {
674 if (value)
675 u.u64[Endian::e2(0)] |= (std::uint64_t(1) << pos);
676 else
677 u.u64[Endian::e2(0)] &= ~(std::uint64_t(1) << pos);
678 }
679 else
680 {
681 if (value)
682 u.u64[Endian::e2(1)] |= (std::uint64_t(1) << (pos - 64));
683 else
684 u.u64[Endian::e2(1)] &= ~(std::uint64_t(1) << (pos - 64));
685 }
686 }
687
688 void set_bit(unsigned int pos, bool value)
689 {
690 if (value)
691 {
692 if (pos < 64)
693 u.u64[Endian::e2(0)] |= (std::uint64_t(1) << pos);
694 else
695 u.u64[Endian::e2(1)] |= (std::uint64_t(1) << (pos - 64));
696 }
697 }
698
699 static void div(const Addr &numerator, const Addr &denominator, Addr &quotient, Addr &remainder)
700 {
701 if (denominator.all_zeros())
702 throw ipv6_exception("division by 0");
703 quotient = from_zero();
704 remainder = numerator;
705 Addr mask_low = from_zero();
706 Addr mask_high = denominator;
707 for (unsigned int i = 0; i < SIZE; ++i)
708 {
709 mask_low >>= 1;
710 mask_low.set_bit(SIZE - 1, mask_high.bit(0));
711 mask_high >>= 1;
712 if (mask_high.all_zeros() && remainder >= mask_low)
713 {
714 remainder -= mask_low;
715 quotient.set_bit((SIZE - 1) - i, true);
716 }
717 }
718 }
719
720 int scope_id() const
721 {
722 return scope_id_;
723 }
724
725 private:
726 union ipv6addr {
727 std::uint64_t u64[2];
728 std::uint32_t u32[4]; // generally stored in host byte order
729 unsigned char bytes[16];
730 openvpn_io::ip::address_v6::bytes_type asio_bytes;
731 };
732
734 {
735 if (prefix_len > 0)
736 {
737 const unsigned int pl = prefix_len - 1;
738 const std::uint32_t mask = ~((1U << (31 - (pl & 31))) - 1);
739 switch (pl >> 5)
740 {
741 case 0:
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;
746 break;
747 case 1:
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;
752 break;
753 case 2:
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;
758 break;
759 case 3:
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;
764 break;
765 }
766 }
767 else
768 zero();
769 }
770
771 void prefix_len_to_netmask(const unsigned int prefix_len)
772 {
773 if (prefix_len <= SIZE)
775 throw ipv6_exception("bad prefix len");
776 }
777
778 static void host_to_network_order(ipv6addr *dest, const ipv6addr *src)
779 {
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)]);
784 }
785
786 static void network_to_host_order(ipv6addr *dest, const ipv6addr *src)
787 {
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)]);
792 }
793
794
795 static void shiftl128(std::uint64_t &low,
796 std::uint64_t &high,
797 unsigned int shift)
798 {
799 if (shift == 1)
800 {
801 high <<= 1U;
802 if (low & (std::uint64_t(1) << 63U))
803 high |= 1U;
804 low <<= 1U;
805 }
806 else if (shift == 0)
807 {
808 // Nothing to do
809 }
810 else if (shift == 128)
811 {
812 /* shifts everything away */
813 high = low = 0;
814 }
815 else if (shift < 64)
816 {
817 high = (high << shift) | (low >> (64U - shift));
818 low <<= shift;
819 }
820 else if (shift < 128) /* in [64, 127] */
821 {
822 high = low;
823 low = 0;
824 /* Shift is guaranteed to be in [0, 63], so
825 * recursion will not come here again */
826 shiftl128(low, high, shift - 64);
827 }
828 else
829 throw ipv6_exception("l-shift too large");
830 }
831
832 static void shiftr128(std::uint64_t &low,
833 std::uint64_t &high,
834 unsigned int shift)
835 {
836 if (shift == 1)
837 {
838 low >>= 1U;
839 if (high & 1U)
840 low |= (std::uint64_t(1) << 63U);
841 high >>= 1U;
842 }
843 else if (shift == 0)
844 {
845 }
846 else if (shift < 64)
847 {
848 low = (low >> shift) | (high << (64 - shift));
849 high >>= shift;
850 }
851 else if (shift <= 128) // shift in [64, 128]
852 {
853 low = high;
854 high = 0;
855 shiftr128(low, high, shift - 64);
856 }
857 else
858 throw ipv6_exception("r-shift too large");
859 }
860
861 static void add(ipv6addr &dest, const ipv6addr &src)
862 {
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)];
866 // check for overflow of low 64 bits, add carry to high
867 if (dest.u64[Endian::e2(0)] < dorigl)
868 ++dest.u64[Endian::e2(1)];
869 }
870
871 static void sub(ipv6addr &dest, const ipv6addr &src)
872 {
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)]);
877 }
878
879
880 template <typename Comparator>
881 bool compare(const Addr &other, Comparator comp) const
882 {
883
884 if (u.u64[Endian::e2(1)] == other.u.u64[Endian::e2(1)])
885 {
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)]);
888 return comp(scope_id_, other.scope_id_);
889 }
890 return comp(u.u64[Endian::e2(1)], other.u.u64[Endian::e2(1)]);
891 }
892
894 unsigned int scope_id_ = 0;
895};
896
897OPENVPN_OSTREAM(Addr, to_string)
898} // namespace openvpn::IPv6
899
900#ifdef USE_OPENVPN_HASH
902#endif
903
904#endif // OPENVPN_ADDR_IPV6_H
static int prefix_len_32(const std::uint32_t addr)
Definition ipv4.hpp:491
Addr & operator<<=(const unsigned int shift)
Definition ipv6.hpp:654
Addr netmask_from_this_as_extent() const
Definition ipv6.hpp:332
std::string to_hex() const
Definition ipv6.hpp:167
void set_clear_bit(unsigned int pos, bool value)
Definition ipv6.hpp:670
bool unspecified() const
Definition ipv6.hpp:479
static Addr from_sockaddr(const sockaddr_in6 *sa)
Definition ipv6.hpp:79
static void sub(ipv6addr &dest, const ipv6addr &src)
Definition ipv6.hpp:871
bool operator!=(const Addr &other) const
Definition ipv6.hpp:456
Addr network_addr(const unsigned int prefix_len) const
Definition ipv6.hpp:446
Addr operator&(const Addr &other) const
Definition ipv6.hpp:344
unsigned int prefix_len() const
Definition ipv6.hpp:523
static Addr from_one()
Definition ipv6.hpp:311
void set_bit(unsigned int pos, bool value)
Definition ipv6.hpp:688
static constexpr unsigned int SIZE
Definition ipv6.hpp:43
bool operator==(const Addr &other) const
Definition ipv6.hpp:451
static std::string arpa()
Definition ipv6.hpp:236
Addr operator*(const Addr &d) const
Definition ipv6.hpp:391
Addr operator+(const Addr &other) const
Definition ipv6.hpp:372
static Addr from_byte_string(const unsigned char *bytestr)
Definition ipv6.hpp:251
static Addr from_long(long ul)
Definition ipv6.hpp:204
bool bit(unsigned int pos) const
Definition ipv6.hpp:514
static Addr from_in6_addr(const in6_addr *in6)
Definition ipv6.hpp:60
static Addr from_string(const std::string &ipstr)
Definition ipv6.hpp:110
static bool byte_string_is_v4(const unsigned char *bytestr)
Definition ipv6.hpp:283
unsigned int scope_id_
Definition ipv6.hpp:894
Addr & operator-=(const long delta)
Definition ipv6.hpp:637
bool compare(const Addr &other, Comparator comp) const
Definition ipv6.hpp:881
Addr & operator>>=(const unsigned int shift)
Definition ipv6.hpp:662
void prefix_len_to_netmask(const unsigned int prefix_len)
Definition ipv6.hpp:771
bool specified() const
Definition ipv6.hpp:484
bool is_mapped_address() const
Definition ipv6.hpp:504
static Addr from_addr(const Addr &addr)
Definition ipv6.hpp:55
static void shiftl128(std::uint64_t &low, std::uint64_t &high, unsigned int shift)
Definition ipv6.hpp:795
static constexpr int ip_version()
Definition ipv6.hpp:45
static Addr from_hex(const std::string &s)
Definition ipv6.hpp:139
Addr operator+(const long delta) const
Definition ipv6.hpp:362
static void host_to_network_order(ipv6addr *dest, const ipv6addr *src)
Definition ipv6.hpp:778
Addr operator%(const Addr &d) const
Definition ipv6.hpp:411
static Addr from_zero_complement()
Definition ipv6.hpp:318
Addr operator|(const Addr &other) const
Definition ipv6.hpp:353
Addr operator-(const long delta) const
Definition ipv6.hpp:379
Addr operator/(const Addr &d) const
Definition ipv6.hpp:404
static Addr netmask_from_prefix_len(const unsigned int prefix_len)
Definition ipv6.hpp:325
static void v4_to_byte_string(unsigned char *bytestr, const std::uint32_t v4addr)
Definition ipv6.hpp:273
bool all_zeros() const
Definition ipv6.hpp:489
void to_byte_string(unsigned char *bytestr) const
Definition ipv6.hpp:263
bool operator<=(const Addr &other) const
Definition ipv6.hpp:470
unsigned int host_len() const
Definition ipv6.hpp:555
static std::uint32_t v4_from_byte_string(const unsigned char *bytestr)
Definition ipv6.hpp:290
Addr & operator+=(const Addr &other)
Definition ipv6.hpp:642
void hash(HASH &h) const
Definition ipv6.hpp:582
long to_long() const
Definition ipv6.hpp:220
static Addr from_zero()
Definition ipv6.hpp:304
bool operator>(const Addr &other) const
Definition ipv6.hpp:466
openvpn_io::ip::address_v6 to_asio() const
Definition ipv6.hpp:297
static constexpr bool defined()
Definition ipv6.hpp:50
static void shiftr128(std::uint64_t &low, std::uint64_t &high, unsigned int shift)
Definition ipv6.hpp:832
static Addr from_asio(const openvpn_io::ip::address_v6 &asio_addr)
Definition ipv6.hpp:241
static void div(const Addr &numerator, const Addr &denominator, Addr &quotient, Addr &remainder)
Definition ipv6.hpp:699
std::uint32_t get_mapped_ipv4_address() const
Definition ipv6.hpp:509
Addr operator-(const Addr &other) const
Definition ipv6.hpp:384
int scope_id() const
Definition ipv6.hpp:720
static void network_to_host_order(ipv6addr *dest, const ipv6addr *src)
Definition ipv6.hpp:786
unsigned long to_ulong() const
Definition ipv6.hpp:195
Addr operator>>(const unsigned int shift) const
Definition ipv6.hpp:427
in6_addr to_in6_addr() const
Definition ipv6.hpp:72
void prefix_len_to_netmask_unchecked(const unsigned int prefix_len)
Definition ipv6.hpp:733
static void add(ipv6addr &dest, const ipv6addr &src)
Definition ipv6.hpp:861
bool is_loopback() const
Definition ipv6.hpp:499
std::string to_string() const
Definition ipv6.hpp:128
static Addr from_string(const std::string &ipstr, const TITLE &title)
Definition ipv6.hpp:101
Addr & operator+=(const long delta)
Definition ipv6.hpp:631
Addr & operator-=(const Addr &other)
Definition ipv6.hpp:648
Addr operator~() const
Definition ipv6.hpp:436
static unsigned int size()
Definition ipv6.hpp:576
bool operator>=(const Addr &other) const
Definition ipv6.hpp:474
Addr operator<<(const unsigned int shift) const
Definition ipv6.hpp:418
bool operator<(const Addr &other) const
Definition ipv6.hpp:462
bool all_ones() const
Definition ipv6.hpp:494
void zero_complement()
Definition ipv6.hpp:612
sockaddr_in6 to_sockaddr(const unsigned short port=0) const
Definition ipv6.hpp:84
Addr extent_from_netmask() const
Definition ipv6.hpp:561
static Addr from_ulong(unsigned long ul)
Definition ipv6.hpp:187
Addr & operator++()
Definition ipv6.hpp:624
#define OPENVPN_EXCEPTION(C)
Definition exception.hpp:99
#define OPENVPN_HASH_METHOD(T, meth)
Definition hash.hpp:30
std::string format_error(const std::string &ipstr, const TITLE &title, const char *ipver, const std::string &message)
Definition iperr.hpp:29
std::string to_lower_copy(const std::string &str)
Definition string.hpp:540
int parse_hex_char(const int c)
Definition hexstr.hpp:65
char render_hex_char(const int c, const bool caps=false)
Definition hexstr.hpp:42
#define OPENVPN_OSTREAM(TYPE, METH)
Definition ostream.hpp:21
proxy_host_port port
std::string ret
openvpn_io::ip::address_v6::bytes_type asio_bytes
Definition ipv6.hpp:730
std::uint32_t u32[4]
Definition ipv6.hpp:728
unsigned char bytes[16]
Definition ipv6.hpp:729
std::uint64_t u64[2]
Definition ipv6.hpp:727