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